代码之家  ›  专栏  ›  技术社区  ›  Ethan

在调用nil对象的方法之前,检查nil对象的更好方法是什么?

  •  6
  • Ethan  · 技术社区  · 15 年前

    我有这个方法调用,我必须使用…

    financial_document.assets.length
    

    但是 financial_document.assets 可以是 nil .

    我可以用…

    financial_document.assets.nil? ? '0' : financial_document.assets.length
    

    有没有不那么重复的方法?

    11 回复  |  直到 15 年前
        1
  •  7
  •   Jonathan Lonowski    15 年前

    我个人会用 or 操作员/关键字:

    (financial_document.assets or []).length
    

    不管怎样, .length 在数组上调用,给您 0 如果 nil .

        2
  •  8
  •   Joel Meador    15 年前

    戴夫·史密斯走对了。

    看看这个: http://www.nach-vorne.de/2007/4/24/attr_accessor-on-steroids

    一个简单的解决方案是这样的:

    class FinancialDocument
      attr_accessor :assets
      def assets
        @assets ||= Array.new
      end
      ...
    end
    
        3
  •  7
  •   Dave W. Smith    15 年前

    处理这一问题的较少重复的方法是,通过安排金融资产持有适当的sentinel值(例如,空集合或具有退化行为的特殊对象),确保金融资产始终是非空对象。

    The Null Object Pattern .

        4
  •  3
  •   Swanand    15 年前

    案例1:

    financial_document assets 有很多关系。在这种情况下, financial_document.assets 始终返回数组。所以 financial_document.assets.size 会给你 0 如果找不到匹配的子条目,则为“大小”。

    案例2:

    资产 只是中的一个方法/属性 财务文件 . 然后有 资产 方法返回数组,以便可以始终调用它的.SIZE。就像乔尔指出的那样。

        5
  •  3
  •   klew    15 年前

    在这种情况下,我使用 andand 宝石:

    financial_document.assets.andand.length || 0
    
        6
  •  3
  •   John    13 年前

    解决此类问题的更通用的方法是向对象添加一个try方法:

      ##
      #   @user.name unless @user.nil?
      # vs
      #   @user.try(:name)
      #
      def try(method, *args, &block)
        return nil unless method
        return nil if is_a?(NilClass) and [:id, 'id'].include?(method)
        self.send(method, *args, &block) if respond_to?(method)
      end
    

    我相信Ruby1.9已经在对象上有了一个try方法。

    然后 financial_document.assets.try(:length).to_i 会达到你想要的结果。 这是因为 nil.to_i 返回0

        7
  •  1
  •   Sohan    13 年前

    Try是一个方法,如果对象的方法非nil,它将调用该对象的方法,否则只返回nil。尝试nil方法将始终返回nil,而不是抛出异常。

    http://api.rubyonrails.org/classes/Object.html#method-i-try

    这是红宝石的方法!

        8
  •  1
  •   sawa    13 年前

    你不需要额外的宝石就可以做到。我一直在用 || , andand , try 但下面看起来更简单。我认为这是确认Dave的空对象模式的Ruby方法。

    financial_document.assets.to_a.length
    
        9
  •  0
  •   bendin    15 年前

    这是Ruby,您可以向nilclass添加一个length方法,并让它始终返回0。

        10
  •  0
  •   Lukas Stejskal    15 年前

    你可以把它改短一点:

    financial_document.assets ? financial_document.assets.length : '0'
    

    因为

    financial_document.assets == !financial_document.assets.nil?
    

    但总的来说,imho有很多重复的方法,只有各种各样的解决方法。(这是我不太喜欢Ruby中的一件事。)你可以确保对象不是空的(正如其他人在这里建议的那样),但你不能到处都这样做。您可以在helper方法或begin rescue块中包装nil检查代码。

    例如,我编写了一个助手方法——一个“长度getter”,而不是将长度方法添加到nil对象(这是一个肮脏的hack):

    def fd_length(financial_document)
      financial_document.assets ? financial_document.assets.length : '0'
    end
    
        11
  •  0
  •   nitecoder    15 年前

    模型中返回0或长度的内容。这使你不必在你看来做一件有价值的事。像这样的事情通常可以在模型中完成。

    class FinancialDocument
    
      def assets_length
        assets.length.blank? 0 : assets.length
      end
    end