[Railsガイド](https://railsguides.jp/active_record_migrations.html)を一読しただけでは、 add_foreign_keyとadd_referenceが、それぞれどのようなもので、どう違うのかがいまいちよく分かりませんでした。 そこで、add_foreign_keyとadd_referenceによって`db/schema.rb`がどのように変化するかを基に、 それぞれの機能について確認してみました。 ## add_foreign_key add_foreign_keyは外部キー制約の追加だけを行います。よって、カラムやインデックスの追加は行いません。 外部キー制約とは、子テーブルが参照している親のIDが親テーブルに存在することをデータベースレベルで保証する制約です。 例えば、以下の記述をマイグレーションファイルに行ったとします。 ```ruby add_foreign_key :products, :users ``` すると以下の記述が`db/schema.rb`に追加されます。 ```ruby add_foreign_key "products", "users" ``` この記述は、products(子テーブル)のuser_idカラムに登場するIDが、users(親テーブル)のidカラムに必ず存在するように制約をかけています。 ## add_reference add_referenceは、テーブル間の関連付けに関する複数の設定を一度に行える便利メソッドです。 add_referenceの基本機能は、カラムとインデックスの追加です。 例えば、以下の記述をマイグレーションファイルに行ったとします。 ```ruby add_reference :products, :user ``` すると以下のように、users(親テーブル)に関連付ける2つの記述、具体的にはuser_idのカラムとインデックスをproducts(子テーブル)に追加する2つの記述が、`db/schema.rb`に追加されます。 ```ruby t.integer "user_id" t.index ["user_id"], name: "index_products_on_user_id" ``` またadd_referenceは、`foreign_key:true`オプションを追加することで、前述の2つに加えて外部キー制約も同時に設定できます。 例えば、以下の記述をマイグレーションファイルに行ったとします。 ```ruby add_reference :products, :user, foreign_key:true ``` すると以下のように、前述の2つの記述に加えて、add_foreign_keyの記述が`db/schema.rb`に追加されます。 ```ruby 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と同じ](https://api.rubyonrails.org/classes/ActiveRecord/ConnectionAdapters/TableDefinition.html#method-i-references)です。 また、[t.referencesの実装](https://github.com/rails/rails/blob/v8.1.2/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb#L543)と[add_referenceの実装](https://github.com/rails/rails/blob/v8.1.2/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb#L1095)のどちらも`ReferenceDefinition.new`を内部で呼ぶ形になっています(v8.1.2で確認)。