10

I get an nested array from facebook via omniauth and wanna check if it's empty?/nil?/exists? the depending line looks like:

 unless omniauth['extra']['raw_info']['location']['name'].nil?

This should check if this part of the array is empty or exists.

But always this error was thrown:

undefined method `[]' for nil:NilClass

Do I check arrays wrong?

I tried it with "has_key" "nil?" "empty?" "exists?" "blank?"

But no one of these works!

Please help me, many thanks in advance!

Jan
  • 12,992
  • 9
  • 53
  • 89

3 Answers3

15

Ideally you should check each nested level to see if it is nil, however, this will also work.

unless (omniauth['extra']['raw_info']['location']['name'] rescue nil).nil?

You can also rescue the NoMethodError specifically.

d11wtq
  • 34,788
  • 19
  • 120
  • 195
13

This error is raised because one of the hash values in the chain of omniauth['extra']['raw_info']['location']['name'].nil? returns nil and it is not the last call ['name'].

If for example omniauth['extra']['raw_info'] returns nil, you're actually trying to call nil['location'] which raises an error in ruby.

You can catch this error simply:

res = omniauth['extra']['raw_info']['location']['name'].nil? rescue true

unless res
  #your code here
end

Please notice that the code block above will fill the variable res with true if the ['name'] hash value is nil or any other hash value in the chain returns nil.

Erez Rabih
  • 15,562
  • 3
  • 47
  • 64
  • Hi Erez, thank you, but how can I say "if you are nil..." execute the next lines? – Jan Jul 16 '12 at 10:05
  • if res is true - one of the omniauth hash values returned nil – Erez Rabih Jul 16 '12 at 10:09
  • I'm late to the game, but I recommend against this methodology, as it will catch any exception in the line, for any reason. In this scenario, you are fairly limited on what would get returned, however this would start to fail if you were using a method to determine the value of `omniauth`. Then you won't know why it's failing. In general, blanket rescue is bad practice. – Jocko Apr 10 '17 at 20:41
7

A bit late to the party, but, as pointed in this answer, Ruby 2.3.0 introduced a new method called dig, which would return nil if one of the chained keys is nil. Your omniauth auth hash could then be presented as:

omniauth = { 
            ...                 
            "extra"=>{ "raw_info"=>
                        { "location"=>"New York",
                          "gravatar_id"=>"123456789"}}
             ...
           }


omniauth.dig('extra', 
             'raw_info',
             'location',
             'name',
             'foo',
             'bar',
             'baz') #<= nil
Community
  • 1
  • 1
dimitry_n
  • 2,939
  • 1
  • 30
  • 53