Elegant handling of empty values ​​in a nested hash

I am sure I have seen this elegant solution before, but I cannot find it:

I have a rail controller that may or may not have the following hash element:

myhash[:parent_field] 

Inside this parent field, the child may also be empty. I am currently testing this using the (very ugly) method:

 if (!myhash[:parent_field] || !myhash[:parent_field][:child_field] || myhash[:parent_field][:child_field].blank?) 

What works, but I suppose - of course - there should be a more elegant way. Just to repeat:

  • myhash [: parent_field] may or may not exist
  • If it exists, myhash [: parent_field] [: child_field] may or may not exist
  • If it exists, it may or may not be empty.
+6
source share
6 answers

#fetch is your friend:

 my_hash.fetch(:parent, {})[:child].blank? 
+9
source

What would I do , just use local variables to ease your burden:

 unless (p=foo[:parent]) && (c=p[:child]) && !c.blank? # Stuff is borked! end 

But let them learn alternatives, for fun & hellip;


If you cannot change your data structure (this is a hash, by the way, not an array), you can use Ruby andand in combination with Rails try as lazy ways to call methods on objects that can be nil objects.


You can alternatively change the data structure to hashes that return empty auto-living hashes when you request a key that does not exist:

 mine = Hash.new{ |h,k| Hash.new(&h.default_proc) } mine[:root] = { dive:42 } p mine[:root][:dive] #=> 42 p mine[:ohno][:blah][:whee] #=> {} p mine[:root][:blah][:whee] #=> undefined method `[]' for nil:NilClass (NoMethodError) 

However, you will need to ensure that every object in your hierarchy is one of these hashes (which I obviously could not do for the content :dive , which led to an error).


For alternative entertainment, you can add your own magic search method:

 class Hash def divedive(*keys) obj = self keys.each do |key| return obj unless obj && obj.respond_to?(:[]) obj = obj[key] end obj end end if myarray.divedive(:parent,:child).blank? # ... 
+3
source

This is a frequently asked question and should probably be closed as a duplicate.

The first on this list was closed as a duplicate of the other two, although I believe that my answer contains a broader overview of methods for solving this problem than the last two.

+1
source

It probably depends on your real needs, but OOP's approach to this will be to convert arrays and hashes to real objects. Each object will manage its relationship (like ActiveRecord) and will know how to get children and parents.

0
source

So how is nil.blank? - true , you can remove the middle condition and simplify this:

 if !myarray[:parent_field] || myarray[:parent_field][:child_field].blank? 

Also, calling the myarray hash myarray bit misleading.

0
source

What about

 !(myarray[:parent_field][:child_field] rescue nil).blank? 

?

-2
source

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


All Articles