Ruby:如何评估每个send命令的多个方法?

时间:2009-09-28 01:49:56

标签: ruby metaprogramming

假设我有一个XML :: Element ...我想做类似的事情:

my_xml_element.send( “parent.next_sibling.next_sibling”)

5 个答案:

答案 0 :(得分:7)

在您的情况下,最好使用instance_eval

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

代码:

my_xml_element.instance_eval{parent.next_sibling.next_sibling}

答案 1 :(得分:5)

呃,如果我正确地理解他的问题,那并不是他要求的。我的意思是发送一个字符串或一个符号作为arg,你的解决方案没有。我不认为有一个内置的方法可以做你想要的,但我用一个测试掀起了一个方法。

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

答案 2 :(得分:4)

实际上,Khelll几乎是对的。 使用此:

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

此代码比使用split()快20倍,并允许您使用args传递链式方法,如下所示:

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

答案 3 :(得分:1)

我认为问题是你明确地将一系列方法定义为字符串,并且你想在某个对象上调用它,对吗?

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"

答案 4 :(得分:0)

Alfuken基于eval的回答问题是

A)虽然快速

,但eval非常不安全

B)如果您有一个额外的(连续的)点,用于方法调用,如

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

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