首页 > 解决方案 > Rails validations - cutom messages are not applied

问题描述

I have a Ride model with price float field and validation of the precision. I want to display my own custom error message when the validation fails but it doesn't work.

According to Rails Gudes "the :message option lets you specify the message that will be added to the errors collection when validation fails. When this option is not used, Active Record will use the respective default error message for each validation helper. The :message option accepts a String or Proc."

I do it exactly as in the example there and it does not work.

Rails guides

validates :age, numericality: { message: "%{value} seems wrong" }

My example

validates :price, numericality: { message: "Invalid price. Max 2 digits after period"}, format: { with: /\A\d{1,4}(.\d{0,2})?\z/ }

spec/models/ride_spec.rb

context 'with more than 2 digits after period' do
      let(:price) { 29.6786745 }

      it 'the price is invalid' do
        expect(subject.save).to be_falsy
        expect(subject).not_to be_persisted
        puts subject.errors.full_messages.last # "Price is invalid"
      end
    end

What am I doing wrong?

Update

This is what I've learned so far. I have set the price to be empty in the test and it now shows the error message that I want.

context 'with more than 2 digits after period' do
      let(:price) { '' }

      it 'the price is invalid' do
        expect(subject.save).to be_falsy
        expect(subject).not_to be_persisted
        puts subject.errors.full_messages.last # "Price Invalid price. Max 2 digits after period"
      end
    end

Conslusion: it works for 'presence' validation, not for numericality validation, which is very confusing as the docs say clearly that you validate numericality, not presence. Am I right? Is this an error or deliberate?

标签: ruby-on-railsvalidation

解决方案


我认为您出错的地方是期望numericality接受验证选项format。参考活动记录指南,没有format.

看到您已调用此方法,您price似乎希望将精度保持在小数点后 2 位,以便您可以存储某物的美元价值。正确的类型是带有 的小数scale: 2,或者我过去成功的方法是将 存储price为整数price_in_cents

context 'with more than 2 digits after period' do
  let(:price) { 123.333 }

  it 'rounds to 2 decimal places' do
    expect(subject.save).to eq true
    expect(subject.reload.price).to eq 123.34
  end
end

推荐阅读