Dive is a gem for accessing values within nested Hashes.
Ruby
Switch branches/tags
Nothing to show
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
lib
spec
.gitignore
CHANGELOG.md
Gemfile
README.md
Rakefile
dive.gemspec
todo.txt

README.md

Dive: for deep hash access

Dive is a gem for accessing values within nested Hashes.

Why?

Well, it all started when I was mapping human readable names taken from a Cucumber table to fields in a JSON response:

Given I have some sausages with
  | Name          | Contents                      |
  | Pork + Fennel | pork mince, fennel, intestine |
  | Soylent Green | people                        |  
Given /^I have some sausages with$/ |table|
  fields = {
    'Name' => :name,
    'Contents' => :ingredients
  }
  table.hashes.each do |row|
    sausage = {} 
    row.each_pair do |key, value|
      sausage[fields[key]] = value
    end
    @response[:sausages] << sausage
  end
end
@response
{ 
  :sausages => [
    {
	  :name => 'Pork + Fennel'
      :ingredients => 'pork mince, fennel, intestine'
    },
    {
	  :name => 'Soylent Green',
	  :ingredients => 'people'
    }
  ]
}

All fine and dandy until I had to map to values that were nested under the first level of the response:

@response
{ 
  :sausages => [
    {
	  :name => 'Pork + Fennel'
      :ingredients => {
	    :casing => 'intestine',
	    :filling => {
	      :meat => 'pork mince',
	      :spices => 'fennel'
	    }
      }
    }
  ]
}

I wanted to be able to do something like this:

fields = {
  'Name' => :sausage_name,
  'Spices' => ':ingredients[:filling[:spices]]'
}

So I did.

Check out the specs for how it behaves.

Dive has been tested with ruby 1.9.2 and 1.8.7.

Installation and usage

gem install dive

require 'dive'
foods = { :sausages => {:pork_and_fennel => 'DELICIOUS'}}
foods[':sausages[:pork_and_fennel]']
foods[':sausages[:coles_bbq]'] = 'YUCK'

Or if you become squeamish at the idea of overriding Hash's [] method:

require 'dive/noninvasive'
foods.dive ':sausages[:pork_and_fennel]'
foods.dive_store ':sausages[:coles_bbq]', 'YUCK'

You can also put this in your Gemfile, but be careful to not have it automatically required:

gem 'dive', :require => nil

If this gem is automatically loaded it may cause Hash access slowdown in your application.

A Note on Dive Keys

Anything containing square brackets can be parsed as a Dive key, for example

'first[second]'

If you are experiencing strange behaviour while using dive to override Hash methods, please check that none of your keys are unintentionally being recognised as such. A test case for the unusual ones would be much appreciated.

Coming up...

  • Array support
:sausages[0]
  • A better key format?
':sausages[0][:casing]'
'sausages.0.casing'
'sausages/0/casing'