Как мне избежать нулевого класса в ruby ​​на рельсах? - PullRequest
2 голосов
/ 13 августа 2010

Я получаю следующую ошибку, и думал , используя .nil?Метод, который я мог бы избежать получения ошибки путем определения исключения.Но я не знаю.

В строке 40 показано, что я получаю сообщение об ошибке ... кажется, что contact.latest_event равен нулю.Но не должен .nil?помочь мне избежать ошибки?Спасибо ...!

ActionView::TemplateError (undefined method `<=>' for nil:NilClass) on line #40
of app/views/companies/show.html.erb:
37:     <p>
38:             <%= full_name(contact) %>, <%= contact.status %><%= contact.titl
e %>,
39:             <span class='date_added'>added <%= contact.date_entered %>
40:                     <% if !contact.latest_event.nil?%>
41:                       last event: <%= contact.latest_event.date_sent %>
42:                     <% end %>
43:             </span>

Вот самое последнее событие:

 def latest_event
   [contact_emails, contact_calls, contact_letters].map do |assoc|
          assoc.first(:order => 'date_sent DESC')
      end.compact.sort_by { |e| e.date_sent }.last
 end

Я думаю, возможно, что ни одна из моделей contact_emails, например, не была выполнена.... но что мне делать, если их не существует?

Ответы [ 4 ]

2 голосов
/ 13 августа 2010

Я не знаю, что делает latest_event, но кажется, что ваш ноль на самом деле в latest_event, так как он выполняет сравнение (<=>). Как выглядит latest_event

0 голосов
/ 24 октября 2013

Вы неявно используете <=>, когда используете sort_by.

Вот один из возможных обходных путей, предполагая, что date_sent содержит Date объект:

def latest_event
  [contact_emails, contact_calls, contact_letters].map do |assoc|
    assoc.first(:order => 'date_sent DESC')
  end.compact.sort_by { |e| e.date_sent.nil? ? Date.new : e.date_sent }.last
end

Ваша проблема в том, что некоторые из ваших записей имеют null в столбце date_sent. Когда вы просите ruby ​​отсортировать по этому значению, ruby ​​не знает, как сравнить nil с Date. Чтобы выполнить сравнение сортировки, ruby ​​использует <=> (см. Документы здесь и здесь о том, что делает этот оператор).

В приведенном выше коде я добавил логику для замены заполнителя Date, когда date_sent равен nil. Этот заполнитель - 1 января, -4712 (очень старая дата). Это означает, что записи с date_sent == nil будут помещены на первое место в результате сортировки.

Если ваш date_sent является Time, тогда вы можете использовать Time.at(0) вместо Date.new.

0 голосов
/ 15 августа 2010

Полагаю, вы можете решить свою проблему, изменив метод latest_event.

def latest_event
   events = [contact_emails, contact_calls, contact_letters].map do |assoc|
          assoc.first(:order => 'date_sent DESC')
      end.compact

   events.sort_by{ |e| e.date_sent }.last unless events.blank?
end

И просто комментарий: когда вам нужно if s, как это

if !contact.latest_event.nil?

лучше использовать unless:

unless contact.latest_event.nil?
0 голосов
/ 14 августа 2010

Метод <=> используется для реализации базовых операторов как <,>, =>, ... (см. Модуль Comparable ).Но я не вижу, где вы их используете, на самом деле ... это может быть внутри метода latest_event.

Кроме того, следующие утверждения эквивалентны:

if !contact.latest_event.nil?
unless contact.latest_event.nil?
if contact.latest_event   # Only nil and false evaluate as false
...