ポリモーフィックとは
1つのモデルが他の複数のモデルに属していることを、1つの関連付けだけで表現できます。
一つのモデルを同じインターフェースを持ったものが扱う(ダックタイピングする)
ポリモーフィックとは1つのモデルで関連付いた複数のモデルの処理を共通化することです。
実装例
例) 本(Book)、日報(Report)からコメント(Comment)を作成する
- 親モデル
- Book
has_many :comments
- Report
has_many :comments
- Book
- 子モデル
ポリモーフィックなCommentモデルを作成する
- 外部キー制約付きカラムなので
:references
- [【Rails】外部キー制約とは? - 時々とおまわり https://karlley.hatenablog.jp/entry/2023/01/04/165450]
- ポリモーフィック用のカラムは
{polymorphic}
も追加で指定
ポリモーフィック用でcommentable
カラムを追加する
$ rails g model Comment commentable:references{polymorphic}
上記コマンドでポリモーフィックに必要な以下の2つのカラムが作成される
# schema.rb ... create_table "comments", force: :cascade do |t| t.string "commentable_type", null: false #ポリモーフィック用カラム t.integer "commentable_id", null: false #ポリモーフィック用カラム t.datetime "created_at", precision: 6, null: false t.datetime "updated_at", precision: 6, null: false t.index ["commentable_type", "commentable_id"], name: "index_comments_on_commentable" end
関連付け
rails db:migrate
後に以下の関連付けを行う
- 子モデルCommentには
belongs_to
は自動付与される - 親モデルBook、Reportには
has_many
は自動付与されない(手動での付与が必要)
# book.rb class Book < ApplicationRecord has_many :comments, as: :commentable end # report.rb class Report < ApplicationRecord has_many :comments, as: :commentable end # comment.rb class Comment < ApplicationRecord belongs_to :commentable, polymorphic: true end
railsコンソールで操作してみる
# ReportからCommentを作成 > report = Report.first > report.comments.create => #<Comment:... id: nil, commentable_type: "Report", commentable_id: 1, created_at: nil, updated_at: nil> # BookからCommentを作成 > book = Book.first > book.comments.create => #<Comment:... id: nil, commentable_type: "Book", commentable_id: 2, created_at: nil, updated_at: nil>
commentable_type
にはポリモーフィックで関連付けられたモデル名が入るcommentable_id
には関連付けられた親モデルのIDが入る
感想
前に調査した際のメモが残っていたのでもったいないので記事にしてみたシリーズ第一弾(笑) 絶対忘れる未来の自分の為にたくさん記事にしていこう。
参照
Active Record の関連付け - Railsガイド
Railsのポリモーフィック関連とはなんなのか - Qiita