How to use ActiveRecord has_and_belongs_to_many (HABTM) association in Rails
When building an application in Rails, often when we need to create relationship between objects, we'll try look for the correct association that we can use based on our own use case. One of the association is has_and_belongs_to_many, a.k.a HABTM (yep, that acronym exists!). While many articles talks about why one should never use HABTM in place of the has_many..., but I think there's a place for HABTM, in my case, I intend to keep my application small and simple.
Let's assume I have a 2 models, "Programmer" and "Project", a programmer can work on many projects, and a project can have many programmers (obviously right?).
To do this in Rails, I took the following steps.
Generate the migration file
You'd also need to update the model classes to includes the necessary relations.
Let's assume I have a 2 models, "Programmer" and "Project", a programmer can work on many projects, and a project can have many programmers (obviously right?).
To do this in Rails, I took the following steps.
Generate the migration file
rails g migration CreateJoinTableProgrammerProject programmer project
This would generate a migration file like the following:
Uncomment the first line that create the index for [:programmer_id, :project_id]; this will let rails to add the index in the database (choosing the right index depend on how the data are query).
class CreateJoinTableProgrammerProject < ActiveRecord::Migration def change create_join_table :programmers, :projects do |t| # t.index [:programmer_id, :project_id] # t.index [:project_id, :programmer_id] end end end
Uncomment the first line that create the index for [:programmer_id, :project_id]; this will let rails to add the index in the database (choosing the right index depend on how the data are query).
Once the migration file has been configured, run migration to update the schema.rb
rake db:migrate
You'd also need to update the model classes to includes the necessary relations.
# models/programmer.rb class Programmer < ActiveRecord::Base has_and_belongs_to_many :projects end # models/project.rb class Project < ActiveRecord::Base has_and_belongs_to_many :programmers end
Done, a many-to-many has been created relationships between "Programmer" and "Project". If you look under the hood, the migration actually created a joining table called programmers_projects with only two field, the programmer_id and the project_id, and this table have no corresponding model class in the project.
To associate a "Programmer" with a "Project", the codes can be written as follow:
# some_controller.rb
@project = programmer.projects.build(project_params) programmer.save
Important: Notice that the save are called from the programmer object, not the @project object. If you call save from the project, the relationship record won’t be added to the join table.
Comments
Post a Comment