如何使用 ActiveRecord 正确地将数据库持久化的 BigDecimal 与另一个值进行比较?

How to properly compare database-persisted BigDecimal to another value using ActiveRecord?

objective 是使用像 #where#first_or_create 这样的 ActiveRecord 方法来正确比较数据库保存的 BigDecimal 值与 Float 或 String 值。

create_things 迁移:

t.decimal :position, :precision => 10, :scale => 4

相关代码:

position = "0.309624"
thing = Thing.where(:position => position).first_or_create
thing2 = Thing.where(:position => position).first_or_initialize

问题:

我希望 Thing.count 等于 1,thing2.persisted? 等于 true,这意味着 Active Record 能够正确比较 positionthing.position找到第一条记录并将其分配给 thing2.

调试中:

thing.position #> #<BigDecimal:7ffbdabe42a8,'0.309624E0',9(18)>
thing.position == position #> false

可以通过转换两个变量来进行有效比较...

thing.position.to_s == position#> true
thing.position.to_f == position.to_f #> true

...但这需要转换数据库持久值。有没有办法使用 #where and/or #first_or_create?

另见 How can I compare a BigDecimal with ActiveRecord decimal field?

编辑:这个问题与相关问题的不同之处在于,相关问题的公认解决方案提倡舍入一个浮点数,应用于此示例将要求分配 position = "0.309624".to_f.round(4),这仍然会产生一个比较无效。

我想我找到了答案,就是在比较之前将位置转换为BigDecimal:

position = BigDecimal.new("0.309624", 4) # where 4 is the decimal scale.

现在看起来很简单...

编辑:BigDecimal 在存储到数据库之前以及与数据库值进行比较时也需要四舍五入:

position = BigDecimal.new("0.309624", 4).round(4)