Simplify multiple nil checking in Rails

后端 未结 10 1958
一个人的身影
一个人的身影 2020-12-17 06:44

How should I write:

if @parent.child.grand_child.attribute.present?
  do_something

without cumbersome nil checkings to avoid exception:

相关标签:
10条回答
  • 2020-12-17 07:36

    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

    0 讨论(0)
  • 2020-12-17 07:37

    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
    
    0 讨论(0)
  • 2020-12-17 07:46

    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

    0 讨论(0)
  • 2020-12-17 07:48

    You could use Object#andand.

    With it your code would look like this:

    if @parent.andand.child.andand.grandchild.andand.attribute
    
    0 讨论(0)
提交回复
热议问题