Railsのマイグレーションファイルで特定のカラムへ格納される値に制約をつけたかったのですが、そのやり方が分からなかったので、備忘録としてまとめます。
目次
問題
勉強の一環でクイズアプリを作っており、QuizChoices
(クイズの選択肢)モデルの実装に取りかかっていました。
すべてのクイズは4択形式としたいため、display_order
カラムに1〜4のいずれかの値だけを許可する必要があります。
display_order
カラムに対して、マイグレーションファイルでデータベースレベルでの制約を付けたいのですが、そのやり方がわかりませんでした、、。
解決方法
結論として、以下のようにマイグレーションファイル内でadd_check_constraint
メソッドを使うことで実現できました。
class AddConstraintToDisplayOrderOnQuizChoices < ActiveRecord::Migration[7.1]
def change
add_check_constraint :quiz_choices, 'display_order BETWEEN 1 AND 4', name: 'display_order_check'
end
end
rails db:migrate
を実行後、db/schema.rb
を見てみるとたしかに制約が付与されています↓
create_table "quiz_choices", charset: "utf8mb4", collation: "utf8mb4_0900_ai_ci", force: :cascade do |t|
t.bigint "quiz_id", null: false
t.string "content", null: false
t.boolean "is_correct", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.integer "display_order", default: 0, null: false
t.index ["quiz_id"], name: "index_quiz_choices_on_quiz_id"
# 制約が追加されている↓
t.check_constraint "`display_order` between 1 and 4", name: "display_order_check"
end
これでカラムに格納される値を限定できました!
捕捉説明
ちなみにadd_check_constraint
メソッドは内部的に以下のSQLを生成し、テーブル定義を変更しています。
ALTER TABLE "quiz_choices" ADD CONSTRAINT display_order_check CHECK (display_order BETWEEN 1 AND 4);
またadd_check_constraint
メソッドに追加できるオプションは次の2つです。
name
オプション:
制約に名前をつける。デフォルトだとchk_rails_123abc456def
のようになってしまうためつけた方が良い。validate
オプション(PostgreSQLのみ):
既存のレコードに対して制約を即時適用するか指定する。
おわりに
add_check_constraint
メソッドの存在を今回初めて知りました。
コメント