Controlling the order of rails validations

David Tuite picture David Tuite · May 11, 2011 · Viewed 17.3k times · Source

I have a rails model which has 7 numeric attributes filled in by the user via a form.

I need to validate the presence of each of these attributes which is obviously easy using

validates :attribute1, :presence => true
validates :attribute2, :presence => true
# and so on through the attributes

However I also need to run a custom validator which takes a number of the attributes and does some calculations with them. If the result of these calculations is not within a certain range then the model should be declared invalid.

On it's own, this too is easy

validate :calculations_ok?

def calculations_ok?
  errors[:base] << "Not within required range" unless within_required_range?
end

def within_required_range?
  # check the calculations and return true or false here
end

However the problem is that the method "validate" always gets run before the method "validates". This means that if the user leaves one of the required fields blank, rails throws an error when it tries to do a calculation with a blank attribute.

So how can I check the presence of all the required attributes first?

Answer

tadman picture tadman · May 11, 2011

I'm not sure it's guaranteed what order these validations get run in, as it might depend on how the attributes hash itself ends up ordered. You may be better off making your validate method more resilient and simply not run if some of the required data is missing. For example:

def within_required_range?
  return if ([ a, b, c, d ].any?(&:blank?))

  # ...
end

This will bail out if any of the variables a through d are blank, which includes nil, empty arrays or strings, and so forth.