我在模型中有一些像
这样的地方 def ServerInfo.starttime(param)
find(:all, :conditions => "name ='#{param}_started'", :select => "date").first.date.to_datetime
end
现在,由于与问题无关的原因,可能会发生此特定行根本不在数据库中,并且上面的代码失败并显示NoMethodError (undefined method `date' for nil:NilClass):
。我目前的修复是
res = find(:all, :conditions => "name ='#{param}_started'", :select => "date")
check_time = res.first.nil? ? 0 : res.first.date.to_datetime
这可以找到,但我觉得把这些代码洒到这个地方是不对的。是否有更多的ruby-ish / rail-ish方法来防止解除引用nil?
答案 0 :(得分:6)
为了避免nil的NoMethodError,您应该定义begin
rescue
块,
def ServerInfo.starttime(param)
begin
find(:all, :conditions => "foo").first.date.to_datetime
rescue
0
end
end
我也喜欢Rails try方法:
find(:all, :conditions => "foo").first.try(:date).try(:to_datetime) || 0
答案 1 :(得分:1)
也许这更清洁:
check_time = res.first.date.to_datetime if res.first
不过,请勿使用:
:conditions => "name ='#{param}_started'" # SQL injection vulnerability.
改为使用这个:
:conditions => ["name = ?", "#{param}_started"] # This is safer. Pure clean Ruby
它更安全
答案 2 :(得分:0)
您也可以定义范围。例如,在Rails3应用程序中,您应该尝试:
在ServerInfo.rb模型中:
scope :starttime, lambda{|param|
if self.has_attribute?(param+'_started')
where("name = ?", param+'_started' ).select('date')
else
false
end
}
//记住永远不要将你的params直接放在你的sql查询中,这是不好的做法,因为你冒险进行一些sql注入//
然后在控制器中:
res = ServerInfo.starttime('a_param')
check_time = res.first.date.to_datetime if res
我没有尝试该代码,那么您可能需要根据您的需要(或您的Rails2应用程序)进行调整