6時だョ!!全員集合!!

Rails・JavaScrictを中心にアウトプットします。

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で投稿に良いねしたユーザーの一覧を取得します。

参考

Railsガイド Active Record の関連付け
Qiita-やさしい図解で学ぶ 中間テーブル 多対多 概念編