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

时间:2009-06-27 06:34:41

标签: ruby-on-rails ruby

我有这个方法调用我必须使用...

financial_document.assets.length

financial_document.assets可能是nil

我可以用......

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

这样做的重复性较低吗?

11 个答案:

答案 0 :(得分:8)

Dave W. Smith走在正确的轨道上。

检查出来:http://www.nach-vorne.de/2007/4/24/attr_accessor-on-steroids

一个简单的解决方案看起来像这样:

class FinancialDocument
  attr_accessor :assets
  def assets
    @assets ||= Array.new
  end
  ...
end

答案 1 :(得分:7)

处理此问题的重复性较小的方法是确保financial_document.assets始终是非null对象,方法是将其设置为保存适当的sentinel值(例如,空集合或具有退化的特殊对象)行为)。

请参阅The Null Object Pattern

答案 2 :(得分:7)

就个人而言,我会使用 or 运算符/关键字:

(financial_document.assets or []).length

无论哪种方式,都会在数组上调用.length,如果0则为nil提供。{/ p>

答案 3 :(得分:3)

案例1:

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

案例2:

assets只是financial_document中的一个方法/属性。 然后使用assets方法返回数组,以便始终可以在其上调用.size。就像乔尔指出的那样。

答案 4 :(得分:3)

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

financial_document.assets.andand.length || 0

答案 5 :(得分:3)

解决此类问题的一种更通用的方法是向Object添加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

我相信ruby 1.9已经在Object上有一个try方法。

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

答案 6 :(得分:1)

financial_document.assets.try(:length)|| 0

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

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

这是Ruby的方法!

答案 7 :(得分:1)

你可以在没有额外宝石的情况下完成。我一直在使用||andandtry,但以下内容看起来更简单。我认为这是确认Dave的空对象模式的红宝石方式。

financial_document.assets.to_a.length

答案 8 :(得分:0)

这是Ruby,你可以为NilClass添加一个长度方法,并且它总是返回0。

答案 9 :(得分:0)

你可以缩短一点:

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

因为

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

但总的来说,恕我直言,重复的方式并不少,只有各种解决方法。 (这是我在Ruby中不太喜欢的事情之一。)你可以确保对象不是null(正如其他人在这里建议的那样) - 但是你无法在任何地方做到这一点。您可以在辅助方法或begin-rescue块中包含nil-checking代码。

例如,不是将长度方法添加到nil对象(这是恕我直言的肮脏黑客),而是写了一个帮助方法 - 一个“长度吸气器”:

def fd_length(financial_document)
  financial_document.assets ? financial_document.assets.length : '0'
end

答案 10 :(得分:0)

模型中返回0或长度的东西。这使您不必在视图中做一件有价值的事情。这样的事情通常可以在模型中完成。

class FinancialDocument

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