This question already has an answer here:
In Rails we can do the following in case a value doesn't exist to avoid an error:
@myvar = @comment.try(:body)
What is the equivalent when I'm digging deep into a hash and don't want to get an error?
@myvar = session[:comments][@comment.id]["temp_value"]
# [:comments] may or may not exist here
In the above case, session[:comments]try[@comment.id]
doesn't work. What would?
say you want to find
params[:user][:email]
but it's not sure whetheruser
is there inparams
or not. Then-you can try:
It will return either
nil
(ifuser
is not there oremail
is not there inuser
) or otherwise the value ofemail
inuser
.Update: As of Ruby 2.3 use #dig
Most objects that respond to [] expect an Integer argument, with Hash being an exception that will accept any object (such as strings or symbols).
The following is a slightly more robust version of Arsen7's answer that supports nested Array, Hash, as well as any other objects that expect an Integer passed to [].
It's not fool proof, as someone may have created an object that implements [] and does not accept an Integer argument. However, this solution works great in the common case e.g. pulling nested values from JSON (which has both Hash and Array):
It can be used the same as Arsen7's solution but also supports arrays e.g.
Try to use
The most beautiful solution is an old answer by Mladen Jablanović, as it lets you to dig in the hash deeper than you could with using direct
.try()
calls, if you want the code still look nice:You should be careful with various objects (especially
params
), because Strings and Arrays also respond to :[], but the returned value may not be what you want, and Array raises exception for Strings or Symbols used as indexes.That is the reason why in the suggested form of this method (below) the (usually ugly) test for
.is_a?(Hash)
is used instead of (usually better).respond_to?(:[])
:The last example would raise an exception: "Symbol as array index (TypeError)" if it was not guarded by this ugly "is_a?(Hash)".
As of Ruby 2.3 this gets a little easier. Instead of having to nest
try
statements or define your own method you can now useHash#dig
(documentation).Or in the example above:
This has the added benefit of being more like
try
than some of the examples above. If any of the arguments lead to the hash returning nil then it will respond nil.Another approach:
This might also be consider a bit dangerous because it can hide too much, personally I like it.
If you want more control, you may consider something like: