Reputation: 13721
I have a really unique case of the 'undefined method error' in Rails. I have a Task Order model that has the attributes "obligatedAmount" and "awardAmount". When creating a new Task Order, one of my business rules is the "obligatedAmount" cannot be greater than the "awardAmount". So ensure this, I made a custom validation:
validate :check_amount_obilgated
validates_presence_of :awardAmount
validates_presence_of :obligatedAmount
def check_amount_obilgated #cannot be greater than contract award amount
if obligatedAmount > awardAmount
errors.add(:obligatedAmount, "The Obligated Amount cannot be greater than the Award Amount")
end
end
This works fine. HOWEVER, if I make a new Task Order and I leave the "obligatedAmount" OR the "awardAmount"empty, I Rails takes me to the error page with the error snippet:
undefined method `>' for nil:NilClass'
def check_amount_obilgated #cannot be greater than contract award amount
if obligatedAmount > awardAmount
errors.add(:obligatedAmount, "The Obligated Amount cannot be greater than the Award Amount")
end
end
So I guess the issue is that if one or both values are missing, the ">" operator cannot work. However, I put in the validates_presence_of :awardAmount and :obligatedAmount... is there any way I can get the validations to kick in first or is there any way around this error? Please let me know. Thank you!!
Upvotes: 0
Views: 701
Reputation: 3235
So the explaination is pretty straightforward. The >
operator is defined on the Fixnum class. NilClass does not have >
defined, so it will throw an undefined method error. If nil is passed to the valid call, you'll get a comparison error as nil can't be coerced implicitly to a Fixnum.
A quick check in irb shows the errors you can expect if nil shows up in either the right-hand or left-hand operand:
2.1.2 :001 > 1 > nil
ArgumentError: comparison of Fixnum with nil failed
from (irb):1:in `>'
from (irb):1
from /Users/hungerandthirst/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
2.1.2 :002 > nil > 1
NoMethodError: undefined method `>' for nil:NilClass
from (irb):2
from /Users/hungerandthirst/.rvm/rubies/ruby-2.1.2/bin/irb:11:in `<main>'
A simple cast to_i
on both operands will result in the values being zero when nil and you will always be able to run the comparison.
2.1.2 :005 > nil.to_i
=> 0
So in your code, do:
obligatedAmount.to_i > awardAmount.to_i
Upvotes: 1
Reputation: 29349
Use to_i
to convert nil to zero
def check_amount_obilgated #cannot be greater than contract award amount
if obligatedAmount.to_i > awardAmount.to_i
errors.add(:obligatedAmount, "The Obligated Amount cannot be greater than the Award Amount")
end
end
Upvotes: 2