Ruby.Enterprise?
Rails
HABTM - Has and Belongs to Many
 in 

This article shows how I used Active Record and HABTM to model a many-to-many relationship between entries and categories in my blog.

First I created a migration to build three tables as follows:


create_table "entries", :force => true do |t|
    t.column "user_id", :integer
    t.column "title", :string
    t.column "body", :text
    t.column "html_body" 
    t.column "last_updated_on", :datetime
    t.column "created_dt", :datetime
 end

create_table "categories", :force => true do |t|
    t.column "name", :string
    t.column "created_dt", :datetime
end

create_table "categories_entries", :id => false, :force => true do |t|
    t.column "category_id", :integer
    t.column "entry_id", :integer
end

Note that there are two source tables – entries and categories, and one association table called categories_entries where the association table is made up of two foreign key columns or one primary key from each of the two source tables.

Next I created the models.


class Entry < ActiveRecord::Base
  has_and_belongs_to_many :categories
end

class Category < ActiveRecord::Base
  has_and_belongs_to_many :entries, :order => "created_dt desc" 
end

The main thing to note here is that models are only created for the two source tables and no model is needed for the association table.

And that’s all it took to model my many-to-many relationship using HABTM.

One thing that is very cool about Ruby is the Ruby console. You can use the Ruby console and Active Record to access your domain and to verify that your HABTM is working correctly.

To start the Ruby console I navigated to my application root and typed the following:


c:\rails\tomaso>ruby script/console

This resulted in the following message and prompt:


Loading development environment
>>

To get a list of all entries I typed the following:


>> entrys = Entry.find(:all)

Next to select a single entry from my list of entries I typed the following:


>> entry = entrys[1]

Finally, to verify HABTM I typed the following to get a list of categories for the entry that I had selected.


>> entry.categories

To verify the other side of my HABTM I typed the following to get a list of entries fo a selected category.


>> cats = Category.find(:all)
>> cat = cats[1]
>> cat.entries