Edited at

Railsの外部キー制約とreference型について

More than 1 year has passed since last update.

Railsで外部キーのカラムを追加する際に、reference型を使うことがあると思います。

reference型の使い方に関しては以下のように様々な記事があります。

外部キーをreferences型カラムで保存する

Rails4 外部キーをテーブルに設定するための、3通りのマイグレーションの書き方。

しかし、reference型で作成する時はadd_index: true必要なの?foreign_key必要なの?

と混乱してしまうので、備忘録のためにまとめておきます。


前提

アプリケーションとしてはTwitterの簡易版で、登録しているユーザーがツイートができるアプリケーションです。

テーブル構造としては

user : tweet = 1 : N

の関係になっています。

テーブル名はそれぞれ、userstweetsです。


reference型を使わない場合

まずはreference型を使わないで、外部キー制約のついたカラムを作成します。


制約などなにもないカラムの作成

以下のように記述すると、インデックスが貼られない、外部キー制約もつかないカラムを作成することができます。


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.integer :user_id
end
end
end


インデックスを貼るカラムの作成

インデックスを貼る場合、2通りの書き方があるようです。

インデックスとはなんぞやという方は こちら をご覧ください。


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.integer :user_id, index: true #indexオプション
end
end
end


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.integer :user_id
end
add_index :tweets, :user_id
# add_index :対象のテーブル名, インデックス対象のカラム名
end
end


外部キー制約が付いているカラムの作成

reference型を使わない場合、foreign_key: trueでは外部キー制約にならないので注意が必要です。

また、外部キー制約をつける場合、インデックスは自動で付与されるので、先ほどのindex: trueは不要になります!(便利ですね)


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.integer :user_id
end
add_foreign_key :tweets, :users
# add_foreign_key :対象のテーブル名, :指定先のテーブル
end
end


reference型を使う場合

次に、reference型を使う場合の外部キー制約のついたカラムを作成します。


reference型を使うメリット

reference型を使い、t.reference :userと記述すると2つのメリットがあります。



  • userではなくuser_idというカラム名を作成してくれる

  • インデックスを自動で張ってくれる


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.references :user
end
end
end

しかし、t.reference :userだけでは外部キー制約はつきません。

ですので、reference型を使う場合は以下のように記述して、外部キー制約をつけることになります。

reference型では外部キー制約をつけるときに、foreign_key: trueが使えるようになります!


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.references :user, foreign_key: true
end
end
end

ちなみに以下のようにadd_foreign_keyでも大丈夫です。


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.references :user
end
add_foreign_key :tweets, :users
end
end


まとめ

外部キー制約のついたカラムを作る際は、以下のように記述するのが手っ取り早いです。


2017_create_tweets.rb

class CreateTweets < ActiveRecord::Migration[5.0]

def change
create_table :tweets do |t|
t.string :text
t.references :user, foreign_key: true
end
end
end

ちなみにadd_columnの場合は以下の形が手っ取り早いです。


2017_add_column.rb

class AddColumn < ActiveRecord::Migration[5.0]

def change
add_reference :tweets, :user, foreign_key: true
end
end


参考にしたサイト

Railsマイグレーションのindex、foreign_keyの設定

Railsで外部キー制約のついたカラムを作る時のmigrationの書き方

Rails4 外部キーをテーブルに設定するための、3通りのマイグレーションの書き方。

Railsマイグレーションの外部キー制約を表現するreferencesについて