2012-11-06 23 views
2

我的web应用程序失败的最常见原因之一是因为用户有时缺少某个视图期望的特定属性。例如,我的应用程序中的大多数用户在我们的系统中都有教育(学校,学位等)条目,但有些用户却没有。假设我的观点看起来是这样的:异常处理:“未定义的方法____'为零:NilClass”

<% @educations.each do |education| %> 
    <%= education.school %> 
    <%= education.degree %> 
<% end %> 

我想避免“宠物小精灵”的异常处理,并认为必须有一个更好的办法解决处理一个“为无未定义的方法`度”:NilClass”错误在用户在我们的数据库中没有教育条目的情况下。这看起来像一个丑陋/乏味的修复:

<% @educations.each do |education| %> 
    <% if education.school %> 
    <%= education.school %> 
    <% end %> 
    <% if education.degree %> 
    <%= education.degree %> 
    <% end %> 
<% end %> 

任何输入表示赞赏。谢谢!

+1

看起来你遇到的问题并不是“度数”是零,而是你的“教育”实例之一是零('nil:NilClass'没有定义方法'程度')。 '@ educations'从哪里来? –

回答

0

只要你知道你的工作不会是零的第一个对象,最简单的方法是只做到这一点:

- @educations.each do |education| 
    = education.try :school 
    = education.try :degree 

#try方法是非常方便的。您也可以拨打.to_s在任何你认为可能是零,即:

- @educations.each do |education| 
    = education.school.to_s 
    = education.degree.to_s 

这将尼尔斯转换为空字符串。这在IMO的视图中并没有那么有用,但如果您有希望是字符串并且可能为空的输入,那么它会派上用场。即一种方法,如:

def put_in_parenthesis(string) 
    "(" + string.to_s + ")" 
end 
0

您在这里有几个选项。

最容易实现的是try method。它用于像这样:

<%= education.try(:degree) %> 

的问题是,try()被视为a bit of an anti-pattern。正如参考文献指出的那样,您可以通过类似的方式实现类似的功能:

<%= education && education.degree %> 

在我看来,这在智力上并没有太大差异。处理这个更简洁一点的流行方式是Null Object pattern,它基本上是一个定义了中性(“null”)行为的对象。

+0

FWIW他在上面的例子中并没有问'如果教育',即使他做了'如果教育&& education.degree; education.degree;结局“,这仍然是他要求不必做的事情。我认为对于非常简单的应用程序,如视图,'#try'是完全合适的。 – Andrew

+0

他不必将其包装在if中,它会返回其评估的最后结果。例如,启动irb并尝试''spice'&&'nice'&& true &&'rice'&& nil'和''spice'&&'nice'&& true&''rice''。只要你愿意,你可以将它链接起来,所以它可以处理诸如'<%= education && education.degree && education.degree.date%>'之类的东西。 (我知道你可以链接尝试,也可以发送它的参数。)就个人而言,我认为这最好通过使用空对象模式来解决,除了在微不足道的情况下(这就是我包括它的原因)。我认为尝试的大多数用法可以通过良好的架构来避免 –

+0

我的不好,我误解了你的答案。感谢您在评论中详细说明。 – Andrew

相关问题