Проверить нулевой результат в запросе ActiveRecord - PullRequest
1 голос
/ 15 сентября 2010

У меня есть несколько мест в модели, которые делают что-то вроде

  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 ]

6 голосов
/ 15 сентября 2010

Чтобы избежать ошибки NoMethodError для nil, вы должны определить блок begin rescue,

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

Мне также нравится Rails , попробуйте , метод:

find(:all, :conditions => "foo").first.try(:date).try(:to_datetime) || 0
1 голос
/ 15 сентября 2010

может быть, это чище:

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 

это безопаснее

0 голосов
/ 15 сентября 2010

Вы также можете определить область действия.Например, в приложении Rails3 вы должны попробовать:

В вашей модели ServerInfo.rb:

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

// Не забудьте никогда не помещать свои параметры непосредственно в запрос sql, что является плохой практикойтак как вы рискуете каким-нибудь SQL-инъекцией //

Затем в контроллере:

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

Я не пробовал этот код, тогда вам может потребоваться адаптировать его к вашим потребностям (или к вашемуПриложение Rails2)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...