Diciamo che ho un XML :: elemento ... io voglio fare qualcosa di simile:Ruby: come valutare più metodi per comando di invio?
my_xml_element.send ("parent.next_sibling.next_sibling")
Diciamo che ho un XML :: elemento ... io voglio fare qualcosa di simile:Ruby: come valutare più metodi per comando di invio?
my_xml_element.send ("parent.next_sibling.next_sibling")
Nel tuo caso è meglio usare instance_eval
"Test".instance_eval{chop!.chop!} #=> "Te"
E per il vostro codice:
my_xml_element.instance_eval{parent.next_sibling.next_sibling}
uh, che non è proprio quello che stava chiedendo se sto capire la sua domanda corr ectly. Voglio dire, send prende una stringa o un simbolo come arg, e la tua soluzione no. Non penso che ci sia un metodo integrato che farà ciò che vuoi, ma ho montato un metodo che, con 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
Penso che la domanda è che avete specificamente una serie di metodi definiti come una stringa, e si vuole invocare che su qualche oggetto, giusto?
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"
In realtà, Khelll aveva quasi ragione. Utilizzare questa:
methods_chain = "parent.next_sibling.next_sibling"
result = my_xml_element.instance_eval(eval methods_chain)
Questo codice è fino a 20 volte più veloce rispetto all'utilizzo di split() e consente di passare metodi catena con args, come questo:
methods = "power!(2).div(57).+(12).to_f"
42.instance_eval { eval methods }
Questa è roba potente. Grazie. –
Il problema con la risposta di Alfuken base su eval è
a) eval è piuttosto pericoloso anche se veloce
B) se si dispone di un() dot consecutiva extra per chiamata di metodo come questo
"example".instance_eval{eval "chop!..chop!"}.class
=> "examp".."examp"
"example".instance_eval {eval "chop!..chop!"}.class
=> Range # this is not what is desired
Quindi, cosa stai cercando di mostrare qui, lo spazio extra tra 'instance_val' e' {'parentesi? Non ho capito bene. –
Spiacente, questo in realtà non funziona fuori dal contesto di Rails poiché Object # try non è definito. – jsharpe
Modifica: funziona senza rotaie ora. – jsharpe
perché non avevo mai pensato a '.inject (self)' prima ??? grazie! –