LoginSignup
6
2
お題は不問!Qiita Engineer Festa 2023で記事投稿!

Boolean型カラムをpresence: trueで設定したらfalseで保存出来なかった

Last updated at Posted at 2023-07-17

前提条件

Userテーブルにnullを許容しないBoolean型のhoge_flagというカラムがあるとする。

create_table :users do |t|
  t.boolean :hoge_flag, default: true, null: false
end

migration後にuser.rbにvalidatesを追加

validates :hoge_flag, presence: true

データ保存時にエラーが出る・・・

上記を踏まえて、hoge_flagをfalseにしてみた!

user = User.first
user.hoge_flag = false
user.save!

結果

Translation missing: ja.activerecord.errors.messages.record_invalid (ActiveRecord::RecordInvalid)

あらら・・・

もう少し確認してみると

user.valid?
=> false

もちろん、バリデーションに引っかかってる:frowning2:
エラー内容は

user.errors.messages
=> {:hoge_flag=>["を入力してください"]}

ん?????
値はちゃんとfalseを入れてるけど??

user.hoge_flag
=> false

入ってるよね:sweat_smile:

調べてみた

Railsガイドで改めてpresenceをみてみる。

Railsガイド/presence

このヘルパーは、指定された属性が空(empty)でないことを確認します。値がnilや空文字でない、つまり空でもなければホワイトスペースでもないことを確認するために、内部でblank?メソッドを使っています。

ほうほう。ここで重要なのは、

内部でblank?メソッドを使っています。

だな:speak_no_evil:

ちなみにblank?の挙動はドキュメントを見てみると

An object is blank if it's false, empty, or a whitespace string. For example, nil, '', ' ', [], {}, and false are all blank.

!address || address.empty?

とあるので、

false.blank?
=> true

となっていて、内部的にtrueが返ってバリデーションに引っかかってたというオチでした・・・

presence: true

この記述はずっと使ってきていたはずなのに、深読みせず空かどうかみるやつねみたいな感覚で使ってた怠惰な自分を反省します:sob:059.jpg

解決法

じゃあ今回のパターンの場合にどう書けばいいかというと、

validates :boolean_field_name, inclusion: [true, false]

もしくは

validates :boolean_field_name, exclusion: [nil]

と書くと、falseでもバリデーションに引っかからずに値が保存出来ます!

まとめ

Railsは魔法が多い。

と常々思っていますが、いつも何気なく使っているメソッド等の挙動や内部処理をドキュメント等で確認することの大事さを今回改めて感じました。

6
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2