rubyのbool値の入るカラムに対するvalidationは工夫が必要
active: [true, false]
のようなカラムに対して次のようなvalidationを貼った。
class ExamModel < ApplicationRecord
validates :active, presence: true
end
しかし、active: false
でレコード保存しようとするとエラーになります。
これはpresence: true
を指定された際に、.blank?
でrails側が検証しているから起きる現象のようで、ソースを見るとboolが入る場合のvalidationの仕方も記載されています
# If you want to validate the presence of a boolean field (where the real values are true and false),
# you will want to use <tt>validates_inclusion_of :field_name, :in => [true, false]</tt>.
source: rails/presence.rb at b481574a33764e2db1caf01c233a9c9ac9723780 · rails/rails
言われた通りに書く
validates :active, inclusion: { in: [true, false] }
うまく動くようになりました🎉
rspec
しかし、次はrspecでもさらにもう一工夫が発生します。
このように書いてみると……
it { is_expected.to validate_inclusion_of(:active).in_array([true, false]) }
shoulda-matchersに怒られてしまいました。
Warning from shoulda-matchers:
You are using
validate_inclusion_of
to assert that a boolean column
allows boolean values and disallows non-boolean ones. Be aware that it
is not possible to fully test this, as boolean columns will
automatically convert non-boolean values to boolean ones. Hence, you
should consider removing this test.
詳しくはこちらのブログで丁寧に説明されていますので丸投げをしますが,次のように書くのが良いようです。
it { is_expected.to allow_value(true).for(:active) }
it { is_expected.to allow_value(false).for(:active) }
it { is_expected.not_to allow_value(nil).for(:active) }
refs:
【メモ】ActiveRecordでboolean型のカラムに必須バリデーションが設定されてるかテストする|石灰|note
なぜか boolean の validates ~ presence がいつもエラーになる - Qiita
下書き:presence: true はboolが入るカラムでは正常に動作しない - void-avoid