Trung Tran
Trung Tran

Reputation: 13721

Unique undefined method error rails

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

Answers (2)

Lukas
Lukas

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

usha
usha

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

Related Questions