---
title: for the record
teaser:
tags: web,rails
author: Jared Carroll
published_on: 2007-09-12
---

Ok, I just want to set this one in stone.

Rails' polymorphic associations.

Ask yourself 2 questions:

Can this object belong to more than 1 **type** of object

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

class House < ActiveRecord::Base
end

class LineItem < ActiveRecord::Base

  belongs_to :salable, :polymorphic => true

end
```

Here's a domain model from an app in which you can purchase both cars and
houses.  They are both salable products that will appear on a line item in an
order.  This is a many-to-1 relationship from a `LineItem` to its salable
product.

Can this object belong to more than 1 **type** of object and more
than 1 object

```ruby
class User < ActiveRecord::Base

  include Groupable

end

class Account < ActiveRecord::Base

  include Groupable

end

class Membership < ActiveRecord::Base

  belongs_to :groupable, :polymorphic => true
  belongs_to :group

end

class Group < ActiveRecord::Base

  has_many :memberships

end

module Groupable

 def self.included(clazz)
    clazz.class_eval
      has_many :memberships, :as => :groupable
    end
  end

end
```

Here we have a many-to-many between groupable objects and groups.  Since a
`Group` can contain members of different types it needs to be polymorphic.
However, in this example a single group can have multiple members all of
different types.  Like any many-to-many we need a table between the 2 other
tables.  Since habtm doesn't support polymorphic associations we have to go with
a join model.  So we introduced `Membership` and made it have a polymorphic
relationship.

It'd be sweet if we didnt need this join model because I can't stand unnecessary
classes, something like:

```ruby
class User < ActiveRecord::Base

  include Groupable

end

class Account < ActiveRecord::Base

  include Groupable

end

class Group < ActiveRecord::Base

  has_and_belongs_to_many :groupables

end

module Groupable

  def self.included(clazz)
    clazz.class_eval
      has_and_belongs_to_many :groups, :as => :groupable
    end
  end

end
```

db schema:

    groupables (groupable_id, groupable_type, group_id)

That's some made up syntax.  I'll say if you have an `:as` parameter to
`#has_and_belongs_to_many` then Rails will look for a table named after the
polymorphic interface, in this case `groupables`, and 2 columns `groupable_id`
and `groupable_type`.  Since the `#has_and_belongs_to_many` call in the `Group`
model doesn't include an `:as` parameter, Rails will, like in a normal
`#has_and_belongs_to_many` call, look for a table named after the association, in
this case `groupables`, and a foreign key in that table referencing this model,
in this case `group_id`.
