开发者

Check for nil result in ActiveRecord query

I have a few places in a model that does stuff like

  def ServerInfo.starttime(param)
    find(:all, :conditions => "name ='#{param}_started'", :select => "date").first.date.to_datetime
  end开发者_如何学Python

Now, for reasons not relevant to the question, it can happen that this particular row is not in the database at all and the code above fails with NoMethodError (undefined method `date' for nil:NilClass):. My current fix is

    res = find(:all, :conditions => "name ='#{param}_started'", :select => "date")
    check_time = res.first.nil? ? 0 : res.first.date.to_datetime

This works find, but I feel it's not right to sprinkle that code all over the place. Is there some more ruby-ish / rail-ish way to prevent dereferencing nil?


In order to avoid the NoMethodError for nil, you should define a begin rescue block,

def ServerInfo.starttime(param)
  begin
    find(:all, :conditions => "foo").first.date.to_datetime
  rescue
    0
  end
end

I also like the Rails try method:

find(:all, :conditions => "foo").first.try(:date).try(:to_datetime) || 0


maybe this is cleaner:

check_time = res.first.date.to_datetime if res.first

btw, don't use:

:conditions => "name ='#{param}_started'" # SQL injection vulnerability.

use this one instead:

:conditions => ["name = ?", "#{param}_started"] # This is safer. Pure clean Ruby 

it's safer


You may also define a scope. For instance in a Rails3 app you should try:

In your ServerInfo.rb model:

scope :starttime, lambda{|param|
  if self.has_attribute?(param+'_started')
    where("name = ?", param+'_started' ).select('date')
  else
    false
  end
}

// Remember to never put your params directly in your sql query, that is bad practice since you risk some sql injection //

Then in a controller:

res = ServerInfo.starttime('a_param')
check_time = res.first.date.to_datetime if res

I didn't try that code, then you may need to adapt it to your need (or to your Rails2 app)

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜