How do I know if a multidimensional hash is significant in a ruby?

I'm currently doing the following, but I'm sure there should be a better way:

def birthday_defined?(map) map && map[:extra] && map[:extra][:raw_info] && map[:extra][:raw_info][:birthday] end 

There may be times when only map[:extra] defined, and then I get errors with Nil errors. The reason map[:extra][:raw_info] does not exist unless I use my verified code above.

+4
source share
6 answers

If you use Rails, you can use try (and NilClass#try ):

 value = map.try(:[], :extra).try(:[], :raw_info).try(:[], :birthday) 

It looks a bit repetitive: it just does the same thing over and over, passing the result of one step to the next step. This code template means we have a hidden injection:

 value = [:extra, :raw_info, :birthday].inject(map) { |h, k| h.try(:[], k) } 

This approach generalizes well any path in map that you have in mind:

 path = [ :some, :path, :of, :keys, :we, :care, :about ] value = path.inject(map) { |h, k| h.try(:[], k) } 

Then you can look at value.nil? .

Of course, if you do not use Rails, you will need a replacement for try , but it is not difficult.

+1
source

I have two ways. Both have the same code, but subtly different:

 # Method 1 def birthday_defined?(map) map[:extra][:raw_info][:birthday] rescue nil # rescues current line end # Method 2 def birthday_defined?(map) map[:extra][:raw_info][:birthday] rescue # rescues whole method nil end 
+1
source

Use the start / rescue unit.

 begin map[:extra][:raw_info][:birthday] rescue Exception => e 'No birthday! =(' end 
0
source

This is idiomatic, why do this. And yes, it can be a little cumbersome.

If you want to extend the Hash bit, you can do some cool things with a bit of a key path. See Accessing Ruby Hash with a Path Outlined String

 def birthday_defined? map.dig('extra.raw_info.birthday') end 
0
source

This is a bit hacky, but it will work:

 def birthday_defined?(map) map.to_s[":birthday"] end 

If map contains :birthday , then it will return a string that will be evaluated to true in the conditional expression, and if it does not contain :birthday , it will return nil .

Note. . It is assumed that the :birthday key :birthday not displayed in potentially several places on the map .

0
source

This should work for you:

 def birthday_defined?(map) map .tap{|x| (x[:extra] if x) .tap{|x| (x[:raw_info] if x) .tap{|x| (x[:birthday] if x) .tap{|x| return x}}}} end 
0
source

Source: https://habr.com/ru/post/1441341/


All Articles