在我的/post/index.html
视图中,我有这一行:
<%= post.status.upcase %>
每当post
的状态值为nil
时,我都会收到此错误:
NoMethodError at /
undefined method `upcase' for nil:NilClass
如何在我的应用程序中安全地处理所有nil
值,这样就不会抛出这样的错误,只是优雅地降级甚至只是忽略它?
我是否必须遍历每个视图和每个可能具有可返回的属性的单个对象,并为每个对象添加异常处理?
是否有“Rails-y”DRY方式来处理这个问题?
答案 0 :(得分: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
答案 1 :(得分:2)
我只是想用另外一个选项来更新这个线程:Ruby now(从2.3开始)为我们提供了一个安全的导航操作符,&.
语法。
所以:
post.status.upcase
会变成:
post.status&.upcase
与Rail的try
方法类似,如果nil
遇到NoMethodError
,整个链将返回nil
。
答案 2 :(得分: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
这样你就不会在数据库中找到错误的数据。
我想另一种(hacky)解决这个问题的方法是在你的模型中创建一个方法,以确保你永远不会从状态方法中得到一个null,所以像这样:
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
或根据您在上述答案中的评论,您总是可以将补丁活动记录设为永不返回nil,而是为每个类返回一些默认值。
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
答案 3 :(得分: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
并使用消息&#34; methodnotfound.html&#34;创建html。