Метапрограммирование Ruby с помощью MongoMapper

Я пытаюсь динамически добавлять ключи в документы MongoMapper.

def build(attrs={})
  doc = self.new
  apply_scope(doc)
  doc.set_up_keys!
  doc.attributes = attrs
  doc
end

def set_up_keys!
  return unless form

  form.fields.each do |f|
    next if self.keys.include?(f.underscored_name)

    self.class.send(:key, f.underscored_name, f.keys['default'].type, :required => f.required, :default => f.default)
  end
end

Рассматриваемый код доступен здесь и здесь.

form — родственная модель. Я хочу создать ключи для текущей модели (я) на основе того, что есть у form#fields.

Проблема в том, что если я создам две модели, у них обоих будут одинаковые ключи от обеих моделей.

self.class.send(:key...) добавляет ключи к модели.

Почему они добавляются в обе модели?

Это потому, что метод вызывается в контексте класса?

Как я могу повлиять только на отдельный экземпляр?


person jordelver    schedule 18.02.2014    source источник
comment
Не отправляйте его в класс.   -  person Dave Newton    schedule 18.02.2014
comment
Но разве #key не является методом класса? Не уверен, что следую :(   -  person jordelver    schedule 18.02.2014


Ответы (1)


Mongomapper определяет модель по ее классу. Все экземпляры этого класса совместно используют ключи модели. Если вы хотите создать модель «на лету», вам, вероятно, потребуется динамически создать класс и добавить к нему ключи:

def build(attrs={})
  c = Class.new(self.class)
  doc = c.new
  apply_scope(doc)
  doc.set_up_keys!
  doc.attributes = attrs
  doc
end
person Uri Agassi    schedule 18.02.2014
comment
Спасибо! Мне пришлось немного изменить его на c = Class.new(klass.new.class), но в остальном он отлично работает. Я изменил исходный код, чтобы использовать #send на self.class вместо class_eval из-за другой проблемы. Вот тогда и возникла эта новая проблема. Влияет ли class_eval только на класс экземпляра (одноэлементный класс/собственный класс), а не на класс всех классов? - person jordelver; 18.02.2014
comment
AFAIK class_eval - это метод класса, а не метод экземпляра, поэтому вопрос кажется спорным - он влияет на вызываемый класс. - person Uri Agassi; 18.02.2014