There are frequent times in development when you want to use "keyword arguments" or in Rails-ish, an options hash. I had looked at some of the Hash extensions that are in the Rails framework in the past, but I had rarely used anything more than stringify_keys and symbolize_keys. Now, reverse_merge is my friend.
Let's take a simple example: say you're making a helper that displays your Person in a default way, where Person has the fields :name, :location, and :birthday. In this horribly contrived example, we'll allow the user to specify the CSS style of each field, like so:
<%= show_person @person, :name => "font-size: 30pt;" %>
Part of the convention-over-configuration principle is providing defaults to reduce the amount of code and to create consistency. This is where the "options hash" comes in. Before when I wanted to do something like this, my code would look thusly:
# in the helper def show_person(person, options = {}) options.symbolize_keys! options = {:name => "font-size: 36px; color: blue", :location => "font-size: 10px; color: gray;", :birthday => "font-family: Georgia;" }.update(options) # do the rest of the helper stuff... end
Now let's turn it on its head with reverse_merge.
def show_person(person, options = {}) options.symbolize_keys! options.reverse_merge! :name => "font-size: 36px; color: blue", :location => "font-size: 10px; color: gray;", :birthday => "font-family: Georgia;" # ... end
Much better! (IMHO, YMMV) reverse_merge works by inserting only those keys that are not in the receiving Hash. Let's clean it up a little more.
def show_person(person, options = {}) options.to_options!.reverse_merge! :name => "font-size: 36px; color: blue", :location => "font-size: 10px; color: gray;", :birthday => "font-family: Georgia;" # ... end
There you have it! Quick, simple and fool-proof "keyword arguments". One enhancement that could simplify it even further is to add our own little extension...
class Hash def options_merge!(options) self.to_options!.reverse_merge! options end end
Happy Ruby-ing!