Como mesclar hashes Ruby

Como posso mesclar esses dois hashes:

{:car => {:color => "red"}} {:car => {:speed => "100mph"}} 

Para obter:

 {:car => {:color => "red", :speed => "100mph"}} 

Existe um método de Hash#merge :

 ruby-1.9.2 > a = {:car => {:color => "red"}} => {:car=>{:color=>"red"}} ruby-1.9.2 > b = {:car => {:speed => "100mph"}} => {:car=>{:speed=>"100mph"}} ruby-1.9.2 > a.merge(b) {|key, a_val, b_val| a_val.merge b_val } => {:car=>{:color=>"red", :speed=>"100mph"}} 

Você pode criar um método recursivo se precisar mesclar hashes nesteds:

 def merge_recursively(a, b) a.merge(b) {|key, a_item, b_item| merge_recursively(a_item, b_item) } end ruby-1.9.2 > merge_recursively(a,b) => {:car=>{:color=>"red", :speed=>"100mph"}} 

Hash#deep_merge

rails 3.0+

 a = {:car => {:color => "red"}} b = {:car => {:speed => "100mph"}} a.deep_merge(b) => {:car=>{:color=>"red", :speed=>"100mph"}} 

Fonte: https://speakerdeck.com/u/jeg2/p/10-things-you-didnt-know-rails-could-do Slide 24

Além disso,

http://apidock.com/rails/v3.2.13/Hash/deep_merge

Você pode usar o método de merge definido na biblioteca de rubys. https://ruby-doc.org/core-2.2.0/Hash.html#method-i-merge


Exemplo

 h1={"a"=>1,"b"=>2} h2={"b"=>3,"c"=>3} h1.merge!(h2) 

Ele vai te dar uma saída como essa {"a"=>1,"b"=>3,"c"=>3}

Merge método de Merge não permite chave duplicada, de modo que a chave b será sobregravada de 2 para 3 .

Para superar o problema acima, você pode hackear o método de merge como este.

 h1.merge(h2){|k,v1,v2|[v1,v2]} 

O snippet de código acima fornecerá a saída

 {"a"=>1,"b"=>[2,3],"c"=>3} 
 h1 = {:car => {:color => "red"}} h2 = {:car => {:speed => "100mph"}} h3 = h1[:car].merge(h2[:car]) h4 = {:car => h3}