- IT Tips
- ライフ
READ MORE
原著者の許諾を得て翻訳・公開いたします。
なお、該当のAPIドキュメントは以下です。
add_check_constraint
— ActiveRecord::ConnectionAdapters::SchemaStatementscheck_constraint
— ActiveRecord::ConnectionAdapters::SchemaStatementsremove_check_constraint
— ActiveRecord::ConnectionAdapters::SchemaStatements従来のRailsでは、ADD CONSTRAINT カラム名 CHECK 制約
を行うにはマイグレーションで生SQLを実行しなければなりませんでした。
例
Bookモデル用のテーブルを作成し、そのprice
フィールドに「価格は100より大きいこと」という制約を付けたいとします。従来は以下のように、テーブル作成後にマイグレーションで生SQLを書くしか方法がありませんでした。
class CreateBooks < ActiveRecord::Migration
def change
create_table :books do |t|
t.string :name
t.integer :price
end
end
end
class AddConstraintToBooks < ActiveRecord::Migration
def up
execute "ALTER TABLE books ADD CONSTRAINT price_check CHECK (price > 100)"
end
def down
execute "ALTER TABLE books DROP CONSTRAINT price_check"
end
end
しかもこのマイグレーションはそのままではロールバックできないので、up
メソッドとdown
メソッドを別々に書かなければいけません。
解決方法: check_constraint
、:add_check_constraint
、remove_check_constraint
Rails 6.1のマイグレーションにcheck_constraint
メソッドが追加され、テーブル作成時にDSLとしてcheck_constraint
を使うことも、テーブル作成後のマイグレーションで使うこともできるようになりました(#31323)。
テーブル作成時にcheck_constraint
を使う場合の構文は以下のとおりです。
create_table :table_name do |t|
...
t.check_constraint [constraint_name], [constraint]
end
既存のテーブルで制約を追加または削除するには、check_constraint
を以下の構文で用います。
add_check_constraint :table_name, :constraint_condition, name: "constraint_name"
remove_check_constraint :table_name, name: "constraint_name"
add_check_constraint
メソッドとremove_check_constraint
メソッドは、どちらもロールバック可能である点にご注目ください。
例:
先ほどのBook
モデルの例を用います。
以下のマイグレーションでは、books
テーブル自身を作成するときにcheck_constraint
メソッドを追加していることにご注目ください。
class CreateBooks < ActiveRecord::Migration
def change
create_table :books do |t|
t.string :name
t.integer :price
t.check_constraint "price_check", "price > 100"
end
end
end
別のマイグレーションで、books
テーブルにprice_check
制約を追加する場合は以下のように書きます。
class CreateBooks < ActiveRecord::Migration
def change
add_check_constraint :books, "price > 100", name: "price_check"
end
end
別のマイグレーションで、price_check
制約をbooks
テーブルから削除するには以下のように書きます。
class CreateBooks < ActiveRecord::Migration
def change
remove_check_constraint :books, name: "price_check"
end
end