当前我正在工作的项目在视图中有以下代码:
<%= 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
。这是品味问题