【问题标题】:Rails validations - cutom messages are not appliedRails 验证 - 不应用自定义消息
【发布时间】:2018-11-18 10:15:14
【问题描述】:

我有一个 Ride 模型,带有 price 浮点字段和精度验证。当验证失败但它不起作用时,我想显示我自己的自定义错误消息。

根据Rails Gudes“:message 选项让您指定验证失败时将添加到错误集合中的消息。当不使用此选项时,Active Record 将为每个验证助手使用各自的默认错误消息. :message 选项接受 String 或 Proc。"

我完全按照那里的示例进行操作,但它不起作用。

导轨

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

我的例子

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

我做错了什么?

更新

这是我到目前为止所学到的。 我在测试中将价格设置为空,现在它会显示我想要的错误消息。

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

结论:它适用于“存在”验证,而不适用于数字验证,这非常令人困惑,因为文档清楚地说您验证的是数字,而不是存在。我对吗?这是一个错误还是故意的?

【问题讨论】:

    标签: ruby-on-rails validation


    【解决方案1】:

    我认为您出错的地方是期望numericality 接受验证选项format。参考active record guides 没有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
    

    【讨论】:

    • 我无法在 DB 级别上设置Float 的精度,我可以在BigDecimal 上设置精度,就像precision: 10, scale: 2 一样,但不能在浮点数上设置。不过,我需要浮点数,因为 Rails 中的 BigDecimals 在 JSON API 响应中作为字符串返回,我需要前端的浮点数来进行进一步的计算。所以我需要验证模型中的格式作为一种解决方法。
    • 我假设您使用price 来显示某物的成本?如果是这样,我通常将价格存储为price_in_cents,然后在必要时转换为美元。
    • 是的,准确地显示成本。因此,您无需验证格式,允许将任何值保存在 DB 中,然后只需使用 Money gem 将 23.4567934 等数字转换为美元,如 23.46 美元?
    • 是 - 使用活动记录保存值(十进制或整数),然后在最后可能的时刻四舍五入(通常在显示总计时)。
    【解决方案2】:

    我想通了,有两个验证:格式验证和数字验证。我没有将消息添加到格式验证,所以当它失败时我会得到标准消息

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

    【讨论】:

      猜你喜欢
      • 2011-10-21
      • 1970-01-01
      • 2011-07-20
      • 1970-01-01
      • 1970-01-01
      • 2012-12-12
      • 1970-01-01
      相关资源
      最近更新 更多