2009-09-28 9 views

Répondre

7

Dans votre cas, il est préférable d'utiliser instance_eval

"Test".instance_eval{chop!.chop!} #=> "Te" 

Et pour votre code:

my_xml_element.instance_eval{parent.next_sibling.next_sibling} 
5

euh, ce n'est pas vraiment ce qu'il demandait si je comprends sa question corr ectly. Je veux dire envoyer prend une chaîne ou un symbole comme argument, et votre solution ne le fait pas. Je ne pense pas qu'il existe une méthode intégrée qui fera ce que vous voulez, mais j'ai fouetté une méthode qui le fera, avec un test.

require 'test/unit' 

class Example 
    def multi_send(str) 
    str.split('.').inject(self){|klass, method| klass.send(method) } 
    end 
end 

class MyTest < Test::Unit::TestCase 
    def test_multi_send 
    a = Example.new 
    methods = "class.to_s.downcase.chop!" 
    assert a.multi_send(methods) == 'exampl' 
    end 
end 
1

Je pense que la question est que vous avez spécifiquement une série de méthodes définies comme une chaîne, et que vous voulez invoquer cela sur un objet, non?

class Object 
    def call_method_chain(method_chain) 
    return self if method_chain.empty? 
    method_chain.split('.').inject(self){|o,m| o.send(m.intern)} 
    end 
end 

>> User.first.profile.address.state.name 
=> "Virginia" 
>> User.first.call_method_chain("profile.address.state.name") 
=> "Virginia" 
+0

Désolé, cela ne fonctionnera pas en dehors du contexte de Rails car Object # try n'est pas défini. – jsharpe

+0

Modifier: Fonctionne sans Rails maintenant. – jsharpe

+0

pourquoi n'avais-je jamais pensé à '.inject (self)' avant ??? Je vous remercie! –

4

En fait, Khelll avait presque raison. Utilisez ceci:

methods_chain = "parent.next_sibling.next_sibling" 
result = my_xml_element.instance_eval(eval methods_chain) 

Ce code est jusqu'à 20 fois plus rapide que d'utiliser split() et vous permet de passer des méthodes de la chaîne avec args, comme ceci:

methods = "power!(2).div(57).+(12).to_f" 
42.instance_eval { eval methods } 
+0

C'est un truc puissant. Merci. –

0

Le problème avec la réponse de Alfuken base sur eval est

A) eval est assez dangereux, bien que rapide

B) si vous avez un point supplémentaire (consécutive) pour l'invocation de méthode comme celle

"example".instance_eval{eval "chop!..chop!"}.class 
=> "examp".."examp" 

"example".instance_eval {eval "chop!..chop!"}.class 
=> Range # this is not what is desired 
+1

Alors, qu'est-ce que vous essayez de montrer ici, l'espace supplémentaire entre le 'instance_val' et le' {'bracket? Je suis confus. –

Questions connexes