What's the most concise way to determine if @hash[:key1][:key2]
is defined, that does not throw an error if @hash
or @hash[:key1]
are nil?
defined?(@hash[:key1][:key2])
returns True if @hash[:key1]
exists (it does not determine whether :key2
is defined)
If you don't care about distinguishing nonexistent
@hash[:key1][:key2]
(at any of 3 levels) from@hash[:key1][:key2] == nil
, this is quite clean and works for any depth:If you want
nil
to be treated as existing, use this instead:Using Hash#fetch
You can use the Hash#fetch method with a default of
{}
so that it is safe to callhas_key?
even if the first level key doesn't exist. e.g.Alternative
Alternatively you can use the conditional operator e.g.
i.e. if
hash
doesn't have keykey1
then just returnfalse
without looking for the second level key. If it does havekey1
then return the result of checkingkey1's
value forkey2
.Also, if you want to check that
hash[key1]'s
value has ahas_key?
method before calling it:When using ActiveSupport (Rails) or Backports, you can use
try
:You could even handle
@hash
beingnil
:If you want
@hash
to always return a hash for a missing key:You could also define this recursive:
But to answer your question:
Perhaps I am missing something, but if all you care about is concise...why not:
or if you want to save a few characters
if any part of this fails, it returns
nil
otherwise it returns the value associated with:key2
ortrue
.The reason the
defined?
returns true even if:key2
is not there is because it just checks whether the object you are referencing exists, which in that case is the method[]
which is an alias for the methodfetch
which does exist on the hash@hash[:key1]
but if that were to return nil, there is no fetch method onnil
and it would returnnil
. That being said, if you had to gon
deep into an embedded hash, at some point it would become more efficient to call:Another option, one that I just discovered, is to extend Hash with a
seek
method. Technique comes from Corey O'Daniel.Stick this in an initializer:
Then just call:
You'll get the value, or nil if it doesn't exist.