2022年5月5日 Railsガイド Active Record の関連付け
has_many :through 関連付け
Physician・・・・医者
Appointment・・・診察予約
Patient・・・患者
class Physician < ApplicationRecord has_many :appointments has_many :patients, through: :appointments end class Appointment < ApplicationRecord belongs_to :physician belongs_to :patient end class Patient < ApplicationRecord has_many :appointments has_many :physicians, through: :appointments end
- 医者は、複数の診察予約を持つことができ、複数の患者を担当することが出来ます。
- 患者は、複数の診療予約を持つことができ、複数の医者から担当されることが出来ます。
- 診療予約にはどの医者とどの患者が関連付けされているかを、2つの外部キーで判断することが出来ます。
- throughオプションで2つの外部キーを持つ診療予約を参照することできます。
- physician.patientsで医者に診療予約した患者のリストを出すことが出来ます。
- patient.physiciansで患者が担当される医者のリストを出すことが出来ます。
中間テーブルの存在意義
usersとcourcesテーブルがあるとして、多対多のアソシエーションを直接紐付けると、1カラムの中にデータは1つずつしか入れられないため、1人のuserがいくつのcourceを選択するかわからないため、選択をしなかった場合に空のカラムができてしまい良くないテーブル設計になってしまいます。
ここで中間テーブルでそれぞれのuser_idとcources_idという外部キーを持たせたテーブルを用意する事で、空のカラムを作る事なく多対多のアソシエーションを組むことができます。
中間テーブルを使わない場合のデメリット
カラム数が多くなる
未使用(NULL)のカラムが多くなる
NULLが沢山入ってしまうアンチパターンという良くない設計になる
中間テーブルとは?
"join table もしくは junction table"とも呼ばれ、その名の通り、2つのテーブルの中間にもう一つ、それぞれに接続されたテーブルを指します。
中間テーブルには、接続先の外部キー同士を紐付けて格納しています。
例) twitterの良いね機能を考えます。 この場合、良いねする人(userテーブル)と良いねされる投稿(boardテーブル)があります。1人のユーザーは、複数の投稿に良いねでき、1つの投稿に対して複数のユーザーから良いねをもらうことができます(多対多)。このような場合に中間テーブルを使うことで良いねしたユーザーのuser_idと良いねされた投稿のboard_idをそれぞれ紐づけて格納してくれます。中間テーブルを使う場合、throughを使います。
class User < ApplicationRecord has_many :boards has_many :favorites # 中間テーブルと紐づけるための記述 has_many :favorite_boards, through: :favorites, source: :board end # いいねする人といいねした投稿を紐付ける中間テーブル # 外部キーであるuser_idとboard_idを格納しています。 class Favorite < ApplicationRecord belongs_to :user belongs_to :board end class Board < ApplicationRecord has_many :users has_many :favorites # 中間テーブルと紐づけるための記述 has_many :favorite_users, through: :favorites, source: :user end
user.favorite_boards
でユーザーが良いねした投稿の一覧を取得します。board.favorite_users
で投稿に良いねしたユーザーの一覧を取得します。