【问题标题】:Ruby: How to evalulate multiple methods per send command?Ruby:如何评估每个发送命令的多个方法?
【发布时间】:2009-09-28 01:49:56
【问题描述】:

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

my_xml_element.send("parent.next_sibling.next_sibling")

【问题讨论】:

    标签: ruby metaprogramming


    【解决方案1】:

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

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

    对于您的代码:

    my_xml_element.instance_eval{parent.next_sibling.next_sibling}
    

    【讨论】:

      【解决方案2】:

      实际上,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】:

      呃,如果我正确理解他的问题,那并不是他真正想要的。我的意思是 send 将字符串或符号作为参数,而您的解决方案没有。我认为没有内置方法可以满足您的需求,但我通过测试创建了一种方法。

      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
      

      【讨论】:

        【解决方案4】:

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

        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"
        

        【讨论】:

        • 抱歉,这实际上在 Rails 的上下文之外无法工作,因为没有定义 Object#try。
        【解决方案5】:

        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
        

        【讨论】:

        • 那么,您想在这里显示什么,instance_val{ 括号之间的额外空格?我很困惑。
        猜你喜欢
        • 2013-04-09
        • 2016-05-12
        • 1970-01-01
        • 2015-03-19
        • 1970-01-01
        • 2018-04-27
        • 2011-10-05
        • 1970-01-01
        • 2021-06-07
        相关资源
        最近更新 更多