presence: true はboolが入るカラムでは正常に動作しない
validationエラーに引っかかったので調査
結論:
code:ruby
# model-validation
validates :active, inclusion: { in: true, false }
# shoulda-matchers利用したrspec
it { is_expected.to allow_value(true).for(:active) }
it { is_expected.to allow_value(false).for(:active) }
なお先輩はこの程度であればなくてもいい とのこと。確かにです。
not null制約やデータ型がDBレイヤでも保証されており、意図しないデータが登録される可能性がとても低いため
調査:
なぜか boolean の validates ~ presence がいつもエラーになる - Qiita https://qiita.com/diskshima/items/9c0b6286d68c0c13bb68
presence の動作を定義している ActiveModel::Validations::PresenceValidator を見ると
class PresenceValidator < EachValidator
def validate_each(record, attr_name, value)
record.errors.add(attr_name, :blank, options) if value.blank?
end
end
となっています。ここで注目すべきは if value.blank? です。ここで、value には false が入っているわけですが、そうなると…
irb> value = false
=> false
irb> value.blank?
=> true
となり、エラーとして認識されてしまいます!
正しい Boolean フィールドのチェック方法
Booelan のバリデーションを行う場合には ActiveModel::Validations::InclusionValidator (validates に書くときは inclusion) を使って
validates :has_glasses, inclusion: true, false
とするのがいいらしいです。
だがこのように書くとshouldaからさらに怒られる
code:ruby
it { is_expected.to validate_inclusion_of(:active).in_array(true, false) }
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.
追加で調べる
https://note.com/ishibai/n/n2c27ff7288e3
code:ruby
it { is_expected.to allow_value(true).for(:active) }
it { is_expected.to allow_value(false).for(:active) }
解決
#rspec
https://zenn.dev/nifchi/scraps/d097c184bfe1c7