ruby 54 lines · 8 steps

How polymorphic comments work in Rails

A reusable Comment model attaches to any model through a polymorphic association and a shared concern.

Explained by highlit
1class Comment < ApplicationRecord
2 belongs_to :commentable, polymorphic: true, counter_cache: true
3 belongs_to :author, class_name: "User"
4 
5 validates :body, presence: true, length: { maximum: 10_000 }
6 
7 scope :recent, -> { order(created_at: :desc) }
8 scope :approved, -> { where(approved: true) }
9 
10 after_create_commit :notify_commentable_owner
11 
12 private
13 
14 def notify_commentable_owner
15 owner = commentable.try(:owner)
16 return if owner.nil? || owner == author
17 
18 CommentMailer.with(comment: self).new_comment.deliver_later
19 end
20end
21 
22module Commentable
23 extend ActiveSupport::Concern
24 
25 included do
26 has_many :comments, as: :commentable, dependent: :destroy
27 end
28 
29 def add_comment(body:, author:)
30 comments.create(body: body, author: author)
31 end
32end
33 
34class Post < ApplicationRecord
35 include Commentable
36end
37 
38class Photo < ApplicationRecord
39 include Commentable
40end
41 
42class CreateComments < ActiveRecord::Migration[7.1]
43 def change
44 create_table :comments do |t|
45 t.text :body, null: false
46 t.boolean :approved, null: false, default: false
47 t.references :author, null: false, foreign_key: { to_table: :users }
48 t.references :commentable, polymorphic: true, null: false
49 t.timestamps
50 end
51 
52 add_index :comments, [:commentable_type, :commentable_id, :created_at]
53 end
54end
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1A polymorphic association lets one model belong to many different parent types through a type and id pair.
  2. 2Concerns package the parent-side wiring so any model becomes commentable with a single include.
  3. 3A composite index matching your query columns keeps polymorphic lookups and ordering fast.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How polymorphic comments work in Rails — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code