One liner nested hash creation in Ruby? (I come from Perl)

Viewed 19052

I am a Perl person and I have made Hashes like this for a while:

my %date;

#Assume the scalars are called with 'my' earlier

$date{$month}{$day}{$hours}{$min}{$sec}++

Now I am learning Ruby and I have so far found that using this tree is the way to do many keys and a value. Is there any way to use the simple format that I use with Perl using one line?

 @date = {                                                                                                                                                                      
        month => {                                                                                                                                                                 
          day => {                                                                                                                                                                 
           hours => {                                                                                                                                                              
              min => {                                                                                                                                                             
                sec => 1                                                                                                                                                           
              }                                                                                                                                                                    
            }                                                                                                                                                                      
          }                                                                                                                                                                        
        }                                                                                                                                                                                                                                                                                                                                                     
      }                   
8 Answers

1) Refinements

You can use the Ruby Refinements instead of Monkey Patching.

It is way more secure than MonkeyPatching the entire Hash class and the usage part is still fancy

Setup ‍

# Use Hash.dynamic_keys to create keys dynamically on a Hash
module HashDynamicKeysRefinements
  refine Hash.singleton_class do
    def dynamic_keys
      new { |hash, key| hash[key] = dynamic_keys }
    end
  end
end

Usage

using HashDynamicKeysRefinements

dynamic_hash = Hash.dynamic_keys

dynamic_hash[:where][:requests][:id] = 3

dynamic_hash
=> {:where=>{:requests=>{:id=>3}}}

2) New Class

Or you can create a new class to implement this feature on the Hash class, the usage part is also awesome.

Setup ‍

  • /lib/hash_dynamic.rb
# Enables dynamic keys creation on a Hash
#   query = Hash.dynamic_keys
#   query[:where][:requests][:id] = 3
#   puts query
#     {:where=>{:requests=>{:id=>3}}}
class HashDynamic < Hash
  def self.new
    Hash.new { |hash, key| hash[key] = new }
  end
end

Usage

require 'hash_dynamic.rb'

dynamic_hash = HashDynamic.new

dynamic_hash[:a][:b][:c] = 5

dynamic_hash
=> {:a=>{:b=>{:c=>5}}}
Related