简体   繁体   中英

How do you pass self to class_eval in ruby?

I'm working on a metaprogramming task, where I'm trying to use a single method to define a polymorphic association in the calling class, while also defining the association in the target class. I need to pass in the name of the calling class to get the association right. Here's a snippet that should get the idea across:


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

class JoinModel < 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

I'd like to eliminate the klass= line, but don't know how else to pass a reference to self from the calling class into class_eval .

any suggestions?

The string parameters will be interpreted in the current context, so you're free to call self.name there, or name directly:

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

If instead of doing an eval on a string you were using a block, note that class_exec is a variation on class_eval that allows you to pass parameters naturally. So:

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

It is new to 1.8.7, so you'll need to require 'backports/1.8.7' if in 1.8.6.

Note: I'm assuming you need to eval at all, because in your particular example, you can call that method directly, no?

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM