s_kajigo
@s_kajigo (kaji shogo)

Are you sure you want to delete the question?

Leaving a resolved question undeleted may help others!

Rails フォロー機能でfollower_idに外部キー制約は不要なのか

Rialsチュートリアルにてユーザーフォロー機能を学習中です。
教材ではモデル作成の際のmigrationファイルが以下のように実装されています。

class CreateRelationships < ActiveRecord::Migration
  def change
    create_table :relationships do |t|
      t.integer :follower_id
      t.integer :followed_id

      t.timestamps null: false
    end
    add_index :relationships, :follower_id
    add_index :relationships, :followed_id
    add_index :relationships, [:follower_id, :followed_id], unique: true
  end
end

今回疑問に思っているのが、followed_id,follower_idに外部キー制約は不要なのかということです。
外部キー制約については、他テーブルと対応する値の生合成を担保する場合につけておくべきものだと認識していましたが、今回の場合だとどちらのカラムにも存在するuser_idが入ると思われますし、外部キー制約をしておけば、add_indexの記載も不要となるので、foreign_key: { to_table: :users }をつけるべきなのではと思ったのですが、何かの理由があってあえてついていないのでしょうか?

 初歩的な質問かとは思いますが、回答いただけると幸いです。

0

1Answer

今回疑問に思っているのが、followed_id,follower_idに外部キー制約は不要なのかということです。

テキストの少し先に書いてあると思いますが。
Relationshipsテーブル(中間テーブル)のマイグレーション側ではなく、
Userモデル側の関連付けで「follower_id」を外部キーとして指定しています。

リスト 14.2
class User < ApplicationRecord
  has_many :microposts, dependent: :destroy
  has_many :active_relationships, class_name:  "Relationship",
                                  foreign_key: "follower_id",
                                  dependent:   :destroy
  .
  .
  .
end

外部キー制約については、他テーブルと対応する値の生合成を担保する場合につけておくべきものだと認識していましたが、今回の場合だとどちらのカラムにも存在するuser_idが入ると思われますし

今回の場合、
同じUserテーブルのuser_idカラムを参照しているので混乱しますが、
followed_id、follower_idという外部キーを
Relationshipsという中間テーブルが持っている状態になります。

そして、テキストにも書いてありますが、
[:follower_id, :followed_id], unique: true
と複合キーインデックスを指定することで
必ず一意の組合せ(ユニーク)になるので整合性が担保されることになります。

今回はUserとUserの多:多なので混乱を招いたかもしれませんが、
中間テーブルについてこちらの記事が分かりやすく書いてあるので
もしよろしければ目を通してみてください。

1Like

Comments

  1. @s_kajigo

    Questioner

    回答ありがとうございます。
    とてもスッキリと理解できました。
    貼っていただいた記事も参考にさせていただき、理解が深まりました!

Your answer might help someone💌