如何使用 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 能够正确比较 position
和 thing.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)
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 能够正确比较 position
和 thing.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)