Disons que j'ai un XML :: Element ... Je veux faire quelque chose comme:Ruby: Comment évaluer plusieurs méthodes par commande d'envoi?
my_xml_element.send ("parent.next_sibling.next_sibling")
Disons que j'ai un XML :: Element ... Je veux faire quelque chose comme:Ruby: Comment évaluer plusieurs méthodes par commande d'envoi?
my_xml_element.send ("parent.next_sibling.next_sibling")
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}
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
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"
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 }
C'est un truc puissant. Merci. –
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
Alors, qu'est-ce que vous essayez de montrer ici, l'espace supplémentaire entre le 'instance_val' et le' {'bracket? Je suis confus. –
Désolé, cela ne fonctionnera pas en dehors du contexte de Rails car Object # try n'est pas défini. – jsharpe
Modifier: Fonctionne sans Rails maintenant. – jsharpe
pourquoi n'avais-je jamais pensé à '.inject (self)' avant ??? Je vous remercie! –