2009-09-28 9 views

Respuesta

7

En su caso es mejor utilizar instance_eval

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

Y para su código:

my_xml_element.instance_eval{parent.next_sibling.next_sibling} 
5

uh, eso no es realmente lo que estaba pidiendo si estoy entendiendo su pregunta corr ectly. Quiero decir que enviar toma una cadena o un símbolo como una arg, y tu solución no. No creo que haya un método integrado que haga lo que quieras, pero aumenté un método que lo hará, con una prueba.

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

Creo que la cuestión es que usted tiene específicamente una serie de métodos definidos como una cadena, y que desea invocar que en algún objeto, ¿verdad?

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

Lo sentimos, esto no funcionará realmente fuera del contexto de Rails ya que Object # try no está definido. – jsharpe

+0

Editar: Funciona sin carriles ahora. – jsharpe

+0

¿Por qué nunca había pensado en '.inject (self)' antes ??? ¡gracias! –

4

En realidad, Khelll era casi correcto. Utilice esta:

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

Este código es hasta 20 veces más rápido que el uso de split() y le permite pasar los métodos de cadena con argumentos, así:

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

Esto es algo poderoso. Gracias. –

0

El problema con la respuesta de Alfuken basada en eval es

a) eval es bastante insegura aunque rápida

B) si tiene un punto adicional (consecutivos) para la invocación de método como este

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

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

Entonces, ¿qué intenta mostrar aquí, el espacio extra entre 'instance_val' y' {'bracket? Estoy confundido. –

Cuestiones relacionadas