Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
195
Help us understand the problem. What is going on with this article?
@publichtml

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

More than 3 years have passed since last update.

確認した環境はRails5.1.3です。

テーブル作成時

外部キー制約をかけるカラム名により、多少書き方が異なります。
カラム名が #{参照先テーブル名の単数形}_id (e.g. 参照先がusers.id なら user_id)の場合が基本形で、参照先テーブル指定が省略できます。
それ以外の場合は、参照先テーブルが推測不可能なので、 オプションで指定する必要があります。

class CreateTasks < ActiveRecord::Migration[5.1]
  def change
    create_table :tasks do |t|
      t.string :name, null: false

      # 基本形: user_idという名前で users.id への外部キー制約をはる
      t.references :user, foreign_key: true

      # 応用形: user_id以外の名前(assignee_id)という名前で users.id への外部キー制約をはる
      t.references :assignee, foreign_key: { to_table: :users }

      t.timestamps
    end
  end
end

カラム追加時

既存テーブルにカラムを追加する時の書き方です。

class AddUserIdToTasks < ActiveRecord::Migration[5.1]
   def change
    # 基本形: user_idという名前で users.id への外部キー制約をはる
    add_reference :tasks, :user, foreign_key: true

    # 応用形: user_id以外の名前(assignee_id)という名前で users.id への外部キー制約をはる
    add_reference :applicants, :assignee, foreign_key: { to_table: :users }
  end
end

注意事項

  • foreign_key オプションを省略してしまうと、外部キー制約がはられません。忘れないようにしましょう。

豆知識

  • create_table 内での t.references や  add_reference を使うとdefaultでindexが作られます
    • indexを作りたくない場合はオプションで明示的に index: false しましょう
    • ( ActiveRecord::ConnectionAdapters::ReferenceDefinition#initialize の default値で index: true になってるからのようです → ここ )

番外編

カラム名に *_id 以外の名前を使いたい

実は t.referencesadd_reference を使った時には、カラム名の後ろに自動で _id が付与され、外せません。
( ActiveRecord::ConnectionAdapters::ReferenceDefinition#column_name で、固定的に _id という suffix を付与しています → ここ )

そのような場合は、今のところ、外部キー制約のないカラムを追加した後に add_foreign_key で別途外部キー制約を追加する方式をとらざるを得ないようです。

# テーブル作成時に、 assigned_to カラムを作り、外部キー制約をはる
class CreateTasks < ActiveRecord::Migration[5.1]
  def change
    create_table :tasks do |t|
      t.string :name, null: false
      t.bigint :assigned_to, index: true
      t.timestamps
    end
    add_foreign_key :tasks, :users, column: :assigned_to
  end
end
# 既存テーブルに assigned_to カラムを追加し、外部キー制約をはる
class AddAssignedToToTasks < ActiveRecord::Migration[5.1]
  def change
    # assigned_to カラムを追加
    add_column :tasks, :assigned_to, :bigint, index: true
    # 別途外部キー制約を追加
    add_foreign_key :tasks, :users, column: :assigned_to
  end
end
195
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
195
Help us understand the problem. What is going on with this article?