6.6. Polymorphic Associations

Sometimes you'll have an ActiveRecord class with a relationship that could apply to objects in multiple classes. Tagging is an example you've already seen, where the tag class might relate to any ActiveRecord model in your system. Or, in a business system, an address table might relate to either a supplier or a customer, each of which has its own separate table. In SoupsOn Line, you might use a rating system where both recipes and users have ratings. Rails makes setting up this kind of relationship reasonably straightforward.

You need to have some kind of common name for whatever feature all the different classes on the receiving end of the relationship might have in common — something like "taggable" or "addressable" or "rateable." This is something vaguely like a Java interface. Unlike Java, Rails doesn't create anything like a class with that kind of actual existence in the code. The name you choose for this relationship is completely up to you, but you do have to be consistent. For this example, you'll create a Rating class, and use ratable for the interface. Enter the following to begin:

$ ruby script/generate model rating --svn

From the Rating side, you declare the relationship in terms of the arbitrary interface name, as follows:

class Rating < ActiveRecord::Base
  belongs_to :ratable, :polymorphic => true
end

Thanks to the :polymorphic option, this will work even though there is no Ratable class. On the other side of the relationship, the

Get Professional Ruby on Rails™ now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.