2009-09-28 8 views

risposta

7

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} 
5

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 
1

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" 
+0

Spiacente, questo in realtà non funziona fuori dal contesto di Rails poiché Object # try non è definito. – jsharpe

+0

Modifica: funziona senza rotaie ora. – jsharpe

+0

perché non avevo mai pensato a '.inject (self)' prima ??? grazie! –

4

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 } 
+0

Questa è roba potente. Grazie. –

0

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 
+1

Quindi, cosa stai cercando di mostrare qui, lo spazio extra tra 'instance_val' e' {'parentesi? Non ho capito bene. –

Problemi correlati