Как вы передаете себя в class_eval в ruby? - PullRequest
2 голосов
/ 09 апреля 2010

Я работаю над задачей метапрограммирования, в которой я пытаюсь использовать один метод для определения полиморфной ассоциации в вызывающем классе, а также определения ассоциации в целевом классе.Мне нужно передать имя вызывающего класса, чтобы получить правильную ассоциацию.Вот фрагмент кода, который должен донести идею:


class SomeClass &lt ActiveRecord::Base
    has_many :join_models, :dependent=>:destroy
end

class JoinModel &lt ActiveRecord::Base
  belongs_to :some_class
  belongs_to :entity, :polymorphic=>true
end

module Foo
 module ClassMethods
   def acts_as_entity
      has_many :join_models,  :as=>:entity, :dependent=>:destroy
      has_many :some_classes,  :through=>:join_models

      klass = self.name.tableize
      SomeClass.class_eval "has_many :#{klass}, :through=>:join_models"
   end
  end
end

Я хотел бы исключить строку klass=, но не знаю, как еще передать ссылку на self из вызывающего классав class_eval.

есть предложения?

1 Ответ

5 голосов
/ 09 апреля 2010

Параметры строки будут интерпретироваться в текущем контексте, поэтому вы можете позвонить туда self.name или name напрямую:

SomeClass.class_eval "has_many :#{name.tableize}, :through=>:join_models"

Если вместо выполнения оценки для строки, которую вы использовали, обратите внимание, что class_exec - это вариант class_eval, который позволяет вам передавать параметры естественным образом. Итак:

SomeClass.class_exec(name.tableize.to_sym) do |klass|
  has_many klass, :through=>:join_models
end

Это новое для 1.8.7, поэтому вам нужно require 'backports/1.8.7', если в 1.8.6.

Примечание: я предполагаю, что вам вообще нужно eval, потому что в вашем конкретном примере вы можете вызвать этот метод напрямую, нет?

SomeClass.has_many name.tableize.to_sym, :through=>:join_models
...