Michael Anhari

Migrating or rolling back a specific migration in Rails

Zebra Migration

Rails provides two tasks for migrating/rolling back specific migrations while ignoring the rest.

db:migrate:up

Run a specific Rails migration based on the timestamp in the filename:

bin/rails db:migrate:up VERSION=20210121221640

db:migrate:down

Roll back a specific Rails migration based on the timestamp in the filename:

bin/rails db:migrate:down VERSION=20210121221640

Why would you want to do this?

The up version could come in handy if you want to run a single migration in production after merging it.

The down version can save you from the following headache:

~ bin/rails db:migrate

== 20210125021956 YourMigrationName: reverting 
rails aborted!
StandardError: An error has occurred, this and all later migrations canceled:

Caused by:
ActiveRecord::IrreversibleMigration

I’ve run into this after rebasing (and running) an irreversible migration on top of my branch before realizing I needed to rollback the migration I was implementing. Your options are twofold.

  1. Fix every irreversible migration that’s blocking your from rolling back yours.
  2. Use bin/rails db:migrate:down and your migration’s version number.

The right path depends on the situation.

How can I avoid writing irreversible migrations?

It’s commonplace for Rails developers to set up an alias that runs migrations, rolls them back, and runs them again to ensure their new migrations are reversible. The following command be used:

bundle exec rake db:migrate db:rollback && bundle exec rake db:migrate db:test:prepare

bundle exec can be replaced with bin/rails if you’re using a newer version of Rails.

Newsletter

I'm working on sending out a weekly newsletter. I'll make it as easy as possible to unsubscribe at any time.