【问题标题】:ActiveRecord less_than_or_equal_to validation error on equal valuesActiveRecord less_than_or_equal_to 等值验证错误
【发布时间】:2019-04-11 10:24:26
【问题描述】:

我已经定义了这个 ActiveRecord 验证

validates :attr_1, numericality: {
    less_than_or_equal_to: :attr_2,
    message: "...",
    allow_nil: true,
  }, if: [proc { |a| a.attr_2.present? }]

这似乎工作正常,但在 attr_1 == attr_2 的一种情况下我得到了误报。

我尝试调试打印消息中的值并放置这样的日志消息的问题

validates :attr_1, numericality: {
    less_than_or_equal_to: :attr_2,
    message: "%{value}, %{count} - ...",
    allow_nil: true,
  }, if: [proc { |a| Rails.logger.info "#{a.attr_1} <= #{a.attr_2} -> #{a.attr_1 <= a.attr_2}" ; a.attr_2.present? }]

此消息引发错误

9531.28, 9531.28 - ...

此外,在我看到的日志中

9531.28 <= 9531.28 -> true

这怎么可能?

编辑: 之前看到要比较的值是parsed as number,但是结果好像是一样的……

【问题讨论】:

    标签: ruby-on-rails activerecord rails-activerecord


    【解决方案1】:

    这些数字是如何计算的?也许是一个精度问题:

    [12] pry(main)> 9531.280000000001 == 9531.280000000002
    false
    [13] pry(main)> 9531.2800000000001 == 9531.2800000000002
    true
    [14] pry(main)> 9531.280000000001 == 9531.280000000002
    false
    [15] pry(main)> 9531.280000000001.round(3) == 9531.280000000002.round(3)
    true
    

    编辑:添加round

    【讨论】:

    • 它们来自用户输入
    • 比较时的值都是9531.28
    • 不,Rails 从输入中读取值并将其分配给模型的列,这可能是BigDecimal。在控制台上测试这个:m = YourModel.new(attr1: 9531.280000000001); m.attr1; m.attr1 == 9531.280000000001,所以你看到的不是你得到的。
    【解决方案2】:

    最后,我弄清楚发生了什么。基本上,该问题与 ActiveModel 验证中存在的错误有关,该错误已在here 中得到很好的描述,该错误已在here 中解决并在version 5.2.3 中发布。

    如果您和我一样落后于这个版本并且不想升级,我建议您实现自己的验证器扩展 ActiveModel::EachValidator,受当前 NumericalityValidator 的启发,并将其用于数值的每个验证。

    【讨论】:

      猜你喜欢
      • 2011-12-25
      • 2019-11-29
      • 2017-03-08
      • 1970-01-01
      • 1970-01-01
      • 2012-02-18
      • 2015-11-03
      相关资源
      最近更新 更多