Deep_merge: Ruby Recursive Merging for Hashes 4

Posted by science on May 19, 2008

Welcome to “deep_merge” - a ruby lib to help merging complex hash structures.

Ruby provides some nice merge capabilities in hash and array. But it rightly doesn’t give us recursive merging, because it’s too poorly defined to standardize. However, recursive merging sometimes solves problems that can’t be solved other ways.

Take this code:

h1 = {:x => {:y => [4,5,6], :z => [7,8,9]}}
h2 = {:x => {:y => [1,2,3], :z => 'xyz'}}

If you want to merge these two hashes, what should happen? Well there are several possibilities. Let’s see how deep_merge handles it:

h2.deep_merge!(h1)
# results: h2 = {:x=>{:z=>[7, 8, 9], :y=>[1, 2, 3, 4, 5, 6]}}
# notice we overwrote 'xyz'! (That's what the bang means)
# Let's try it without the bang:
h1 = {:x => {:y => [4,5,6], :z => [7,8,9]}}
h2 = {:x => {:y => [1,2,3], :z => 'xyz'}}
h2.deep_merge(h1)
# results: h2 = {:x=>{:z=>"xyz", :y=>[1, 2, 3, 4, 5, 6]}}
# notice 'xyz' didn't get overwritten this time. No bang.

Let’s get a little more complicated with a “knockout” merge. We introduce a special string “–” which can “knockout” an element in an existing hash or array element:

h1 = {:x => {:y => ["d","e","--c"]}}
h2 = {:x => {:y => ["a","b","c"]}}
h2.ko_deep_merge!(h1)
# h2 = {:x=>{:y=>["a", "b", "d", "e"]}}
# notice no "c" any more!

Many of these features are configurable to your needs - feel free to read up in the source code. Home page and installation instructions are here: http://trac.misuse.org/science/wiki/DeepMerge

Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. [...] using a utility like Steve Midgley’s Deep Merge gem (Download) I can use common_bits as the base configuration and deep merge the individual site [...]

  2. Amy Wed, 04 Feb 2009 09:59:13 EST

    Thanks! Your gem makes my new cascading config system work beautifully!

  3. Jónas Tryggvi Wed, 08 Apr 2009 09:33:00 EDT

    This looks like something that should be used in merging the hashes that happens in ActiveRecord, because if you chain many scopes together which each have different joins, it ends up doing duplicate joins cause the hashes aren’t identical.

    I ended up using strings instead of hashes for the joins to prevent multiple joins to same tables

  4. Nando Sola Tue, 19 May 2009 18:32:39 EDT

    Beautiful gem! Merging complex data from big forms has never been easier.

Comments