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?
Rails validation defines valid states for each of your Active Record model classes. They are used to ensure that only valid details are entered into your database. Rails make it easy to add validations to your model classes and allows you to create your own validation methods as well.
validates is used for normal validations presence , length , and the like. validate is used for custom validation methods validate_name_starts_with_a , or whatever crazy method you come up with. These methods are clearly useful and help keep data clean.
Data validation (when done properly) ensures that data is clean, usable and accurate. Only validated data should be stored, imported or used and failing to do so can result either in applications failing, inaccurate outcomes (e.g. in the case of training models on poor data) or other potentially catastrophic issues.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With