我有一个Project模型,它与我的Client模型有一个belongs_to关系。客户有一个名称,但项目不一定有客户。
在我的视图中,我有如下代码:
<%=h project.client && project.client.name %>
因为如果项目没有客户端,尝试访问project.client.name
会导致NoMethodError(nil
没有名为name
的方法)。
问题是,在视图中使用这种nil检查是否可接受,还是应该寻找其他解决方法?
<%=h project.client && project.client.name %>
因为如果项目没有客户端,尝试访问project.client.name
会导致NoMethodError(nil
没有名为name
的方法)。
问题是,在视图中使用这种nil检查是否可接受,还是应该寻找其他解决方法?
只需使用
project.client.try(:name)
Project
中添加一个名为client_name
的方法,如果存在客户名称,则显示客户名称,但这样就将模型链接在一起,超出了一些人的建议范围。def client_name
client && client.name
end
def client_name
client ? client.name : "no client"
end
client.name ||“无客户”
- Eric我认为这是完全可以接受的 - 这是视图逻辑,您基本上是根据是否有数据来决定是否显示您的视图的部分。
我的临时解决方案是使用yield块并捕获错误。许多人会说使用rescue作为逻辑非常不好。只要不在需要知道某些东西为空且不应该为空的情况下使用即可。
在application_helper.rb中:
def none_on_fail
begin
return yield
rescue
return "(none entered)"
end
end
然后在视图中:
<%= none_on_fail { project.client.name } %>
然后方法可以链式调用,深度可以任意设置,并且它可以用于任何方法,但是如果存在其他潜在的模型/关系/方法问题,它将掩盖这些问题。我会把它比作用火焰喷射器取出刺,如果使用不当,会产生痛苦的后果。
我认为这些检查通常可以通过一点思考来消除。这样做的好处是保持您的视图代码更清洁,更重要的是,将逻辑保持在视图层之外,这是最佳实践。有些模板引擎不允许在视图中使用任何逻辑。
至少有几种情况。比如说,您有一个依赖于实例变量的show
操作。如果未找到记录,则控制器不应该渲染HTML,而应该通过重定向或其他方式进行处理。如果您在视图中有一个数组的循环,请使用@array.each do |a| end
,以便在数组为空时不进行评估。如果您真的想在视图中使用应用程序默认值,请尝试从配置文件中加载它,例如@page_title || #{@APP_CONFIG['page_title']}
(请参见Railscasts #85)。请记住,您可能希望稍后更改这些字符串,例如翻译UI。
以下是一些可以避免使用存在性检查和try
的情况。如果可能的话,我会尽量避免使用它们。如果无法避免,我会将条件检查放在视图助手中,并添加一个助手单元测试来验证(和记录)两个代码路径。