2010-04-09 3 views
2

Je travaille sur une tâche de métaprogrammation, où j'essaie d'utiliser une méthode unique pour définir une association polymorphique dans la classe appelante, tout en définissant l'association dans la classe cible. Je dois passer au nom de la classe appelante pour que l'association soit correcte. Voici un extrait qui devrait faire passer l'idée:Comment passez-vous self à class_eval dans ruby?


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 

Je voudrais éliminer la ligne klass=, mais je ne sais pas comment passer une référence à self de la classe en appelant class_eval.

des suggestions?

Répondre

5

Les paramètres de chaîne seront interprétés dans le contexte actuel, de sorte que vous êtes libre d'appeler self.name là, ou name directement:

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

Si au lieu de faire un eval sur une chaîne que vous utilisiez un bloc , notez que class_exec est une variation sur class_eval qui vous permet de transmettre des paramètres naturellement. Alors:

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

Il est nouveau à 1.8.7, vous aurez donc besoin de require 'backports/1.8.7' si 1.8.6.

Remarque: Je suppose que vous avez besoin d'effectuer une évaluation, car dans votre exemple, vous pouvez appeler cette méthode directement, non?

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

Bonne réponse, j'ai appris quelques nouvelles astuces - merci. Votre "Note" était la meilleure solution - j'avais oublié d'appeler SomeClass.has_many, mais connaître class_exec est également utile. – klochner

Questions connexes