views:

40

answers:

3

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

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?

A: 

maybe this, its cleaner:

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

btw, dont use:

:conditions => "name ='#{param}_started'"

insted of this use:

:conditions => ["name = ?", #{param}_started']

its more safer

Sebastian Brózda
A: 

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)

Yannis
+2  A: 

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
jpemberthy
I'd use the try method, it's very useful.
j.
Sweet, didn't know about Rails `try`. That's what I went with, for brevity reasons.
jhwist