Many to many

Two ways to represent a many-to-many relationship.

  1. has_and_belongs_to_many
  2. has_many :through

jruby script/generate model category name:string
jruby script/generate/model product name:string
jruby script/generate migration create_categories_products_join

# Open the migration.
class CreateCategoriesProductsJoin < ActiveRecord::Migration

def self.up
create_table ‘categories_products’, :id => false do |t|
t.column ‘category_id’, :integer
t.column ‘product_id’, :integer
end
end

def self.down
drop_table ‘categories_products’
end

end

# Create the tables
jruby -S rake db:migrate

# Edit the Category and Product models
class Product < ActiveRecord::Base
has_and_belongs_to_many :categories
end

class Category < ActiveRecord::Base
has_and_belongs_to_many :products
end

has_and_belongs_to_many has a limitation.
You cannot add more columns to the join table.
What if you wanted to add more data associated with the join?
has_many :through is more flexible, but requires a new model.

jruby script/generate model categorization product_id:integer category_id:integer position:integer created_at:datetime

jruby -S rake db:migrate

# Edit the Categorization model.
class Categorization < ActiveRecord::Base
belongs_to :product
belongs_to :category
end

# Edit the Product model.
class Product < ActiveRecord::Base
has_many :categorizations
has_many :categories, :through => :categorizations
end

# Edit the Category model.
class Category < ActiveRecord::Base
has_many :categorizations
has_many :categories, :through => :categorizations
end

Ask yourself…

  1. Storing extra information in the join?
  2. Treating the join like its own model?

If you answer “yes” to either of the above, you need has_many :through.

~ by bandwagonblog on January 17, 2009.

Leave a Reply