railsでboolean値のvalidationをする方法

ちょっと罠にかかりました。

validates :publish, presence: true

いつも通りpresence: trueを書いていました。

こうすると、errorになります。

なぜ、そんなことが起こるかです。

rails/presence.rb at d57356bd5ad0d64ed3fb530d722f32107ea60cdf · rails/rails · GitHub

  def validates_presence_of(*attr_names)
    validates_with PresenceValidator, _merge_attributes(attr_names)
  end

https://github.com/rails/rails/blob/47eadb68bfcae1641b019e07e051aa39420685fb/activemodel/test/models/person_with_validator.rb#L6

class PresenceValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    record.errors[attribute] << "Local validator#{options[:custom]}" if value.blank?
  end
end

value.blank?になっていますね。

[1] pry(main)> false.blank?
=> true
[2] pry(main)> true.blank?
=> false

この結果、falseの場合に反応しています。

なので、別のvalidationを使います。

validates :publish, inclusion: { in: [true, false] }

これでtrue or falseが存在する場合に反応するようになります。

意外なところで存在を知った。