web-dev-qa-db-ja.com

Ruby:「送信」と一緒に複数のメソッド呼び出しをチェーンする方法

これを行うには、組み込みの方法が必要ですよね?

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

私はこれに出くわしました、そしてそれは本当に注入を懇願します:

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

いいえ、ありますそうではありませんこれを行うための組み込みの方法。あなたがしたことは、危険なことは言うまでもなく、十分に単純で簡潔です。ご使用の際はご注意ください。

別の考えでは、これを拡張して引数も受け入れることができます。

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
6
edgerunner

以前の回答に基づいて、各メソッドに引数を渡す必要がある場合は、次を使用できます。

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"

このメソッドは、単一の引数も受け入れます。

5
dgilperez

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
_

このようにして、SymbolString、またはArrayを取り、両方を均等に組み合わせることができます。

使用例:

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

0