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.dband add the following: -
Seed the database by running
rails db:seed5. Open up the Rails Console by runningrails c. Confirm there is data in the database by running the following: -
Open up
schema.rbto 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 upanddef downmethods. Specifically, add the following:- In the
def upmethod usecreate_tableto create a new join table. - In the
def upmethod populate the new join table with the existing relationships. - In the
def upmethod remove the existingreferencecolumn. - In the
def downmethod add areferencecolumn. - In the
def downmethod populate the reference column. - In the
def downmethod use thedrop_tablemethod to remove the join table.
- In the
- Update the database by running
rails db:migratein a terminal window. -
Open
schema.rbto 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.rbshould look similar to the following: -
Open up a terminal and run
rails c. Then run the following: