いーほろよいの技術ブログ

IT技術ブログになります。

Railsのマイグレーションファイルに外部キー制約はどう書くの?

はじめに

タイトル通り、Railsでモデルを作成する時にマイグレーションファイルが作成されますが、その時に外部キー制約を指定したい場合はどうするのか疑問に思ったので試してみました。

環境については後に記述するので一致しない方は別途ご自身で調べてみてください。

ある程度、開発に携わっている方なら、外部キー制約(FOREIGN KEY)をご存知かと思いますが、もし知らない方は下記を読んで外部キー制約の仕様について確認してみてください。(なぜ必要なのかも調べておくといいかも知れません。)

外部キー制約について

MySQL :: MySQL 5.6 リファレンスマニュアル :: 13.1.17.2 外部キー制約の使用

 

また、この辺の扱い方を詳しく書いているRailsのドキュメントが見当たらず(たぶん調べ方が悪いのだと思います...)、下記の記事が大変参考になりました。ありがとうございます。

参考にさせていただいた記事

suin.io

 

環境

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カラムが存在しないテーブルと外部キー制約をする場合はどうかいたらいいのか
  • 外部キーの名前を指定できないのか

この辺はもう少し掘り下げて調べてみる必要があるかも知れません。

もしかしたら、モデルだけ作成してマイグレーションファイルは作成しないとか...

 

以上、最後まで読んでいただきありがとうございます。