davidhu
davidhu

Reputation: 10434

send method: choose when to pass arguments

Say I have a method that takes in a string and an options hash. The options hash has method names as keys, and boolean / values as values.

some_method("foo", upcase: true, times: 5)

What this method should do is take the string, and run certain methods on the string based on the options hash, in this case, it should make the string upcase, then multiple it by 5. We get FOOFOOFOOFOOFOO as the output.

The problem I am having is when I use the send method, some of the methods from the options hash require arguments (such as *, and some do not (such as 'upcase').

Here is what I have so far.

def method(string, options = {})
  options.each do |method_name, arg|
    method_name = :* if method_name == :times
    mod_string = mod_string.send(method_name, arg)
  end
end

I get an error as expected

wrong number of arguments (given 1, expected 0)

(repl):9:in `upcase'

So, my question is: is there a way to only send the argument when there is an argument?

The only thing I came up with is use a if statement to check for boolean values

  options.each do |method_name, arg|
    method_name = :* if method_name == :times
    if arg == true
      mod_string = mod_string.send(method_name)
    elsif !(!!arg == arg)
      mod_string = mod_string.send(method_name, arg)
    end
  end

I just want to see if there is a better way.

Upvotes: 0

Views: 325

Answers (1)

Amadan
Amadan

Reputation: 198314

"When a method has one required argument, call it":

method = mod_string.method(method_name)
arity = method.arity
case arity
when 1, -1
  method.call(arg)
when 0
  method.call
else
  raise "Method requires #{arity} arguments"
end

A probably better way would be to restructure your hash, and give it exactly the arguments you want to pass as an array:

some_method("foo", upcase: [], times: [5])

then you can simply mod_string.send(method_name, *arg).

Upvotes: 1

Related Questions