Search code examples
rubyinstance-methods

Ruby programmatically calling method, with variable number of args


I am trying to do something similar to this:

def foo(mode= :serial)

  if (mode == :serial) then
    self.send(:bar, "one_type")
  else
    self.send(:bar,"second_type",:T5)
  end
end

I can obviously type this out like this.

But I've recently tried expanding it to include a second function like this:

def foo(mode= :serial)

  if (mode == :serial) then
    self.send(:bar, "one_type")
    self.send(:foobar, "one_type",20)
  else
    self.send(:bar,"second_type",:T5)
    self.send(:foobar, "one_type",20,:T5)
  end
end

I can still continue as it is, but I thought to myself, there's a pattern here, I should abstract the arguments away into another layer and make this simpler.

So what I wanted to do was something like this:

arg_arr   = [:bar, "one_type"]
arg_arr_2 = [:foobar, "one_type", 20]
if (mode == :serial) then
  self.send(arg_arr)
  self.send(arg_arr_2)
else
  arg_arr << :T5
  arg_arr2 << :T5
  self.send(arg_arr)
  self.send(arg_arr2 )
end

I tried some other ideas involving .each, .inspect, but nothing that would work (the usual error was can't convert array into string, which I'm guessing refers to the fact that it treats the array as the entire function name). I can do it if I explicitly say "use array elements[0] , [1] etc, but that just seems wasteful.

Is there a way to achieve this without writing code that is hardcoded to the number of arguments?


Solution

  • Try this

    def foo(a, b)
      puts a
      puts b
    end
    
    array = ['bar', 'qux']
    send(:foo, *array) # using send
    foo(*array) # using the method name
    

    Both print

    bar
    qux
    

    The splat operator * packs or unpacks an array.