boolean型カラムが他の型と違うところ

f:id:endoakak:20200725103912j:plain

テーブルに初めてboolean型のカラムを使ってみたところ、いろいろと今までと違うことがあって戸惑いました。

boolean型カラムの作り方

マイグレーションファイルに記述する、ということは他の型と変わりません。t.stringt.integerと同じように、t.booleanと書いて、カラム名を付ければOKです。

class CreatePosts < ActiveRecord::Migration[6.0]
  def change
    create_table :posts do |t|
      t.boolean :checked
      t.timestamps
    end
  end
end

デフォルトの値を指定する

必須ではないですが、NOT NULL制約とデフォルトの値を設定しておいた方がいいみたいです。

t.boolean :checked, null: false, default: false

データベースとRubyでNull(nil)の扱い方が違うことが問題らしいです。データベース(SQL)にとってはNullは特別な値で、trueでもfalseでもなければ空でもない値として扱われます。一方Rubyでは、nilはfalseとして扱われます。

データベースにアクセスするときなどにややこしいことになってくるので、なるべくnullは入れない方がいいということですね。

Boolean型のカラムを追加するときは必ずデフォルト値を設定しよう - Qiita

バリデーションでpresenceはNG

boolean型のカラムについてバリデーションを設定するときにpresence: trueとしてしまうと、値が入っているはずなのにエラーになります。

presenceの定義上、falseという値では引っかかってしまうようです。

そのため、boolean型のカラムに値が入っていることを確かめたいときはinclusionを使います。

class Post < ApplicationRecord
  validates checked, inclusion: [true, false]
end

checkedの値がtrueかfalseである、ということですね。

なぜか boolean の validates ~ presence がいつもエラーになる - Qiita

フォームで値を送るときはチェックボックス

boolean型の値をフォームで入力させたいときは、チェックボックスが便利です。

使い方はこんな感じ。

<%= form_with model: @post, local: true do |f| %>
  <%= f.check_box :checked, {}, "true", "false" %>
<% end %>

このように表示されます。

f:id:endoakak:20200820094450p:plain:h50

:checkedがキーの名前、{}がオプション、"true"がチェックされている時に送る値、"false"がチェックされていない時に送る値です。

オプションには、あらかじめチェックをオンにしておくchecked: trueなどを設定することができます。

ラジオボタンでも送れる

チェックボックスだけでなくラジオボタンで値を送ることも可能です。

<%= form_with model: @post, local: true do |f| %>
  <%= f.radio_button :checked, :true %>
  <%= f.label :checked, "チェックあり" %><br />
  <%= f.radio_button :checked, :false %>
  <%= f.label :checked, "チェックなし" %><br />
<% end %>

このように表示されます。

f:id:endoakak:20200820094915p:plain:h50

f.radio_buttonの後ろに送りたい値のキーcheckedとバリューtrue(false)を設定します。その後ろにオプションを設定することもできます。

これだけだとページ上にボタンしか表示されないので、labelを使って選択肢を表示する必要があります。

まとめ