rainkinz
rainkinz

Reputation: 10394

Ruby style: Default value from a hash

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

Answers (2)

David Grayson
David Grayson

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

squiguy
squiguy

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

Related Questions