railsでポリモーフィック関連のある中間テーブルにthroughを定義する方法を調べたので忘備録です。便利だけどあまり、情報が落ちてないです。
説明すること/しないこと
-
説明すること
RailsのActiveRecordにおいて、ポリモーフィック関連が定義されてる中間テーブルがある場合のthroughの定義方法。 -
説明しないこと
ポリモーフィック関連やthrough関連の詳細な説明。
通常のthrough関連付け
companyは複数のeventを主催することができ、また、複数のcompanyが共同でeventを主催できます。この場合、以下のような関連付けを定義します。
model.rb
class Company < ApplicationRecord
has_many :event_owners
has_many :events, through: :event_owners
end
class EventOwners < ApplicationRecord
belongs_to :company
belongs_to :event
end
class Event < ApplicationRecord
has_many :event_owners
has_many :companies, through: :event_owners
end
するとEventOwnerを介してevetに紐づく複数のcompanyを以下のように取得することができます。
> event.companies
=> # [company1, company2]
さて、ここまでは知っての通りです。
ポリモーフィック関連でのthrough関連
それではここで、comapnyの他に一般のuserもイベントを開催できるようになった場合を考えてみます。関連図は以下のようになります。
ではさっそく、ポリモーフィック関連を定義してみましょう。
model.rb
class Company < ApplicationRecord
has_many :event_owners, as: :eventable
has_many :events, through: :event_owners
end
class User < ApplicationRecord
has_many :event_owners, as: :eventable
has_many :events, through: :event_owners
end
class EventOwners < ApplicationRecord
belongs_to :event
belongs_to :eventable, polymorphic: true # ポリモーフィック関連
end
class Event < ApplicationRecord
has_many :event_owners
# 以下がポリモーフィックなthrough関連
has_many :companies, through: :event_owners, source: :eventable, source_type: 'Company'
has_many :users, through: :event_owners, source: :eventable, source_type: 'User'
end
through関連でsourceを定義することで、以下のようにeventに関連するuser or companyを取得することができます。
> event.companies # or event.users
=> # [company1, company2]
ちょっと前まで知らなかったけどめっちゃ便利やん!