When trying to access an element deep in an array of arrays, what is the best way to avoid getting the error 'undefined method `[]' for nil:NilClass' if an element doesn't exist?
For example I'm currently doing this, but it seems bad to me:
if @foursquare['response']['groups'][0].present? && @foursquare['response']['groups'][0]['items'].present?
Ruby 2.3.0 introduced a new method called dig
on both Hash
and Array
that can be combined with the new safe navigation operator (&.
) to solve your problem.
@foursquare.dig('response', 'groups')&.first&.dig('items')
This will return nil
if a value is missing at any level.
Depending on your array content, you can omit the .present?
. Ruby will also just take the last value in such a construct, so you can omit the if
statement.
@foursquare['response']['groups'][0] &&
@foursquare['response']['groups'][0]['items'] &&
@foursquare['response']['groups'][0]['items'][42]
More elegant solutions for this problem are the egonil (blog post), the andand gem (blog post), or even Ruby 2.3's safe navigation operator.
Update: Recent Rubies include the #dig
method, which might be helpful in this case. See user513951's answer for more details.
if @foursquare['response']['groups'][0].to_a['items']
. . .
It happens that NilClass
implements a #to_a
that returns [].
This means that you can map every nil
to []
and typically write a single expression without tests.
精彩评论