Ruby:如何将多个方法调用与“send”链接在一起

时间:2010-11-04 17:28:14

标签: ruby metaprogramming

必须有一种内置的方法,对吗?

class Object
  def send_chain(arr)
    o=self
    arr.each{|a| o=o.send(a) }
    return o
  end
end

4 个答案:

答案 0 :(得分:57)

我刚碰过这个,它真的很想注入:

def send_chain(arr)
  arr.inject(self) {|o, a| o.send(a) }
end

答案 1 :(得分:6)

不,不是内置方式来执行此操作。你所做的简单而简洁,更不用说危险了。使用时要小心。

另一个想法是,这可以扩展到接受参数:

class Object
  def send_chain(*args)
    o=self
    args.each do |arg|
      case arg
      when Symbol, String
        o = o.send arg # send single symbol or string without arguments
      when Array
        o = o.send *arg # smash the inner array into method name + arguments
      else
        raise ArgumentError
      end
    end
    return o
  end
end

这可以让你在一个数组中传递一个带有参数的方法名,比如;

test = MyObject.new
test.send_chain :a_method, [:a_method_with_args, an_argument, another_argument], :another_method

答案 2 :(得分:4)

根据以前的答案,如果您需要将参数传递给每个方法,可以使用:

def send_chain(arr)
  Array(arr).inject(self) { |o, a| o.send(*a) }
end

然后您可以使用以下方法:

arr = [:to_i, [:+, 4], :to_s, [:*, 3]]
'1'.send_chain(arr) # => "555"

此方法也接受单个参数。

答案 3 :(得分:0)

如何在不污染Object类的情况下实现这种多功能解决方案:

def chain_try(arr)
  [arr].flatten.inject(self_or_instance, :try)
end

def chain_send(arr)
  [arr].flatten.inject(self_or_instance, :send)
end

通过这种方式,可以同时使用SymbolStringArray以及两者的混合。?

用法示例:

  • chain_send([:method1, 'method2', :method3])
  • chain_send(:one_method)
  • chain_send('one_method')