检查ActiveRecord查询中的nil结果

时间:2010-09-15 11:58:34

标签: ruby-on-rails activerecord

我在模型中有一些像

这样的地方
  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?

3 个答案:

答案 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应用程序)进行调整