🐰
ActiveRecord で integer 型カラムの数値範囲に制限をかける
Rails の ActiveRecord で、数値型のカラムに対して数値範囲の制限をかける方法について備忘録としてまとめます。
結論
- migration ファイルで指定する limit は大きさではなくバイト数
- Model 側で numericality validates を設定したほうがよさげ
- 有効/無効 のような数種類のフラグや選択式の値を管理するなら、enum の方がわかりやすい
やりたかったこと
モデル名やカラム名は架空のものですが、以下のように、integer 型のカラム(:age, :account_status)に入る数値に以下のような数値範囲の制限をかけたかったのです。
カラム | 制限 |
---|---|
age | 0 ~ 19 まで登録可能 |
account_status | 0 なら無効、1 なら有効 |
class CreateChirdren < ActiveRecord::Migration[7.1]
def up
create_table :chirdren do |t|
t.string :email, :null => false, comment: "メールアドレス"
t.string :name, :null => false, comment: "名前"
t.integer :age, default: 0, comment: "年齢"
t.integer :account_status, comment: "アカウント有効性(0: 無効, 1: 有効)"
t.timestamps
end
end
def down
drop_table :children
end
end
migration ファイルで指定する limit は大きさではなくバイト数
当初、下記のように migration ファイルで、limit で最大の数を指定しようとしていました。
t.integer :age, default: 0, limit: 19, comment: "年齢"
これは間違いで、この場合、age カラムは 19 バイトの制限をかけようとしているということになります。
Model 側で numericality validates を設定したほうがよさげ
なので、migration ファイルではなく、Model 側で制限をかけます。
numericality ヘルパーに、数値範囲オプションで制約をかけることができます。
class Children < ApplicationRecord
validates :age, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 19 }
end
上記の例では、以上
・以下
のオプションで設定しましたが、超過
・未満
もそれぞれ、grater_than
, less_than
のように設定することができます。
また、Rails 7 なら下記のように、in
オプションに range オブジェクトを渡してシンプルに記述することもできます。
class Children < ApplicationRecord
validates :age, numericality: { in: 0..19 }
end
有効/無効 のような数種類のフラグや選択式の値を管理するなら、enum の方がわかりやすい
また、有効/無効の2つの値しかとらないデータや、有料/無料プラン(有料でも松竹梅のようにいくつか分かれている場合もありますよね)のような選択式の値を integer 型カラムで管理する場合は、enum で管理する方が個人的にはわかりやすいかなと思います。
class Children < ApplicationRecord
enum :account_status, { ban: 0, active: 1 }
end
参考
Discussion