One association, several possible types

Free preview 3 min to read

Every association so far pointed at one kind of model

ActiveRecord associations: has_one/through covered belongs_to, has_many, has_one and :through, and each of them pointed at one other kind of model. Catalog::Lesson belongs_to :course always means a Catalog::Course on the other end. That fixed type is built into course_id: an integer column that only ever means a row in the courses table.

A comment that needs two homes

Picture a Comment model that has to attach to either an Article or a Photo: one comment thread under a blog post, another under an image. The previous course suggests two ordinary belongs_to lines:

class Comment < ApplicationRecord
  belongs_to :article, optional: true
  belongs_to :photo, optional: true
end

This works, but it has cracks. Nothing stops one comment row from having both article_id and photo_id set, or neither. Every new commentable type, say a course review or a lesson note, means another nullable column on the same table. And both lines need optional: true, because Rails 8 requires a belongs_to by default (lesson 1 of the previous course), and that requirement doesn't fit here.

The question this course answers

What if one association could point at either kind of model, decided per row, with no extra column for each new type? That's what a polymorphic association does, and it's the subject of this course: one association, several possible types, resolved at runtime instead of fixed by a single target column.

What's ahead

Lesson 2 introduces the two columns a polymorphic belongs_to needs and what each one stores. Lesson 3 covers the reverse side, has_many ..., as: :commentable, on each possible type. Lesson 4 covers dependent: :destroy and a trap worth knowing. Lesson 5 shows the same mechanism inside this app's own code, where it has been running unnoticed. Lesson 6 covers querying by type, and lesson 7 ties it together.

Key takeaways

  • Every association in ActiveRecord associations: has_one/through pointed at one fixed kind of model. This course covers one association that has to point at several kinds.
  • The naive fix, one nullable belongs_to column per type, allows invalid combinations (both set, or neither) and needs a new column for every new type.
  • A polymorphic association solves this with one association resolved per row instead of one column per type.
  • The seven lessons go from the two required columns, through the reverse side and dependent:, to an example already in this app and querying by type.
Lesson 1 of 7 · free

Keep going with lesson 2

The two columns a polymorphic belongs_to needs

Explains the commentable_type and commentable_id columns and how reading commentable returns the original row.

A free account also gives you the quizzes, your progress and notes, and the discussion.

Type to start searching...