I'm looking for a good way to avoid checking for nil
at each level in deeply nested hashes. For example:
name = params[:company][:owner][:name] if params[:company] && params[:company][:owner] && params[:company][:owner][:name]
This requires three checks, and makes for very ugly code. Any way to get around this?
TLDR;
params&.dig(:company, :owner, :name)
As of Ruby 2.3.0:
You can also use
&.
called the "safe navigation operator" as:params&.[](:company)&.[](:owner)&.[](:name)
. This one is perfectly safe.Using
dig
onparams
is not actually safe asparams.dig
will fail ifparams
is nil.However you may combine the two as:
params&.dig(:company, :owner, :name)
.So either of the following is safe to use:
params&.[](:company)&.[](:owner)&.[](:name)
params&.dig(:company, :owner, :name)
If it's rails, use
Oh wait, that's even uglier. ;-)
(Even though it's a really old question maybe this answer will be useful for some stackoverflow people like me that did not think of the "begin rescue" control structure expression.)
I would do it with a try catch statement (begin rescue in ruby language):
You may want to look into one of the ways to add auto-vivification to ruby hashes. There are a number of approaches mentioned in the following stackoverflow threads:
Equivalent to the second solution that user
mpd
suggested, only more idiomatic Ruby:You don't need access to the original hash definition -- you can override the [] method on the fly after you get it using h.instance_eval, e.g.
But that's not going to help you with the code you have, because you're relying on an unfound value to return a false value (e.g., nil) and if you do any of the "normal" auto-vivification stuff linked to above you're going to end up with an empty hash for unfound values, which evaluates as "true".
You could do something like this -- it only checks for defined values and returns them. You can't set them this way, because we've got no way of knowing if the call is on the LHS of an assignment.
Again, though, you can only check values with it -- not assign them. So it's not real auto-vivification as we all know and love it in Perl.