2010-01-11 5 views
0

Man, je peler les couches de l'oignon aujourd'hui, de toute façon ici le les environs de codeRuby class_eval et donner

class MyClass 
    def initialize(dynamic_methods) 
    @arr = Array.new(dynamic_methods) 
    @arr.each { |m| 
     self.class.class_eval do 
     define_method(m) do 
      "<#{yield self if block_given?}>" 
     end 
     end 
    } 
    end 
end 

tmp = MyClass.new ['method1', 'method2', 'method3'] 
tmp.method1 do |t| 
    "here" 
end 

Mon problème est que je suis en train d'accéder à « ici » au define_method (m) lorsque la méthode est en cours d'exécution, pas lorsqu'elle est créée. L'instruction actuelle "< # {yield self si block_given?}>" Ne me donne pas ça. Et au cas où vous vous poseriez la question, je dois garder cette partie du code telle quelle mais je peux apporter tous les changements que je souhaite à MyClass.

tmp = MyClass.new ['method1', 'method2', 'method3'] 
tmp.method1 do |t| 
    "here" 
end 

Quelqu'un peut-il aider avec la syntaxe? Merci d'avance pour votre aide.

MISE À JOUR: Voir ci-dessous pour ma réponse.

Répondre

1

Essayez de remplacer

define_method(m) do 
    "<#{yield self if block_given?}>" 
end 

avec:

define_method(m) do |&block| 
    "<#{block.call if block}>" 
end 

Cela devrait fonctionner pour 1.8.7 et plus. Vous pouvez aussi utiliser module_eval:

self.class.module_eval %Q{ 
    def #{m}(&block) 
    "<\#{block.call if block}>" 
    end 
} 
+0

Cela fonctionne avec 1.8.7, mais peut ne pas fonctionner avec les versions antérieures. – mxgrn

+0

Malheureusement, vous avez raison, je suis sur 1.8.6 et il barfed (erreur de syntaxe) sur & block. – Bob

+0

Dans ce cas, vous pouvez céder à 'module_eval', qui prend une chaîne: Q module_eval de% {def # {m} (et bloc) "<# {block.call si le bloc}>" end} – mxgrn

0

Avec beaucoup de commentaires de Sergei et certains bricoler moi-même, je parviens à le faire fonctionner

class MyClass 
    def initialize(dynamic_methods) 
    @arr = Array.new(dynamic_methods) 
    @arr.each { |m| 
     self.class.module_eval %Q{ 
     def #{m}(&block) 
      yield(self) if block_given? 
     end 
     end 
    } 
    end 
end 

tmp = MyClass.new ['method1', 'method2', 'method3'] 
tmp.method1 do |t| 
    "here" 
end 

Comme vous pouvez le dire, il y a quelques modifications mineures aux suggestions de Sergei, alors merci pour votre aide Sergei.

Questions connexes