Many to Many associations in Rails HABTM and has_many :through

We've noticed there's a bit of confusion about the differences between the two ways to create many-to-many relationships using Rails associations. 

Has and Belongs to many (HABTM) or Join Table Associations

create_table "dancers_movies", :id => false do |t|
  t.column "dancer_id", :integer, :null => false
  t.column "movie_id",  :integer, :null => false
end
class Dancer < ActiveRecord::Base
  has_and_belongs_to_many :movies
end

class Movie < ActiveRecord::Base
  has_and_belongs_to_many :dancers
end
 

has_and_belongs_to_many associations are simple to set up. The join table has only foreign keys for the models being joined - no primary key or other attributes.There is no model class for the join table.

has many : through or Join Model associations

create_table "appearances", do |t|
  t.column "dancer_id",      :integer, :null => false
  t.column "movie_id",       :integer, :null => false
  t.column "character_name", :string
  t.column "dance_numbers",  :integer
end

class Appearance < ActiveRecord::Base
  belongs_to :dancer
  belongs_to :movie
end

class Dancer < ActiveRecord::Base
  has_many :appearances, :dependent => true
  has_many :movies, :through => :appearances
end

class Movie < ActiveRecord::Base
  has_many :appearances, :dependent => true
  has_many :dancers, :through => :appearances
end
 

has_many :through associations are pretty easy to set up for the simple case, but can get tricky when using other features like polymorphism. The table for the join model has a primary key and can contain attributes just like any other model.

Conclusion


has_and_belongs_to_many uses a simple join table where each row is just two foreign keys. There's no model class for the join as the join table records are never accessed directly.

has_many :through upgrades the join table to a full-fledged model. It uses a model class to represent entries in the table.

Comments

Popular posts from this blog

Interview Question on Ruby on Rails

Inserting and Moving elements inside Ruby Array