Convert a Rails association from “has and belongs to many” to “has many through”

All steps I took to convert an association in my project


There are a lot of blog posts that warn you about not using the Rails has_and_belongs_to_many association since you can’t predict when you will need additional functionality on the join model.

I did it anyways. Of course I ended up having to convert to a has_many :through association.

Here’s how I did it.

Original models

Update the associations

Go ahead and change the association on the models right away.

Updating models up front means that the migrations you will write shortly have to work with the updated associations. If you don’t do that you might have problems running the migrations in production.

Create a new join table

The automatic table join was called teams_users and doesn’t have an id.

Create a new table with an id and the belongs_to fields.

Pick a temporary name for the table.

Migrate the data

Here’s the important bit: copy all the rows from the old join table to the new one.

Do this by using a local version of the ActiveRecord models with both associations in it.

Local AR classes have both the has and belongs to many association and the has many association

Note that it’s not necessary to have the 2 associations in both the User and Team models, but it doesn’t hurt and I find it helped me write the correct migration code in the up method on the first try.

Drop the old join table

Or keep the old join table for a while until you are sure no data was lost

Rename the new table

Next time I know that I’ll be using a has many through association from the start!

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.