Active Recordマイグレーションでのadd_foreign_keyとadd_referenceの違い 43 views Post @wakairo 30 Jan, 2026 12:14 +00:00 Railsガイドを一読しただけでは、 add_foreign_keyとadd_referenceが、それぞれどのようなもので、どう違うのかがいまいちよく分かりませんでした。 そこで、add_foreign_keyとadd_referenceによってdb/schema.rbがどのように変化するかを基に、 それぞれの機能について確認してみました。 add_foreign_key add_foreign_keyは外部キー制約の追加だけを行います。よって、カラムやインデックスの追加は行いません。 外部キー制約とは、子テーブルが参照している親のIDが親テーブルに存在することをデータベースレベルで保証する制約です。 例えば、以下の記述をマイグレーションファイルに行ったとします。 add_foreign_key :products, :users すると以下の記述がdb/schema.rbに追加されます。 add_foreign_key "products", "users" この記述は、products(子テーブル)のuser_idカラムに登場するIDが、users(親テーブル)のidカラムに必ず存在するように制約をかけています。 add_reference add_referenceは、テーブル間の関連付けに関する複数の設定を一度に行える便利メソッドです。 add_referenceの基本機能は、カラムとインデックスの追加です。 例えば、以下の記述をマイグレーションファイルに行ったとします。 add_reference :products, :user すると以下のように、users(親テーブル)に関連付ける2つの記述、具体的にはuser_idのカラムとインデックスをproducts(子テーブル)に追加する2つの記述が、db/schema.rbに追加されます。 t.integer "user_id" t.index ["user_id"], name: "index_products_on_user_id" またadd_referenceは、foreign_key:trueオプションを追加することで、前述の2つに加えて外部キー制約も同時に設定できます。 例えば、以下の記述をマイグレーションファイルに行ったとします。 add_reference :products, :user, foreign_key:true すると以下のように、前述の2つの記述に加えて、add_foreign_keyの記述がdb/schema.rbに追加されます。 t.integer "user_id" t.index ["user_id"], name: "index_products_on_user_id" add_foreign_key "products", "users" (参考)add_referenceとt.referencesの機能は基本的に同じ add_referenceとcreate_tableのブロックの中で呼び出すt.referencesは基本的に同じ機能を提供します(オプション以外の引数の部分で違いはありますが。) 実際にt.referencesへ渡せるオプションはadd_referenceと同じです。 また、t.referencesの実装とadd_referenceの実装のどちらもReferenceDefinition.newを内部で呼ぶ形になっています(v8.1.2で確認)。 Write Preview How to write in Markdown
@wakairo 30 Jan, 2026 12:14 +00:00 Railsガイドを一読しただけでは、 add_foreign_keyとadd_referenceが、それぞれどのようなもので、どう違うのかがいまいちよく分かりませんでした。 そこで、add_foreign_keyとadd_referenceによってdb/schema.rbがどのように変化するかを基に、 それぞれの機能について確認してみました。 add_foreign_key add_foreign_keyは外部キー制約の追加だけを行います。よって、カラムやインデックスの追加は行いません。 外部キー制約とは、子テーブルが参照している親のIDが親テーブルに存在することをデータベースレベルで保証する制約です。 例えば、以下の記述をマイグレーションファイルに行ったとします。 add_foreign_key :products, :users すると以下の記述がdb/schema.rbに追加されます。 add_foreign_key "products", "users" この記述は、products(子テーブル)のuser_idカラムに登場するIDが、users(親テーブル)のidカラムに必ず存在するように制約をかけています。 add_reference add_referenceは、テーブル間の関連付けに関する複数の設定を一度に行える便利メソッドです。 add_referenceの基本機能は、カラムとインデックスの追加です。 例えば、以下の記述をマイグレーションファイルに行ったとします。 add_reference :products, :user すると以下のように、users(親テーブル)に関連付ける2つの記述、具体的にはuser_idのカラムとインデックスをproducts(子テーブル)に追加する2つの記述が、db/schema.rbに追加されます。 t.integer "user_id" t.index ["user_id"], name: "index_products_on_user_id" またadd_referenceは、foreign_key:trueオプションを追加することで、前述の2つに加えて外部キー制約も同時に設定できます。 例えば、以下の記述をマイグレーションファイルに行ったとします。 add_reference :products, :user, foreign_key:true すると以下のように、前述の2つの記述に加えて、add_foreign_keyの記述がdb/schema.rbに追加されます。 t.integer "user_id" t.index ["user_id"], name: "index_products_on_user_id" add_foreign_key "products", "users" (参考)add_referenceとt.referencesの機能は基本的に同じ add_referenceとcreate_tableのブロックの中で呼び出すt.referencesは基本的に同じ機能を提供します(オプション以外の引数の部分で違いはありますが。) 実際にt.referencesへ渡せるオプションはadd_referenceと同じです。 また、t.referencesの実装とadd_referenceの実装のどちらもReferenceDefinition.newを内部で呼ぶ形になっています(v8.1.2で確認)。
Railsガイドを一読しただけでは、 add_foreign_keyとadd_referenceが、それぞれどのようなもので、どう違うのかがいまいちよく分かりませんでした。 そこで、add_foreign_keyとadd_referenceによって
db/schema.rbがどのように変化するかを基に、 それぞれの機能について確認してみました。add_foreign_key
add_foreign_keyは外部キー制約の追加だけを行います。よって、カラムやインデックスの追加は行いません。
外部キー制約とは、子テーブルが参照している親のIDが親テーブルに存在することをデータベースレベルで保証する制約です。
例えば、以下の記述をマイグレーションファイルに行ったとします。
すると以下の記述が
db/schema.rbに追加されます。この記述は、products(子テーブル)のuser_idカラムに登場するIDが、users(親テーブル)のidカラムに必ず存在するように制約をかけています。
add_reference
add_referenceは、テーブル間の関連付けに関する複数の設定を一度に行える便利メソッドです。
add_referenceの基本機能は、カラムとインデックスの追加です。 例えば、以下の記述をマイグレーションファイルに行ったとします。
すると以下のように、users(親テーブル)に関連付ける2つの記述、具体的にはuser_idのカラムとインデックスをproducts(子テーブル)に追加する2つの記述が、
db/schema.rbに追加されます。またadd_referenceは、
foreign_key:trueオプションを追加することで、前述の2つに加えて外部キー制約も同時に設定できます。 例えば、以下の記述をマイグレーションファイルに行ったとします。すると以下のように、前述の2つの記述に加えて、add_foreign_keyの記述が
db/schema.rbに追加されます。(参考)add_referenceとt.referencesの機能は基本的に同じ
add_referenceとcreate_tableのブロックの中で呼び出すt.referencesは基本的に同じ機能を提供します(オプション以外の引数の部分で違いはありますが。) 実際にt.referencesへ渡せるオプションはadd_referenceと同じです。 また、t.referencesの実装とadd_referenceの実装のどちらも
ReferenceDefinition.newを内部で呼ぶ形になっています(v8.1.2で確認)。