---
title: What's the Deal with Rails' Polymorphic Associations?
teaser: An intro to Rails polymorphic associations for Java developers.
tags: web,rails
author: Jared Carroll
published_on: 2006-12-27
---

The latest big `ActiveRecord` feature to Rails has been polymorphic
associations.  Not very clear at first, I found out they're easier to understand
with a couple examples.

A common one:

```ruby
class Person < ActiveRecord::Base
  has_one :address, :as => :addressable
end

class Company < ActiveRecord::Base
  has_one :address, :as => :addressable
end

class Address < ActiveRecord::Base
  belongs_to :addressable, :polymorphic => true
end
```

This basically allows the address class to `belongs_to` any model.  Which is
nice, the alternative would be to say:

```ruby
class Address < ActiveRecord::Base
  belongs_to :person
  belongs_to :company
end
```

Then you'd have all these foreign keys in your addresses table but you only
would ever have a value for one of them because an address can only belong to a
person or a company but not both.

OK that was the basics.

Now the rails docs refer to the `as` keyword parameter to `has_one` and
`has_many` as specifying a "polymorphic interface."  What is that?

When I think"polymorphic interface", I think something along the lines of the
`<<` message in Ruby. I can send that message to a bunch of different objects
like arrays, strings, IO streams, etc. and they all know what to do when they
receive it.

I think `<<` as a kind of interface that all those different classes implement.
From a statically typed language standpoint, such as Java, it would be as if we
had a nice little hierarchy of classes all implementing a common interface.

Pretending Java allowed operator overloading and `<<` was an operator it might
look like this.

```java
public interface Collection {
  Collection <<(Object anObject);
}
```

And the classes.

```java
public class Array implements Collection {
  public Collection << (Object object) {
    // add object to me
  }
}

public class String implements Collection {
  public Collection << (Object object) {
    // add object to me
  }
}
```

Where am I going with this?  Stay with me here.

Lets rotate the class diagram for the `Person`, `Company`, and `Address` 90
degrees to the left (I don't know how to draw that here but if you write it out
on paper you'll see what I mean) and make `Person` and `Company` inherit from
`Address`.

```ruby
class Address < ActiveRecord::Base
end

class Person < Address
end

class Company < Address
end
```

Now neither a `Person` nor a `Company` are an `Address` so lets instead use that
"polymorphic interface" as our superclass name.

```ruby
class Addressable < ActiveRecord::Base
end

class Person < Addressable
end

class Company < Addressable
end
```

That's better.  A `Person` and a `Company` are addressable but what happened to
the `Address` class.

```ruby
class Addressable < ActiveRecord::Base
  has_one :address
end
```

There we go.  Now `Person` and `Company` `has_one` address, they inherit it from
`Addressable`, and no polymorphic associations.

But wait, inheritance?  More specifically in the Rails world, "single-table
inheritance" (<abbr title="Single Table Inheritance">STI</abbr>) ?  Let's
pretend a `Person` and a `Company` have very little state in common; what does
using (<abbr title="Single Table Inheritance">STI</abbr>) give us?  It's gives
us a giant table with a lot of empty columns for the `Company` attributes when
the row is a `Person` and a lot of empty columns for the `Person` attributes
when the row is a `Company`.

I don't like it.

As more `Addressable`'s come into the system that table is going to get bigger
and bigger.  To me using `Addressable` makes sense, inheritance is about
behavior and not about state and if I was modeling without thinking about a
database I probably would of first came up with using the `Addressable` class.

What can we conclude?  We can say that <abbr title="Single Table
Inheritance">STI</abbr> is basically a way to map an inheritance hierarchy for a
bunch of classes that have a lot of common state not behavior.

Now there are other ways to map an inheritance hierarchy to a relational
database.  In fact there's 3 commonly used ones.  Rails only gives us the
simplest one <abbr title="Single Table Inheritance">STI</abbr>.

* Single Table Inheritance (<abbr title="Single Table Inheritance">STI</abbr>) -
  The whole hierarchy is mapped to a single table with an extra column ("type"
  in Rails) that holds the class name for that row
* One Table per Concrete Class - Each concrete class gets its own table, the
  superclass (like all good superclasses) is abstract and does not get its own
  table.  Any common state in the superclasses is duplicated in each subclass
  table.
* One Table per Class - Each class in the hierarchy gets its own table.
  Subclass tables have foreign keys referencing their corresponding superclass
  row in the superclass table.

For the 2nd one it won't work.  But that last one "One Table per Class" is
interesting.

Back to our `Person`, `Company`, and `Addressable` example.

If we mapped each of those classes to its own table what would or database look
like?

    addressables (id)
    people (id, name, age, height, weight, addressable_id)
    companies (id, size, established_date, addressable_id)
    addresses (id, street, city, state, addressable_id)

Hmmm.  We get to use the nice hierarchy that uses behavior to model inheritance
with `Addressable` as our superclass and we don't have to put all the subclasses
into their own table.  So we got rid of that big ugly <abbr title="Single Table
Inheritance">STI</abbr> table with all those empty columns.  When reading a
`Person` from the database, we'd do a join to `Person`'s superclass table
`addressables` on `addressable_id`.  And to read a `Person`'s address we'd do a
join to `addresses` on `addressable_id`.

So we eliminated polymorphic associations and replaced them with inheritance,
assuming rails supported our inheritance mapping scheme of "One Table per
Class", which it doesn't but lets keep going.  And I like our hierarchy, a
`Person` is `Addressable`, a `Company` is `Addressable` it reads nice and
logical.  One beef.  What's the deal with that `addressables` table?  A table
with one column.  That's weird.  For now, mark it down as a disadvantage and
some ugliness with this method.

But wait.  Here comes another feature.  Users now want to be able tag people and
companies.  We could use the Rails plugin acts\_as\_taggable, which uses
polymorphic associations.  Let's not and keep running with this to see where it
takes us.

A `Taggable` class sounds good.  But wait.  Ruby doesn't allow multiple
inheritance and it doesn't have the Java/C# equivalent of interfaces.  Ruby uses
`modules` instead.  OK so we screwed up.  We should of modeled `Addressable` as
a `module` and not a class.  I say we didn't screw up - we modeled that because
that's what the current requirements were; we didn't know tagging was coming.
That's another agile story.

Anyway, let's try using modules.

```ruby
module Addressable
end

module Taggable
end

class Person < ActiveRecord::Base
  include Addressable
  include Taggable
end

class Company < ActiveRecord::Base
  include Addressable
  include Taggable
end
```

There that's better now Addresses and Companies are both addressable and
taggable.

```ruby
module Addressable
  has_one :address
end
```

Wait, we can't do that in Rails. OK how about this.

```ruby
module Addressable
  def self.included(klazz)  # klazz is that class object that included this module
    klazz.class_eval do
      has_one :address
    end
  end
end
```

There now, each class that includes the `Addressable` module `has_one`
`Address`.  Hold up.  What would our database look like?

    addresses (id, street, city, state, person_id, company_id)

Oh no, we're back to where we started.  An `Address` can't `belongs_to` a
`Person` and a `Company` at the same time.  We need polymorphic associations.

Wow, that was a trip. What did we learn.  At first we started out using
polymorphic associations.  Then we decided to refactor and try modeling in what
I'd call "the more natural way" using inheritance and `Addressable` and
`Taggable` classes.  But we eventually got burnt when a `Person` and a `Company`
both needed to be `Taggable` as well.  So we used Ruby's version of
interfaces/multiple inheritance by using modules.  And that got us right back to
where we started

The moral of the story is this because Rails only allows you to map inheritance
hierarchies using <abbr title="Single Table Inheritance">STI</abbr> plus Ruby's
lack of "interfaces we can't model using interface like classes like
Addressable" and `Taggable`.  Instead we use polymorphic associations and let
them use that "polymorphic interface" for the name of the association:

```ruby
class Address < ActiveRecord::Base
  # here's where we'll use Addressable
  belongs_to :addressable, :polymorphic => true
end

class Tagging < ActiveRecord::Base
  # here's where we'll use Taggable
  belongs_to :taggable, :polymorphic => true
end
```

I like modeling using interfaces such as `Addressable` and `Taggable`.  I really
like the following Java classes.

```java
public interface Addressable {
  Address getAddress ();

  void setAddress (Address address);
}

public class Address {
  private String street;
  private String city;
  private State state;
  private Zipcode zipcode;
  private Addressable addressable;    // anyone who implements Addressable

  // various getters and setters, etc.
}

public class Person implements Addressable {
  private Address address;

  public Address getAddress () {
    return address;
  }

  public void setAddress (Address address) {
    this.address = address;
  }
}

public class Company implements Addressable {
  private Address address;

  public Address getAddress () {
    return address;
  }

  public void setAddress (Address address) {
    this.address = address;
  }
}
```

And for `Taggable`

```java
public interface Taggable {
  Collection getTaggings ();
}

public class Tagging {
  private Taggable taggable;  // anyone who implements Taggable
  private Tag tag;

  // various getters/setters, etc.
}

public class Person implements Addressable, Taggable {
  // Addressable implementation from above
  private Collection taggings;

  public Collection getTaggings () {
    return taggings;
  }
}

public class Company implements Addressable, Taggable {
  // Addressable implementation from above
  private Collection taggings;

  public Collection getTaggings () {
    return taggings;
  }
}
```

In Object-relational mapping (ORM) libraries in the Java/.Net world they provide
all 3 inheritance mapping schemes whereas in Rails you only get <abbr
title="Single Table Inheritance">STI</abbr>.

Were the other 2 inheritance mapping schemes too "enterprise" for Rails?  Too
complicated for DHH to implement?  Nah, Ruby's lack of interfaces make the other
2 schemes not as powerful as in languages that support interfaces e.g. like in
the above example `Addressable` worked fine, but the minute we introduced
`Taggable` i.e. another "interface" we were done for.

And Rails form of "polymorphic associations" aren't found in Java/.Net
object-relational mapping libraries as well.  Of course not, Ruby's use of
modules as a form of multiple inheritance required something unique,
"polymorphic associations" are that something.  Look at the source for the
popular `acts_as_taggable` plugin.  It uses polymorphic associations and it uses
modules to `include` in any shared behavior such as instance and classes
methods.  This is nice.  You call `acts_as_taggable` in your class definition
and you get all this behavior for free.

I'm sorry, but I miss my interfaces.  Looking at the above Java code, you might
say "yeah but look at that `Addressable` and `Taggable` implementation in the
`Person` and `Company` classes its exactly the same, its not <abbr title="Don't
Repeat Yourself">DRY</abbr>.  In Ruby with modules you'd only have to implement
that once and just `include` it into the `Person` and `Company` classes".
That's true but if someone decides to change that module it might break classes
that `include` it - that's another story something called the "brittle base
class".  I also like the fact that its explicit, its duplicated but I can see
the code in both the `Person` and `Company` classes, no messing around in
`$RAILS_ROOT/vendor/plugins`.

Well if you made it through that you're just as crazy as I am.  But I'm scoring
this one a point for Java/C#.  Ruby usually dominates but being able to use
those Java/C# interfaces just seem more natural and better to me.  And the fact
that Rails' polymorphic associations are a new thing, there's definitely a
source of confusion around them in the Rails community.

#### Next Steps & Related Reading

Detect emerging problems in your codebase with [Ruby Science][ruby-science].
We'll deliver solutions for fixing them, and demonstrate techniques for building
a Ruby on Rails application that will be fun to work on for years to come.

[Grab a free sample of Ruby Science today!][ruby-science]

[ruby-science]: http://rubyscience.com?utm_source=giantrobots&amp;utm_medium=blog&amp;utm_campaign=remarket&amp;utm_term=testing
