1

在我/post/index.html观,我有这样一行:如何优雅地处理零例外?

<%= post.status.upcase %> 

每当有post具有带nil值状态,我得到这个错误:

NoMethodError at/
undefined method `upcase' for nil:NilClass 

如何安全处理所有nil值在整个我的应用程序,所以它不会抛出这样的错误,它只是优雅地退化甚至忽略它?

我是否必须遍历每个视图和每个可能具有返回nil属性的对象,并为每个对象添加异常处理?

有没有“Rails-y”DRY方式来处理这个问题?

回答

3

忽略无是一个好主意恕我直言。它会导致细微的错误,无法追查。但是,如果你的示例中你想要输出一个空字符串(或者什么也没有),那么当status为零时,你有几个选项。对于我认为你在做的事情,我更喜欢第一个,紧随其后的是第二个,并且讨厌最后两个。

post.status.to_s.upcase

post.status.try(:upcase)

post.status.present? ? post.status.upcase : 'NO STATUS. OH NO'

begin 
    post.status.upcase 
rescue 
    'NO STATUS. OH NO' 
end 
+0

第一个会直接返回字符串'nil'呃?这是一个有趣的解决方法。在这种特殊情况下,我所能做的只是在模型上强制执行一个验证,即“status”属性不能为“nil”。我真的正在寻找一种更全面的方法来处理所有属性,这些属性在我的应用程序中不能为零,而无需为每个属性执行无校验运算。 – marcamillion 2014-09-19 00:03:01

+0

@marcamillion不,第一个会返回一个空白字符串。 'nil.to_s =>“”'' – 2014-09-19 16:57:50

0

如何post定义?通常在控制器中,您可以设置一个实例变量,例如@post。我会假定帖子是以某种方式从模型派生的,在这种情况下,您真正​​想要做的是确保您永远不会将状态为nil的帖子保存到数据库中。您应该对Post模型进行验证,以确保状态始终存在,然后检查Post对象在创建时是否有效。因此,像这样:

在你的模型:

class Post < ActiveRecord::Base 
validates :status, presence: true 
... 

,然后在posts_controller.rb控制器:

def create 
... 
if @post.save 
    #handle successful save 
else 
    # handle unsuccessful save 
end 

这样你永远不与数据库中的错误数据结束。

我猜的其他(哈克)的方式来解决这个问题将是创建你的模型的方法,以确保你永远不会从状态methos空,所以是这样的:

class Post 
... 
def status 
    read_attibute(:status) || "" # return an empty string is status is null - this is a hack, I should fix this at some point by making sure the a status of nil is never saved to the database! 
end 

或根据你在上面的回答中的评论,你总是可以猴子补丁活动记录永远不会返回零,而是返回每个类的默认值。

文件ActiveRecord的/ lib目录/ active_record/base.rb,线路1870

def read_attribute(attr_name) 
    attr_name = attr_name.to_s 
    if !(value = @attributes[attr_name]).nil? 
     if column = column_for_attribute(attr_name) 
     if unserializable_attribute?(attr_name, column) 
      unserialize_attribute(attr_name) 
     else 
      column.type_cast(value) 
     end 
     else 
     value 
     end 
    else 
     nil # return whatever you think is appropriate 
    end 
    end 
0

在Application_controller将这个。rb

rescue_from Exception::NoMethodError, :with => :render_error 

private 
def render_error 
render :file => "#{Rails.root}/public/methodnotfound.html", :status => 404, :layout => false 
end 

并且还用消息“methodnotfound.html”创建html。

0

我只是想用一个更多的选项来更新这个线程:现在Ruby(2.3版本)给了我们一个安全的导航操作符,&.语法。

所以:

post.status.upcase

将成为:

post.status&.upcase

类似于铁路的try方法,整个产业链将返回nil,如果它在nil遇到NoMethodError

相关问题