Jon-Michael Deldin

BMX, bike trials, & software from the Pacific Northwest

Deep Fetching Keys in Ruby Hashes

Have you ever wished Ruby had a simple way to “deep fetch” a key from a hash table? I’ve re-implemented Hash#deep_fetch numerous times now for dealing with hierarchical hashes (e.g., JSON API responses), so I’m finally posting the following snippet:

## Fetch nested keys in a more convenient way.
#
# Author :: Jon-Michael Deldin (@jmdeldin)
# License :: WTFPL
#
module DeepFetch
  def deep_fetch(*args)
    args.reduce(self) { |hsh, k| hsh.fetch(k) { |x| yield(x) } }
  end
end

if $0 == __FILE__
  require 'minitest/autorun'

  describe DeepFetch do
    it 'works for flat hashes' do
      h = {foo: :bar}.extend(DeepFetch)
      h.deep_fetch(:foo).must_equal :bar
    end

    it 'returns the value' do
      h = {foo: {bar: {baz: :spam}}}.extend(DeepFetch)
      h.deep_fetch(:foo, :bar).must_equal({baz: :spam})
      h.deep_fetch(:foo, :bar, :baz).must_equal :spam
    end

    it 'supports a not-found block' do
      h = {foo: {bar: :baz}}.extend(DeepFetch)
      h.deep_fetch(:foo, :spam) { |k| "no #{k}!" }.must_equal "no spam!"
    end
  end
end

It’s way too small for a Ruby Gem, but it fits quite nicely in a lib directory.

* * *