LoginSignup
25
27

More than 5 years have passed since last update.

マイグレーションにおいて参照先テーブル名を自動で推定できないカラムを外部キーとして指定する方法

Posted at

結論

方法は 2 通りあります。

references 型カラム定義時に :to_table オプションを使う

references 型のカラム定義時にオプション foreign_key: { to_table: <参照先テーブル名> } を指定します。

add_foreign_key:column オプションを使う

テーブル/カラム定義後に外部キーとしたいカラムに対して add_foreign_key <テーブル名>, <参照先テーブル名>, column: <カラム名> を指定します。

問題

テーブル users, memos において、memos の外部キーのカラム名 author にテーブル users を参照させるようなマイグレーションを書いたとします。

class CreateUsers < ActiveRecord::Migration[5.0]
  def change
    create_table :users do |t|
      t.string :name, null: false
      t.string :email, null: false
      t.string :password_digest, null: false

      t.timestamps
    end
  end
end

class CreateMemos < ActiveRecord::Migration[5.0]
  def change
    create_table :memos do |t|
      t.string :title
      t.text :content, null: false
      t.references :author, foreign_key: true

      t.timestamps
    end
  end
end

このとき、外部キーのカラム名から参照先テーブルを推定できないため、たとえば PostgerSQL だと次のようなメッセージを出力して、DB のマイグレーションに失敗します。

PG::UndefinedTable: ERROR:  relation "authors" does not exist
: CREATE TABLE "memos" ("id" serial primary key, "title" character varying, "content" text NOT NULL, "author_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL, CONSTRAINT "fk_rails_55c841b9ea"
FOREIGN KEY ("author_id")
  REFERENCES "authors" ("id")
)

解決方法

解決方法は 2 通りあります。

reference 型カラム定義時に :to_table オプションを使う

この場合は、references 型カラムを定義している部分でオプション :foreign_key にサブオプション :to_table を参照先テーブル名とともに指定することで、正しく参照先テーブルを参照できるようになります。

テーブル定義と一緒にカラムを定義する場合、次のように書きます。

class CreateMemos < ActiveRecord::Migration[5.0]
  def change
    create_table :memos do |t|
      # ...
      t.references :author, foreign_key: { to_table: :users }
      # ...
    end
  end
end

カラムだけ定義する場合、次のように書きます。

class AddAuthorToMemos < ActiveReocrd::Migration[5.0]
  def change
    add_reference :memos, :author, foreign_key: { to_table: :users }
  end
end

add_foreign_key:column オプションを使う

この場合は、references 型のカラムだけを定義しておき、別途 add_foreign_key のオプション :column で外部キーのカラム名と参照先テーブル名を明示的に関連付けることで、正しく参照先テーブルを参照できるようになります。

テーブル定義と一緒にカラムを定義する場合、次のように書きます。

class CreateMemos < ActiveRecord::Migration[5.0]
  def change
    create_table :memos do |t|
      # ...
      t.references :author
      # ...
    end
  end
  add_foreign_key :memos, :users, column: :author_id
end

カラム定義後の場合、次のように書きます。

class AddAuthorToMemos < ActiveReocrd::Migration[5.0]
  def change
    add_reference :memos, :author
  end
  add_foreign_key :memos, :users, column: :author_id
end

参考文献

25
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
27