I have an existing rails project in which the requirements were recently changed. Initially, I had a model associated with another through a one-to-many relationship. Now, there’s a new use case which changes the association to many-to-many.
class Questionnaire < ActiveRecord::Base has_many :sections end
class Section < ActiveRecord::Base belongs_to :questionnaire end
To migrate has_many to has_many :through, I created three separate migrations. The first migration created the table to hold the relation.
class CreateTemplates < ActiveRecord::Migration def change create_table :templates do |t| t.integer :questionnaire_id t.integer :section_id t.timestamps end end end
The second migration migrated the existing data from the existing relationship. A ‘Template’ record was created for every existing section. This migration is not reversible and will result in data loss if the database needed to be rollback for any reason. It is best to backup the database before performing this migration.
class CreateTemplatesFromSections < ActiveRecord::Migration def up Section.all.each do |section| Template.create(section_id: section.id, questionnaire_id: section.questionnaire_id) end end end
The third migration removed the questionnaire_id from the Section model. Since it will no longer be used.
class RemoveQuestionnaireFromSections < ActiveRecord::Migration def change remove_column :sections, :questionnaire_id end end
Changed the models to reflect the below:
class Questionnaire < ActiveRecord::Base has_many :templates has_many :sections, through: :templates end
class Section < ActiveRecord::Base has_many :templates has_many :questionnaires, through: :templates end
class Template < ActiveRecord::Base belongs_to :questionnaire belongs_to :section end
$ rake db:migrate