Ruby Methods and Optional parameters
If you want to default the values in your options hash, you want to merge the defaults in your function. If you put the defaults in the default parameter itself, it'll be over-written:
def my_info(name, options = {})
options.reverse_merge!(age: 27, weight: 160, city: "New York")
...
end
The problem is the default value of options
is the entire Hash
in the second version you posted. So, the default value, the entire Hash
, gets overridden. That's why passing nothing works, because this activates the default value which is the Hash
and entering all of them also works, because it is overwriting the default value with a Hash
of identical keys.
I highly suggest using an Array
to capture all additional objects that are at the end of your method call.
def my_info(name, *args)
options = args.extract_options!
age = options[:age] || 27
end
I learned this trick from reading through the source for Rails. However, note that this only works if you include ActiveSupport. Or, if you don't want the overhead of the entire ActiveSupport gem, just use the two methods added to Hash
and Array
that make this possible.
rails / activesupport / lib / active_support / core_ext / array / extract_options.rb
So when you call your method, call it much like you would any other Rails helper method with additional options.
my_info "Ned Stark", "Winter is coming", :city => "Winterfell"
The way optional arguments work in ruby is that you specify an equal sign, and if no argument is passed then what you specified is used. So, if no second argument is passed in the second example, then
{age: 27, weight: 160, city: "New York"}
is used. If you do use the hash syntax after the first argument, then that exact hash is passed.
The best you can do is
def my_info2(name, options = {})
options = {age: 27, weight: 160, city: "New York"}.merge(options)
...