Hilmi Yamcı
Hilmi Yamcı

Reputation: 473

Ruby on Rails Decimal property validation

I have a business model with a decimal field. Its value must be between 0.00 and 999.99. So I have created a decimal field and add validations to the model.

class Order < ApplicationRecord

  validates :price, format: { with: /\A\d+(?:\.\d{0,2})?\z/ }, numericality: { greater_than: 0, less_than: 1000 }

end

When I create the Order object with a decimal value which is greater than 1000 or less than 0, I get the error I expected and that's ok. I can see that "numericality: { greater_than: 0, less_than: 1000 }" validations work as expected.

Howeber, when I try to create an Order object with a decimal value of 45.45554 or 45.45666, rails persists the object to the database with the price value of 45.45. I expect getting a format error, but it seems that format validation doesn't work.

What I'm doing wrong ?

Any suggestions,

Thanks.

Upvotes: 0

Views: 4504

Answers (2)

max
max

Reputation: 101811

The value is converted to decimal by the setter. Which means that format validation will always pass.

If you need validate the format use read_attribute_before_type_cast in a custom validation.

class Order < ApplicationRecord

  validates :price, numericality: { greater_than: 0, less_than: 1000 }
  validates :price_format
  PRICE_REGEXP = /\A\d+(?:\.\d{0,2})?\z/.freeze

  private 
  def price_format
    unless read_attribute_before_type_cast('price') =~ PRICE_REGEXP
      errors.add('price', 'must match the correct format')
    end
  end
end

Upvotes: 1

at0misk
at0misk

Reputation: 76

What is the precision of your price field? Via the docs:

precision Defines the precision for the decimal fields, representing the total number of digits in the number.

I'm assuming price only has a precision of 2, and that's why it's getting rounded.

Upvotes: 1

Related Questions