---
title: Rails has_and_belongs_to_many conveniences
teaser:
tags: web,rails
author: Eric Torrey
published_on: 2007-08-14
---

The other day, I was developing an ordering system.  In this system, an order
has many items and each item has a price.  I also needed to store how many of
each item was being purchased.  So I used my old friend habtm, and noticed that
a simple join table wouldn't be enough, I would need to store a quantity for
each item sold. From the Rails docs:

> Deprecated: Any additional fields added to the join table will be placed as
> attributes when pulling records out through `has_and_belongs_to_many`
> associations. Records returned from join tables with additional attributes
> will be marked as ReadOnly (because we can't save changes to the additional
> attrbutes). It's strongly recommended that you upgrade any associations with
> attributes to a real join model.

So I used a join model, but kept to the Rails naming convention for join tables
and script/generated a model called `items_orders`, and my three models looked
something like this:

```ruby
class Item < ActiveRecord::Base
  has_and_belongs_to_many :orders
end

class Order < ActiveRecord::Base
  has_and_belongs_to_many :items
end

class ItemsOrders < ActiveRecord::Base
  belongs_to :item
  belongs_to :order
  validates_presence_of :quantity
end
```

From my ItemsOrders join model, I can access the quantity for each item.  From
script/console:

```ruby
>> item = Item.create :price => 100, :name => 'Giant robot'
>> order = Order.create
>> items_orders = ItemsOrders.create :item => item,
  :order => order, :quantity => 10
>> items_orders = ItemsOrders.create :item => item,
  :order => order, :quantity => 5

>> order.items.collect{ |each| each.quantity }
=> ["10", "5"]

>> item.quantity
  NoMethodError: undefined method `quantity' for #<Item:0xb777aa30>
```

You'll notice that item itself does not understand quantity, but when accessed
through an order with a habtm association it does.  This allows me more access
to order specific information, so later in the view I can do things like this:

```erb
<h1>Order summary</h1>
<% @order.items.each do |each| -%>

    <%= each.name %> <%= each.price %>
    <%= each.quantity %>, Total: <%= each.quantity * each.price %>

<% end -%>
```
