2

Let's say I have a hash of hashes as follows:

order_history = {}

order_history[customer_id][order_id] = { :total_spend => order_spend, :date => order_date }

When I add entries into this hash I have to check whether the customer_id exists first, like so:

order_history[customer_id] = {} unless order_history.has_key?(customer_id)

Then, I can add the details for an individual order:

order_history[123][456] = { :total_spend => 200.45, :date => 2016-05-03 }

Is it possible to declare the order_history hash as a hash-of-hashes at the outset, so I don't have to do the test every time? Or is there a way of telling ruby that when a new key is created, set the value to be a new, empty hash?

smilin_stan
  • 1,693
  • 2
  • 28
  • 40

2 Answers2

3

You can try this for your hash :

h = Hash.new { |h, k| h[k] = Hash.new(&h.default_proc) }

h['bar'] -> {}
h['tar']['star']['par'] -> {}

For more information, this answer is from this post

Community
  • 1
  • 1
XavM
  • 863
  • 9
  • 22
0

While the answer provided by @XavM perfectly answers the question, I would drop here a reference to excellent Hashie#Mash. Using the latter, one might do for string keys:

▶ require 'hashie/mash'
▶ hm = Hashie::Mash.new
#⇒ {}
▶ hm.foo.bar
#⇒ NoMethodError: undefined method `bar' for nil:NilClass

but:

▶ hm.foo!.bar
#⇒ nil
▶ hm.foo!.bar!
#⇒ {}

Sometimes it is more handy, than defining a default_proc.

NB the correct answer to the question stated in OP is provided by @XavM, please upvote it. I just dropped it here as an addendum.

Aleksei Matiushkin
  • 119,336
  • 10
  • 100
  • 160