Open2

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