Many to many
Two ways to represent a many-to-many relationship.
- has_and_belongs_to_many
- 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…
- Storing extra information in the join?
- Treating the join like its own model?
If you answer “yes” to either of the above, you need has_many :through.

Leave a Reply