再・ポリモーフィック関連について

ポリモーフィック関連とは

ポリモーフィック関連とは、ある1つのカラムが複数のテーブルを参照しているようなパターンの関連を表したものです。

同じようなカラムを持っているテーブルが複数ある場合、それらを1つのテーブルで管理してしまうことができます。複数のクラスのインターフェースを統一し、同じように扱えるようになります。

 

 

 メリット

 ・どのクラスに属するものかを意識することなく関連するレコードにアクセスできます。
 ・特定の外部キーを持たず、1つのカラムで複数のテーブルを管理しているため、新たに管理するモデルが増えたとしてもカラムを追加したり、テーブルを追加することなく、has_manyの関連を定義してやるだけでよいです。

 

ポリモーフィック関連を使わなかった場合

外部キーを関連するモデルの数だけカラムとして増やす or テーブルを増やす必要があります。

*外部キーを関連するモデルの数だけカラムとして作った場合のデメリット

→新たにタイムラインが従属するモデルを作った際、タイムラインのbelongs_toを増やし、カラムも追加しないといけなくなります。

→タイムラインモデルのインスタンスから直接、従属しているモデル(questionなのかanswerなのか)を判断することができません。

*関連するモデルが増えるとテーブルの数もどんどん増えていくことになります。

 

 

 具体例

Food、Shopというモデルがあるとします。それぞれにReviewモデルをポリモーフィック関連で紐づけたい場合、以下のように定義してあげることが出来ます。

review.rb

class Review < ApplicationRecored
belongs_to :comment, polymophic: true
end

 

カラム
・id
・comment_id
・comment_type
・text

 

food.rb

class Food < ApplicationRecord
has_many :reviews, as: :comment
end

 

カラム
・id
・name

 

shop.rb

class Shop < ApplicationRecord
has_many :reviews, as: :comment
end

 

カラム

・id
・name

 

こうすることで、以下のようにReviewクラスのインスタンスから、どのモデルと紐づいているのか意識することなく、関連先のインスタンスの情報を作成・取得することが出来ます。

 

#レコード作成

food = Food.create(name: "potato")
food.reviews.create(text: "good")

shop = Shop.create(name: "familymart")
shop.reviews.create(text: "my favorite store")
shop.reviews.create(text: "it is exiting")

 

 

#レコード取得

food.reviews.each do |review|
puts review.text
end

=> potato

shop.reviews.each do |review|
puts review.text
end

=> my favorite store
=> it is exiting

Review.all.each do |review|
puts review.comment.name
end

=> potato
=> familymart
=> familymart