How should I write:
if @parent.child.grand_child.attribute.present?
do_something
without cumbersome nil checkings to avoid exception:
If the attribute you are checking is always the same, create a method in @parent.
def attribute_present?
@parent.child.present? && @parent.child.grandchild.present? && @parent.child.grandchild.attribute.present?
end
Alternatively, create has_many :through
relationship so that @parent
can get to grandchild
so that you can use :
@parent.grandchild.try(:attribute).try(:present?)
Note: present?
is not just for nil, it also checks for blank values, ''
. You can just do @parent.grandchild.attribute
if it's just nil checking
Hi Think you can use a flag variable here with rescue option
flag = @parent.child.grand_child.attribute.present? rescue false
if flag
do_something
end
You could do this:
Optional = Struct.new(:value) do
def and_then(&block)
if value.nil?
Optional.new(nil)
else
block.call(value)
end
end
def method_missing(*args, &block)
and_then do |value|
Optional.new(value.public_send(*args, &block))
end
end
end
Your check would become:
if Optional.new(@parent).child.grand_child.attribute.present?
do_something
Source: http://codon.com/refactoring-ruby-with-monads
You could use Object#andand.
With it your code would look like this:
if @parent.andand.child.andand.grandchild.andand.attribute