ハマったのでメモ。
まあRailsで1から作っている場合は遭遇しないかもしれませんが・・・。
ActiveRecord::Enumとは
割愛。
http://ruby-rails.hatenadiary.com/entry/20150710/1436461745
問題
class User < ApplicationRecord
enum state: { pending: 0, active: 1 }
end
user = User.new(state: :pending)
# => #<User:0x007fbdbf882a78 id: nil, state: 'pending'>
user.save!
# => true
user
# => #<User:0x007fbdbf882a78 id: 1, state: nil>
例外も発生せず、データベースを直接覗いてもデータはきちんと入っているのに、save!
するとstate
がnil
になった!?!?
原因
state
カラムがTINYINTだった。ActiveRecordは、カラムがTINYINT(1)の場合、自動的にbooleanとみなしてキャストするらしい。今回の場合(enumの場合)、enumのvalueにしていたのが数値だったために「(キャストした値)true/falseに該当するlabelがない」=> nil
となっていた様子。
解決策
class User < ApplicationRecord
attribute :state, ActiveRecord::Type::Integer.new
enum state: { pending: 0, active: 1 }
end
これでActiveRecordがstate
カラムを整数値としてキャストしてくれるようになる。
参考(https://blog.kazu69.net/2015/10/22/active-record-tinyint/)
(ちなみにリンク先で「TINYINT(1)はbooleanと同じなので0 か 1 しかとらない」とありますが、TINYINT(1)は場合-128~127 の値をとれます。booleanも同様)