开发者

How do I avoid nil class in ruby on rails?

开发者 https://www.devze.com 2023-01-11 17:32 出处:网络
I get the following error, and thought by using the .nil? method I could avoid getting an error by identifying the exception.But I don\'t.

I get the following error, and thought by using the .nil? method I could avoid getting an error by identifying the exception. But I don't.

Line 40 shows I am getting an error...it seems to think that contact.latest_event is nil. But shouldn't .nil? help me avoid getting the error? Thanks...!

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>

Here is latest_event:

 def latest_event
   [contact_emails, contact_calls, contact_letters].map do |as开发者_运维百科soc|
          assoc.first(:order => 'date_sent DESC')
      end.compact.sort_by { |e| e.date_sent }.last
 end

I guess it's possible none of the Models contact_emails, for example, have been done...but what do I do if there aren't any that exist?


I don't know what latest_event does, but it seems like your nil is actually in latest_event since it's doing a comparison (<=>). What does latest_event look like?


I believe you can solve your problem changing the latest_event method.

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

And just a comment: when you need ifs like this

if !contact.latest_event.nil?

it's better to use unless:

unless contact.latest_event.nil?


The method <=> is used to implement basic operators as <, >, =>, ... (see the module Comparable). But I can't see where you use them, actually ... it may be inside the latest_event method.

Asides, the following statements are equivalent:

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


You're implicitly using <=> when you use sort_by.

Here's one possible workaround, assuming that date_sent holds a Date object:

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

Your problem is that some of your records have a null in the date_sent column. When you ask ruby to sort by this value, ruby doesn't know how to compare nil with a Date. To do the sorting comparisons, ruby uses <=> (see the docs here and here on what this operator does).

In the code above, I added logic to substitute a placeholder Date when date_sent is nil. That placeholder is Jan 1, -4712 (a very old date). That means records with date_sent == nil will be placed first in the sort result.

If your date_sent is a Time, then you can use Time.at(0) instead of Date.new.

0

精彩评论

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