在Rails 2.3.x中处理嵌套关系中的nil (null)值



当前我正在工作的项目在视图中有以下代码:

<%= product.provider.name %>

上面的代码是获取产品的"提供者"并显示他/她的名字。但我的问题是有时这段代码会在provider得到nil时失败。(我知道这有点不寻常,但因为我正在使用遗留数据库,所以会发生这种情况)

所以检查nil验证,我写了以下代码(在我的ApplicationHelper)

def t(obj, attr)
    obj.nil? ? "" : obj.send(attr.to_sym)
end

现在我做的是这样的:

<%= t(product.provider, "name") %>

尽管这可以工作,但我遇到了另一个问题,我发现了以下代码:

<%= product.provider.provider_type.title %>

这里的问题是,在上面的代码中,'provider'或'provider_type'都可以是nil。

我正在研究的是一个异常处理机制,可以处理任意数量的嵌套关系。

或者这是一个完全错误的路径来处理嵌套关系中的nil值?我在Rails 2.3.8上运行

这是一个常见的问题。您可能需要检查这些:

  • Object.try
  • andand

例子:

# With try
product.provider.try(:name)
product.provider.try(:provider_type).try(:title)
# With andand
product.provider.andand.name

可以挽救所有异常:

<%= product.provider.provider_type.title rescue nil %>

由于我们可以使用#try方法或内联处理异常,这种使用方法违反了得墨忒耳定律:每个单元对其他单元的了解应该是有限的:只有与当前单元"密切"相关的单元。

视图应该使用现成的对象/变量,而不是链。因此,您可以尝试在模型中使用delegate方法,并使用helper覆盖其他方法。保持你的视图尽可能的干净,从设计者的角度来看。

我是这样解决这个问题的:

class Object
  def unless_nil(default = nil, &block)
    if nil?
      default
    else
      block[self]
    end
  end
end
product.provider.unless_nil(&:name)
product.provider.unless_nil(&:provider_type).unless_nil(&:title)
product.provider.unless_nil("Not specified", &:name)

Object#unless_blank, Array#unless_empty, Hash#unless_empty也很方便。

补充道:

同时,在某些情况下使用完整块甚至更方便:

some_variable = 
  product.provider.unless_nil do |provider|
    # some complex logic here using provider
  end

我更喜欢它

provider = product.provider
some_variable = 
  if provider
    # ...
  end

或到处使用product.provider。这是品味问题

最新更新