Jean
Jean

Reputation: 5411

compare two dates undefined method `>' for nil:NilClass

I'm trying to comparte two dates in my controller here is the code

if @user.payment.count == 0
    some action
elsif @user.payment.last.active_until.to_date > Time.now.to_date
    some action
elsif @user.payment.last.active_until.nil?
    some action
end

When I try to evaluate this

elsif @user.payment.last.active_until.to_date > Time.now.to_date

I get this error:

undefined method `>' for nil:NilClass

But I have the same line in a view to show some other information and it works great.

I don't understand why in the controller doesn't work.

Thanks in advance for your help.


UPDATE

here is my console output

1.9.3p286 :002 > u.payment.last.active_until
  Payment Load (0.2ms)  SELECT "payments".* FROM "payments" WHERE "payments"."user_id" = 10 ORDER BY "payments"."id" DESC LIMIT 1
 => Thu, 24 Jan 2013 

If I compare this in my console I get this:

1.9.3p286 :003 > u.payment.last.active_until.to_date > Time.now.to_date
  Payment Load (0.3ms)  SELECT "payments".* FROM "payments" WHERE "payments"."user_id" = 10 ORDER BY "payments"."id" DESC LIMIT 1
 => true 

UPDATE 2

the same if in my controller is true and in console is false, I thinks here is the problem

1.9.3p286 :010 > u.payment.last.active_until.nil?
  Payment Load (0.3ms)  SELECT "payments".* FROM "payments" WHERE "payments"."user_id" = 10 ORDER BY "payments"."id" DESC LIMIT 1
 => false 

Upvotes: 0

Views: 1457

Answers (4)

Sean Hill
Sean Hill

Reputation: 15056

The only way that to_date will return nil is when you have a blank string. All other strings will raise an exception of some sort. You need to check for a blank string instead of nil? because "".nil? == false. Instead, use @user.payment.last.active_until.blank?. That will check for blank strings and nil.

if @user.payment.count == 0
    some action
elsif @user.payment.last.active_until.blank?
    some action
elsif @user.payment.last.active_until.to_date > Time.now.to_date
    some action
end

Besides that, is there any good reason that you're storing dates as strings?

Upvotes: 0

schmatz
schmatz

Reputation: 183

Check your syntax in your model, including validations. All answers I've seen online concerning this type of error are just syntax errors. This error is essentially saying you're trying to call a comparison on the left-hand object, which happens to be nonexistent, so it's probably a problem with your model or validations.

Upvotes: 0

Leo Correa
Leo Correa

Reputation: 19789

Your problem is with @user.payment.last.active_until

You should do the check for nil before you try to access that field and you'll probably see that it's empty

A good habit I've created is that every time I access a chain method like that I check along the way if the value is not nil so I don't unexpectedly call methods on nil stuff unless I'm absolutely 100% sure that value can never be nil.

payments = @user.payment

if payments.count == 0
    some action
elsif payments.last.active_until.nil?
    some action
elsif payments.last.active_until.to_date > Time.now.to_date
    some action
end

or if you want to keep the same code you had then

if payments.count == 0
    some action
elsif !payments.last.active_until.nil? && payments.last.active_until.to_date > Time.now.to_date
    some action
elsif payments.last.active_until.nil?
    some action
end

Upvotes: 0

Koraktor
Koraktor

Reputation: 42903

Just reorder your statements, so the date is first checked for nil?:

if @user.payment.count == 0
  some action
elsif @user.payment.last.active_until.nil?
  some action
elsif @user.payment.last.active_until.to_date > Time.now.to_date
  some action
end

PS: Additionally, check that the to_date method doesn't return nil for non-nil objects.

Upvotes: 2

Related Questions