Convert a belongs_to Association to a has_many :through Association in Ruby on Rails
I was tasked with converting a belongs_to
association to a has_many :through
association. The challenge was that the app was live, and there were existing relationships. I was able to convert the belongs_to
association to a has_many :through
association while still maintaining existing relationships by creating a custom migration file, and updating the existing models.
In order to understand how to create this conversion, let’s create a sample app.
If you want to skip ahead to the solution click here.
1. Create a Sample Rails App
Run the following commands in a new terminal window.
2. Create the belongs_to Association
Update the Book and Author models so they are associated with a belongs_to
association.
3. Seed the database
Install Faker and seed the database with sample data.
- Add
gem 'faker', '~> 1.9', '>= 1.9.1'
to yourGemfile
- Run
bundle install
-
Open
seeds.db
and add the following: -
Seed the database by running
rails db:seed
5. Open up the Rails Console by runningrails c
. Confirm there is data in the database by running the following: -
Open up
schema.rb
to confirm the schema looks similar to the following:
At this point we have set up a simple belongs_to
association. This will be the baseline to understanding how to convert a belongs_to
association to a has_many :through
association.
4. Create a Join Table
-
Open a new terminal and run
rails g model BooksAuthors book:references author:references
.The new migration file should render something similar to the following:
-
Update the migration file to use
def up
anddef down
methods. Specifically, add the following:- In the
def up
method usecreate_table
to create a new join table. - In the
def up
method populate the new join table with the existing relationships. - In the
def up
method remove the existingreference
column. - In the
def down
method add areference
column. - In the
def down
method populate the reference column. - In the
def down
method use thedrop_table
method to remove the join table.
- In the
- Update the database by running
rails db:migrate
in a terminal window. -
Open
schema.rb
to confirm the schema looks similar to the following: -
Open the Rails Console by running
rails c
. Enter the following to confirm the data was migrated correctly: -
Update the existing models.
- Update
books_author.rb
- Update
book.rb
- Update
author.rb
- Update
-
Open a terminal window and run
rails c
. Then run the following:
5. Rolling Back The Conversion
If you need to rollback the conversion, follow these steps.
- Open up a terminal window and run
rails db:rollback
. -
The
schema.rb
should look similar to the following: -
Open up a terminal and run
rails c
. Then run the following: