Ruby Recursive/Deep Merge

2012-06-20

Here’s a problem I encountered this morning: I needed to do a recursive/deep merge with hashes. My code looked like this:

def user_image_tag(user, style=:original, opts={})
  if user.profile_photo.exists?
    image_url user.profile_photo(style)
  else
    # Fall back to Gravatar
    opts = {
      :gravatar => {
        :size => 100,
        # (image_url is defined elsewhere b/c Rails oddly omits it):
        :default => image_url("default_user_#{style}.png")
      }
    }.merge(opts)
    gravatar_image_tag(user.email, opts)
  end
end

And I was calling the function like this:

= user_image_tag(@user, :medium, :gravatar => {:size => 60})

The problem is that I was clobbering the defaults for the :gravatar key. In this case, opts[:gravatar][:default] was deleted.

I did a Google search and turned up a snippet on DZone to patch Hash with a deep_merge function. But further down the page I saw a link to the ActiveSupport API documentation. Turns out there is already a deep_merge function that does just what I need. Nice!

blog comments powered by Disqus Prev: Postgres string_agg Function Next: Alien Words: Vocabulary Game for Greek and Latin