Reputation: 10394
Given that I have a hash of opts with possibly missing keys, what is considered better or more idiomatic Ruby? This:
my_val = opts.delete(:key){|k| default_value_for_key }
or:
my_val = opts.delete(:key) || default_value_for_key
given that I want to remove the keys from the hash when extracting the values.
Upvotes: 4
Views: 803
Reputation: 87406
Keyword arguments:
If you are using Ruby 2.0 or later, the most idiomatic way to do things is to use keyword arguments:
def foo(bar: 10)
# do something with bar
end
The keyword arguments feature automatically takes care of assigning default values and throwing an exception when an unknown key is supplied.
If you are not using Ruby 2.0, or keyword arguments do not work for some other reason, you should decide if your method will detect unknown keys and throw an error, or just silently ignore them.
Silently ignoring unknown keys:
def foo(opts={})
bar = opts.fetch(:bar, 10)
# do something with bar
end
Using fetch
can be better than using opts[:bar] || 10
because it allows the caller of the method to specify bar=nil
or bar=false
. The ||
operator would result in you overriding any value returned from the hash if it is nil or false.
Complaining about unknown keys:
If you have a lot of keys and want to throw an exception when an unknown one is given, you probably should use delete
. The idea here is that when you are done deleting known keys, only the unknown ones are left.
def foo(opts={})
opts = opts.dup # Avoid deleting from the hash the caller passed
# in because that would surprise the caller!
bar = opts.delete(:bar) { 10 }
# get other options
raise "Unknown keys #{opts.keys.inspect}" if !opts.empty?
# do stuff
end
Upvotes: 2
Reputation: 33370
I think you could use fetch
with a default option.
my_val = opts.fetch(:key, "default_value_for_key")
EDIT:
Given that you want to delete the key, the block form is IMHO the way to go since it will return whatever the block evaluates to.
However, the second option is easier on the eyes.
Upvotes: 3