The numericality validator does not care about your BigDecimal precision

Posted 11 months ago. Visible to the public. Repeats.

Looking at the source code of the validates_numericality_of validator Show archive.org snapshot , it becomes clear that it converts the attribute in question to either an integer or float:

if configuration[:only_integer]
  unless raw_value.to_s =~ /\A[+-]?\d+\Z/
    record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[:not_a_number])
    next
  end
  raw_value = raw_value.to_i
else
 begin
    raw_value = Kernel.Float(raw_value.to_s)
  rescue ArgumentError, TypeError
    record.errors.add(attr_name, configuration[:message] || ActiveRecord::Errors.default_error_messages[:not_a_number])
    next
  end
end

This might bite you for BigDecimals with a high precision as the casted float value might be rounded up or down. In these cases you'll have to write your own numericality validator.

One example would be a validation that your attribute is less_than: 100000. The Float 99999.999999999999 will NOT pass this check because it's rounded up. It will however most likely never affect any of your users as this is only broken in the most extreme case shown above.

Michael Leimstädtner
Last edit
11 months ago
Tobias Kraze
License
Source code in this card is licensed under the MIT License.
Posted by Michael Leimstädtner to makandra dev (2023-06-15 08:40)