I'm sure I've seen an elegant solution to this before, but I can't quite find it:
I have a rails controller which may-or-may-not have the following hash element:
myhash[:parent_field]
Inside that parent field, a child element could also be blank. I'm currently checking that via the (very ugly) method:
if (!myhash[:parent_field] || !myhash[:parent_field][:child_field] || myhash[:parent_field][:child_field].blank?)
Which works, but I figure - surely - there has to be a more elegant way. Just to reiterate:
#fetch
is your friend:
my_hash.fetch(:parent, {})[:child].blank?
What I would do is just use local variables to ease your burden:
unless (p=foo[:parent]) && (c=p[:child]) && !c.blank?
# Stuff is borked!
end
But let's explore alternatives, for fun…
If you can't change your data structure (that's a Hash, by the way, not an Array) then you can use the Ruby andand gem in conjunction with the Rails' try
as lazy ways of calling methods on things that might be nil
objects.
You could alternatively change your data structure to Hashes that return empty auto-vivifying hashes when you ask for 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'd have to ensure that every object in your hierarchy was one of these hashes (which I explicitly failed to do for the contents of :dive
, resulting in the error).
For alternative fun, you could add your own magic lookup 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?
# ...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With