Peter
Peter

Reputation: 132247

Changing default Ruby arguments

I want to change the default arguments passed to a Ruby function. For example, instead of each time writing

[1,2,3].do_stuff(:option => ' my option ')

I want to modify the defaults so that I can write

[1,2,3].do_stuff

What is the simplest, cleanest, most Ruby-like way of changing default parameters?

Upvotes: 3

Views: 336

Answers (3)

David Miani
David Miani

Reputation: 14668

(moved from your original question)

I assume you are talking about a method Array#do_stuff that already exists, but you want to modify it slightly (in your case by changing a default parameter).

A post here gives a nice way of doing it. It doesn't suffer from the same problems as the alias technique, as there isn't a leftover "old" method.

Here how you could use that technique with your example problem (tested with ruby 1.9)

class Array
  old_do_stuff = instance_method(:do_stuff)
  define_method(:do_stuff) { |options = {}|

    options[:option] ||= " option "
    old_do_stuff.bind(self).call(options)
  }
end

You might also want read up on UnboundMethod if the above code is confusing. Note that old_do_stuff goes out of scope after the end statement, so it isn't a problem for future uses of Array.

Upvotes: 1

Swanand
Swanand

Reputation: 12426

>> [1, 2, 3].do_stuff
=> Result I get
>> [1, 2, 3].do_stuff :an_option => a_value
=> Result I really want, but don't want to specify the argument

I like to use super for this. It allows us to add some functionality to the method apart from just changing default arguments:

class Array
  def do_stuff(options = {})
     # Verify if caller has not passed the option
     options[:argument_i_want_to_change] = default_value_i_want unless options.has_key? :argument_i_want_to_change
     # call super
     super
  end
end

Result:

>> [1, 2, 3].do_stuff
=> Result that I really want

UPDATE: Removed reverse_merge! dependency. (Now looking for a better alternatives to using []= method)

Upvotes: 2

Benjamin Oakes
Benjamin Oakes

Reputation: 12782

Are you wanting a solution for code you didn't write yourself? There are two options I'm aware of.

Code you wrote yourself:

def some_method_you_wrote(options)

becomes:

def some_method_you_wrote(options = { :option1 => 'value' })

(Swanand's answer is nice too)

For code you didn't write, look into aliasing methods. (Rails provides something called alias_method_chain for this purpose, IIRC.)

Upvotes: 0

Related Questions