Safely Assign Value to Nested Hash Using Hash#Dig or Lonely Operator(&.)

How to set dynamically value of nested key in Ruby hash

Answer for hashes, just out of curiosity:

hash = { a: { b: { c: 1 } } }
def deep_set(hash, value, *keys)
keys[0...-1].inject(hash) do |acc, h|
acc.public_send(:[], h)
end.public_send(:[]=, keys.last, value)
end

deep_set(hash, 42, :a, :b, :c)
#⇒ 42
hash
#⇒ { a: { b: { c: 42 } } }

Extract Hash values using Hash#dig

You can, of course, pass an expression as an argument to #dig:

h.dig(:users, h.dig(:users)&.keys&.first, :name)
#=> John

Extract the key if you want more legibility, at the cost of lines of code:

first_user_id = h.dig(:users)&.keys&.first
h.dig(:users, first_user_id, :name)
#=> John

Another option would be to chain your #dig method calls. This is shorter, but a bit less legible.

h.dig(:users)&.values&.dig(0, :name)
#=> John

I'm afraid there is no "neater" way of doing this while still having safe navigation.

Safe navigation equivalent to Rails try for hashes

&. is not equivalent to Rails' try, but you can use &. for hashes. Just use it, nothing special.

hash[:key1]&.[](:key2)&.[](:key3)

Although I would not do that.

Getting minimum with a default

Your solution it's quite easy to read but rather inefficient because you're creating an array and invoking the min method every time and it is an overkill.

A maybe less readable and more verbose but more easy on the machine approach could be:

if params[:limit] && params[:limit] < 50
params[:limit]
else
50
end


Related Topics



Leave a reply



Submit