Ruby: Как связать несколько вызовов методов вместе с «send» - PullRequest
30 голосов
/ 04 ноября 2010

Должен быть встроенный способ сделать это, верно?

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

Ответы [ 3 ]

58 голосов
/ 22 августа 2012

Я только что наткнулся на это, и это действительно требует инъекции:

def send_chain(arr)
  arr.inject(self) {|o, a| o.send(a) }
end
6 голосов
/ 04 ноября 2010

Нет, не встроенный способ сделать это. То, что вы сделали, достаточно просто и кратко, не говоря уже об опасности. Будьте осторожны при использовании.

С другой стороны, это можно расширить и на аргументы:

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
5 голосов
/ 02 марта 2016

Основываясь на предыдущих ответах, если вам нужно передать аргументы каждому методу, вы можете использовать это:

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"

Этот метод также принимает одиночные аргументы.

...