Fixing a Rails Migration Snafu
Ford Fischer Jun 13
I had been working on a huge new feature for a Rails app with existing customers for about two months. This new feature had about 10 new database migrations, including rolling back and editing the last migration that had been pushed to production and renaming those tables. That was a mistake. If, two months later, I had remembered to rollback the most recent migration in production before performing the new migrations, all would have been well.
Alas, I did not. Obviously, any programming change that requires you remember to do something 2 months from now is bad, especially if you have no system to remind yourself before deploying. When I did push the feature to production, my new migrations ran fine and two days laters I started getting errors about how a database table doesn't exist when my code assumes it does. It didn't take me long to realize that it was the migration about 10 migration files back that was the source of the error where I had rolled back in development and renamed the tables, but I had not rolled back in production.
Worse, I had a bunch of data live in production now, that depended on tables created in migrations after the problem migration file. I very decidedly was not okay losing that data, but the only solution to my problem that I knew about required it. Basically, I was familiar with the basics of migrations through the Rails ActiveRecord migrations guide. I thought I'd have to push the old version of that migration file to production, rollback 10 migrations (losing all my new data), push the new version of the migration file and run db:migrate one more time.
Thankfully, in my desperate googling for a solution, I ran into this question and answer, which suggested a path forward. When I realized you could run a single migration up or down with the version option, it became clear. I had to push the old version of that migration to production and then run:
rails db:migrate:down VERSION=20180506181554
Then push the new version of that migration and run:
rails db:migrate:up VERSION=20180506181554
The version, by the way, is just the timestamp in the filename rails generates automatically if you are using
rails generate migration. Knowing how to reverse and rerun a specific migration file is a huge relief. Its comforting to know getting migrations out of sync in production doesn't necessarily have to blow everything up, but has the potential to be dealt with as an isolated problem. Thanks Rails!