例えば、decimal 型の weight という属性を持つ Item クラスがあるとする。
class Item < ActiveRecord::Base validates :weight, inclusion: { in: [0.2, 0.4, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0] } end
Rails 4.1.2 までは下記のようなバリデーションが成功していたのに、 4.2.0 に上げたら失敗するようになった。
item = Item.new(weight: 1.2) item.valid? #=> false item.weight #=> #<BigDecimal:7f0319279bd8,'0.1199999999 9999999555 9107901499 3738383E1',45(54)>
環境は次の通り。
- Ruby 2.1.3
- Rails 4.2.0
- データベースは PostgreSQL 9.1.14
decimal 型の属性は BigDecimal で保持するみたいで、 初期値として渡した Float の値を BigDecimal に変換した結果、誤差が発生してしまっていた。
BigDecimal は文字列から作成できるので
item = Item.new(weight: "1.2") item.valid? #=> true item.weight #=> #<BigDecimal:7f031937dbd8,'0.12E1',18(18)>
という風に文字列でセットして回避。