Railsのマイグレーションファイルに外部キー制約はどう書くの?
はじめに
タイトル通り、Railsでモデルを作成する時にマイグレーションファイルが作成されますが、その時に外部キー制約を指定したい場合はどうするのか疑問に思ったので試してみました。
環境については後に記述するので一致しない方は別途ご自身で調べてみてください。
ある程度、開発に携わっている方なら、外部キー制約(FOREIGN KEY)をご存知かと思いますが、もし知らない方は下記を読んで外部キー制約の仕様について確認してみてください。(なぜ必要なのかも調べておくといいかも知れません。)
外部キー制約について
MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.1.17.2 外部キー制約の使用
また、この辺の扱い方を詳しく書いているRailsのドキュメントが見当たらず(たぶん調べ方が悪いのだと思います...)、下記の記事が大変参考になりました。ありがとうございます。
参考にさせていただいた記事
環境
Ruby on Rails4
MySQL5.7
手順
始める前に
あるプロジェクト管理テーブル(親テーブル)に紐付くタスクテーブル(子テーブル)という想定です。
親:projects
子:tasks
※外部キー制約の確認が目的なのでカラムを指定しません。
モデル作成
>bundler exec rails g model project
>bundler exec rails g model task
マイグレーションファイル編集
作成されたtasksのマイグレーションファイルを編集します。
>vi db/migrate/yyyymmddxxxxx_create_tasks.rb
class CreateTasks < ActiveRecord::Migration
def change
create_table :tasks do |t|
t.references :project, foreign_key: true
t.timestamps null: false
end
end
end
マイグレーション実行
>bundler exec rake db:migrate RAILS_ENV=development_root
作成されたテーブルの確認
mysqlクライアントでDBに接続してテーブル作成確認コマンドで確認してみましょう。
>mysql -uユーザー -p
>show create table table_name
希望通りにprojectsテーブルのidとtasksテーブルのproject_idが外部キー制約(FOREIGN KEY)になっております。
CREATE TABLE `projects` ( `id` int(11) NOT NULL AUTO_INCREMENT, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci CREATE TABLE `tasks` ( `id` int(11) NOT NULL AUTO_INCREMENT, `project_id` int(11) DEFAULT NULL, `created_at` datetime NOT NULL, `updated_at` datetime NOT NULL, PRIMARY KEY (`id`), KEY `fk_rails_02e851e3b7` (`project_id`), CONSTRAINT `fk_rails_02e851e3b7` FOREIGN KEY (`project_id`) REFERENCES `projects` (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
所感
いつものようにRailsのお作法に則って記述すれば全く難しい事はありません。
しかし、全てのシステムがこのようになっているとは限りません...
例えば
- idカラムが存在しないテーブルと外部キー制約をする場合はどうかいたらいいのか
- 外部キーの名前を指定できないのか
この辺はもう少し掘り下げて調べてみる必要があるかも知れません。
もしかしたら、モデルだけ作成してマイグレーションファイルは作成しないとか...
以上、最後まで読んでいただきありがとうございます。