Today I
had to change a belongs_to
associate to an has_and_belongs_to_many
in a Rails
project I’m currently working on. Not that hard you would say, but there were some catches for
deploying/migrating these changes to the production environment.
In this post I’d like to explain how to achieve this without having to do multiple deployments of your model to maintain a consistent database schema and model.
TL;DR;
Here you can find the final migration. Note that this example could also be solved with plain sql instead of using ActiveRecord, but there might be cases were you depend on the ActiveRecord associates. In these cases this is a great workaround
The problem
Let’s say we have a Article that belongs to a Category. Our model would look like something like this:
1 2 3 4 |
|
And the executed migration would look like this:
1 2 3 4 5 6 7 8 9 |
|
The initial migration
First let’s create a new table that can hold the associate between multiple Articles and Categories. The migration would look like this:
1 2 3 4 5 6 7 8 9 10 11 |
|
At this point all is fine and we can migrate the database without any problems. Only this doesn’t add the current category to the new collection of categories.
Moving the belongs_to associate
Here’s were the problem actually starts, because to move the category to the categories collection
for the articles, we have to define the belongs_to
but also the
has_and_belongs_to_many
associate on the Article
model.
I don’t like this approach because we’ll have to define both these associates and the
belongs_to
should be removed in the next release. So how to deal with this?
The fix
The fix is quite simple. We remove the belongs_to
associate from the model and only define
the new has_and_belongs_to_many
associate and within the migration we extend the model with
the “old” belongs_to
associate so we can use this within the migration.
So our files will look like this
1 2 3 4 |
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
|