Rails のポリモーフィック関連付けについて理解する
ラブグラフでインターンをしているりょうさんです!
Rails には、ポリモーフィック関連付けという機能があります。これは、ある1つのモデルが他の複数のモデルに属していることを、1つの関連付けだけで表現できるという機能です。
今回は、このポリモーフィック関連付けについて、あまり理解ができていなかったので、この記事を通して整理していこうと思います。
具体例
以下の状況を仮定しましょう。
学校における「コメント」機能を実装したいとします。
- 生徒の日記にコメントをつけたい
- 先生のお知らせにコメントをつけたい
- 部活動のブログ記事にコメントをつけたい
素直にコメント機能を作成しようとすると、
class Comment < ApplicationRecord
belongs_to :student_diary, optional: true
belongs_to :teacher_notice, optional: true
belongs_to :club_blog, optional: true
end
このように、たくさん belongs_to
が増えて、どれにコメントしてるかが曖昧になったり、テーブル設計が複雑になります。
ここで登場するのが、Rails のポリモーフィック関連付けです。
ポリモーフィック関連付けの設計
まず、コメント(Comment)モデルは、どのモデルにも紐づけられるようにテーブルを定義します。
# db/migrate/xxxx_create_comments.rb
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.text :content
t.references :commentable, polymorphic: true, null: false
t.timestamps
end
end
end
次に、コメントを受け取る側のモデルで関連付けを宣言します。
class Comment < ApplicationRecord
belongs_to :commentable, polymorphic: true
end
class StudentDiary < ApplicationRecord
has_many :comments, as: :commentable
end
class TeacherNotice < ApplicationRecord
has_many :comments, as: :commentable
end
class ClubBlog < ApplicationRecord
has_many :comments, as: :commentable
end
ここにおける commentable
というのは、コメントされる「対象」や「親」となる任意のモデル を指す、抽象的な役割名 です。
この例では、StudentDiary
、TeacherNotice
、ClubBlog
のそれぞれが commentable なオブジェクトとして振る舞い、共通の Comment
モデルと関連付けを持つことができます。
すると、Railsは commentable_type
と commentable_id
というカラムを見て、
-
commentable_type = "StudentDiary"
,commentable_id = 1
→ 生徒の日記の1番に対するコメント -
commentable_type = "TeacherNotice"
→ 先生のお知らせ -
commentable_type = "ClubBlog"
→ 部活ブログ
という風に、どのモデルに属しているかを判断してくれるのです!
この2つのカラムは公式でも、
ポリモーフィック関連付けを手動でセットアップする場合は、以下のようにモデルで外部キーカラム(imageable_id)とtypeカラム(imageable_type)の両方を宣言する必要があります。
とあるため、この2つのカラムは存在しています。
mermaid で図解
実際にどのような関連なのか、図で見てみましょう。
クラス図
まとめ
ポリモーフィック関連付けを使うことで、1つのコメントモデルで複数のモデルに対してコメント機能を共通実装できます。テーブル設計・モデル宣言のシンプルさが大きなメリットです。
参考記事
Discussion