0

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!!

Trung Tran
  • 13,141
  • 42
  • 113
  • 200
  • possible duplicate of [Controlling the order of rails validations](http://stackoverflow.com/questions/5966055/controlling-the-order-of-rails-validations) – hammar May 26 '14 at 18:23

2 Answers2

2

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
usha
  • 28,973
  • 5
  • 72
  • 93
1

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
Lukas
  • 3,175
  • 2
  • 25
  • 34