Safely assign value to nested hash using Hash#dig or Lonely operator(&.)
It's not without its caveats (and doesn't work if you're receiving the hash from elsewhere), but a common solution is this:
hash = Hash.new {|h,k| h[k] = h.class.new(&h.default_proc) }hash[:data][:user][:value] = "Bob"p hash# => { :data => { :user => { :value => "Bob" } } }
And building on @rellampec's answer, ones that does not throw errors:
def dig_set(obj, keys, value) key = keys.first if keys.length == 1 obj[key] = value else obj[key] = {} unless obj[key] dig_set(obj[key], keys.slice(1..-1), value) endendobj = {d: 'hey'}dig_set(obj, [:a, :b, :c], 'val')obj #=> {d: 'hey', a: {b: {c: 'val'}}}
interesting one:
def dig_set(obj, keys, value) if keys.length == 1 obj[keys.first] = value else dig_set(obj[keys.first], keys.slice(1..-1), value) endend
will raise an exception anyways if there's no []
or []=
methods.