Last Updated: February 25, 2016
·
2.275K
· eladmeidar

Diving into ruby hashes

Nested hashes in ruby are a PITA. if in somewhere along the way one of your keys are missing / returning an empty hash, you'll get a fancy:

undefined method `[]' for nil:NilClass (NoMethodError)

Yes. annoying.

I took a shot at this issue by creating this ruby hash spinoff that accepts default values to key fetch requests. here it is

class NestedHash < Hash

  def [](value, default = NestedHash.new)
    self.fetch(value, default)
  end

  def self.from_hash(other_hash)
    nested_hash = NestedHash.new
    other_hash.each_pair do |key, val|
      if val.is_a?(Hash)
        nested_hash[key] = NestedHash.from_hash(val)
      else
        nested_hash[key] = val
      end
    end
    return nested_hash
  end
end


# Setup a regular hash
h = NestedHash.new
h["elad"] = NestedHash.new
h["elad"]["adam"] = NestedHash.new
h["elad"]["adam"]["hungry"] = "always"

# Test non existing value
puts h["elad"]["miki"]["hungry", "no"] # => "no"

# Test Converstions from regular hashes
real_hash = {:elad => {:koko => :awesome}, :adam => {:moko => :no}}

nested = NestedHash.from_hash(real_hash)

# Missing Value
puts nested[:elad][:invalid_key, "not here"] # => "not here"

# Existing value
puts nested[:elad][:koko] # => "awesome"

also available as a gist: https://gist.github.com/eladmeidar/5857066

2 Responses
Add your response

only this causes a rather crazy situations where

h["elad"]["adam"]["hungry"] = "always"
h["elad"]["adam"]["hungry"] # => nil

another approach would be:

class NestedHash < Hash  
  def initialize(*args)  
    inner_hash = lambda {|h,k| h[k] =  Hash.new &inner_hash   }  
    super(*args, &inner_hash)  
  end  
end  
over 1 year ago ·

or use fetch

over 1 year ago ·