Проверка свойства Ruby on Rails Decimal

У меня есть бизнес-модель с десятичным полем. Его значение должно находиться в диапазоне от 0,00 до 999,99. Поэтому я создал десятичное поле и добавил проверки в модель.

class Order < ApplicationRecord

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

end

Когда я создаю объект Order с десятичным значением, которое больше 1000 или меньше 0, я получаю ожидаемую ошибку, и это нормально. Я вижу, что проверки "числовости: {больше_чем: 0, меньше_чем: 1000}" работают, как и ожидалось.

Однако, когда я пытаюсь создать объект Order с десятичным значением 45,45554 или 45,45666, rails сохраняет объект в базе данных со значением цены 45,45. Я ожидаю получить ошибку формата, но кажется, что проверка формата не работает.

Что я делаю неправильно?

Какие-либо предложения,

Спасибо.


person Hilmi Yamcı    schedule 22.08.2017    source источник


Ответы (2)


Какова точность вашего ценового поля? В документах:

precision Определяет точность для десятичных полей, представляющих общее количество цифр в числе.

Я предполагаю, что цена имеет точность только 2, и поэтому она округляется.

person at0misk    schedule 22.08.2017
comment
Да, цена имеет точность 2. Предполагая, что у меня нет точности, проверка формата должна работать. Однако в любом случае это не работает. - person Hilmi Yamcı; 23.08.2017
comment
Я бы увеличил вашу точность, если вы имеете в виду, что хотите потребовать определенное количество десятичных знаков, это другая история, но я не понимаю ваш вариант использования. - person at0misk; 23.08.2017

Значение преобразуется в десятичное сеттером. Это означает, что проверка формата всегда будет проходить.

Если вам нужно проверить формат, используйте read_attribute_before_type_cast в пользовательской проверке.

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
person max    schedule 23.08.2017