目的・前提
Ruby on Railsではテーブル作成に使うマイグレーションファイルにテーブルの依存関係を数行追加するだけで
簡単に依存関係が構築できます。しかし、僕はいつもチュートリアルを読むとき、「どこまでがRuby on Railsで推測してくれるのか」についてわからなくります。
今回は、マイグレーションファイルで使用する.references型についてまた不明点がでてきましたので、現時点で調べた結果を記載します。
Railsチュートリアル「13.1.1 基本的なモデル」より
https://railstutorial.jp/chapters/user_microposts?version=5.1#sec-the_basic_model
内容としては、
・テーブル「Users」で管理されているユーザが、ツイッターのようなテキストを投稿する。
・テーブル「Microposts」でユーザが投稿したテキストを管理する。
なのですが、Micropostsで管理されるテキストがどのユーザが投稿したものなのかを管理吸うために2つのテーブルを紐付ける必要があります。
そのために、「Microposts」にあるカラム「user_id」は「Users」テーブルの「id 」カラムと紐付けることにします。という処理が必要になります。
下記2テーブルの関係について記載します。
#図1, 図2はいずれもRuby on Rails チュートリアル: 実例を使って Rails を学ぼうより引っ張ってきています。
コード
class User < ApplicationRecord
has_many :microposts, dependent: :destroy
#micropostモデルに依存されています、という記載
#userモデルのレコードを削除したらそれに紐付いたmicropostモデルの記事も削除される
end
class Micropost < ApplicationRecord
belongs_to :user
#userモデルに依存します、という記載
end
class CreateMicroposts < ActiveRecord::Migration[5.1]
def change
create_table :microposts do |t|
t.text :content
t.references :user, foreign_key: true
#userモデルに外部制約キーを付ける
t.timestamps
end
add_index :microposts, [:user_id, :created_at]
#user_idにindexを付ける
end
end
Micropostモデルに記載のbelongs_to :userについて
belongs_to関連付けを行なうと、他方のモデルとの間に「1対1」のつながりが設定されます。
"belongs_to :user"と記載すれば、Usersモデルのテーブル「Users」でデフォルトで必ず作成される「id」に依存する、とRailsで判断されます。
依存するとは、例えば、テーブル「Users」の「id」が「10」であるユーザが削除されると、そのユーザが投稿したテキストも自動的に削除される、ということです。
この関連付けのためにはUserモデルの方でも記載が必要です。
それが"has_many :microposts"です。
Userモデルに記載の"has_many :microposts"について
has_many関連付けが使用されている場合、そのモデルのインスタンスは、反対側のモデルの「0個以上の」インスタンスを所有します。
「2.3 has_many関連付け」より
この場合の"反対側"とは"belongs_to :user"を記載したMicropostモデルを指します。つまり
・belongs_to :user : Userモデルに依存します。
・has_many :microposts : たくさんのMicropostモデルを所有します。
という親「Userモデル」、子「Micropostモデル」の関係がこれで築かれます。
"dependent: :destroy"によって、もしUsersテーブルにあるユーザが削除されたとき、そのユーザが作成したMicropostの記事は連動して削除されます。
t.references :user, foreign_key: trueについて
".references"を記載すると”指定したモデル名_id”のカラムが追加されます。
この場合":user"と記載しているので、カラム"user_id"が追加されます。
同時にuser_idにはindexが付与されます。なので単にindexを付与するための下記の記載は不要となります。
index: true
"foreign_key: true"を記載すると指定したモデル名_idに外部キー制約を付与します。つまりこのuser_idからむはモデル「User」で作成されたテーブル「Users」のデフォルトで必ず作られる「id」を参照して紐づけます。
残った課題
上記でUserモデルとMicropostモデルの依存関係の構築は完了しましたが、.referencesで指定した際に自動的にindexが付与されのであれば
add_index :microposts, [:user_id, :created_at]
の行がいらないはずです。これはRailsチュートリアルの後の章で説明される複合キーインデックスを扱うために必要とのことです。
それについて、覚えていたら後から記載しようと思います。

