top of page

How-To: Rolling Back a Specific and Isolated Rails Migration (v6)

February 25th, 2022

Database maintenance image

1.1 What are we trying to do

We recently had the need to replace a custom role based access control (RBAC) solution with the Rolify Gem to provide a more fine grain and flexible solution that integrates well with the other solutions we were utilizing for authentication (Devise) and authorization (CanCanCan).


Since we already created our custom Rails models and migrations, we needed to rollback specific migrations in isolation and well needless to say our existing migration structure included many other migrations in between (meaning we couldn't simply run a simple variation of the rake db:rollback command.)


1.2 The "Why"

The obvious is that we needed to get rid of what will be no longer necessary database tables, indexes, and the like. Beyond the obvious, I like keeping my migrations directory clean, where instead of creating a migration to "undo" a prior migration, I'd much rather see if we can simply get rid of the migration we want to undo and keep only the pertinent migrations. Otherwise, we have additional code that needs to be maintained, stored, reasoned about, etc... which costs resources (time and money.)


1.3 Gotchas... Don't just take my word on this, reason for yourself as this is not a one-size-fits-all solution

Now obviously, this solution may not always be the prudent one. For example, if the migration can not be removed in isolation because it does more than simple data definition tasks utilizing data definition language (DDL) commands (e.g. creating tables, adding fields, adding indexes, etc...); or, if later migrations depend on that earlier migration, in essence where running all migrations to create the data structure from scratch would end up failing with a migration error. This is only a fraction of the reasons why you may end up not using this method. You will want to understand the migration and determine the feasibility of using this method.


We are also assuming that this is a relatively simple migration where Rails can properly run the "down" command successfully, which goes to the first point of it being a relatively simple migration. Granted you can absolutely change/create the down method within your migration file to do specific tasks to make it where the migration will accomplish what you want in order to make the migration disappear in its entirety, but that is more advanced than this blog will get into and requires a lot more reasoning.


2 What you came for...The how to part

We have a very specific need to remove older tables created by a Rails migration. First, you'll want to make sure you identify the specific migration that you are interested in making disappear (then reason about it see 1.3 above.)


Once you've identified the migration and determined that this can be removed in its entirety you'll want to note the "version" number of the migration. Rails default for this value is a timestamp before the more friendly name provided. For example the following migration filename 20220225121500_create_roles.rb version would be 20220225121500.


Now that we have this vital piece of information (the version we identified in the last step,) we can run the following from your OS' console window to undo the migration:

<AppRoot>$ rake db:migrate:down VERSION=20220225121500

This should output something like the following to your console:

== 20220225121500 CreateRoles: reverting =======================
-- drop_table(:roles)
   -> 0.0299s
== 20220225121500 CreateRoles: reverted (0.0358s) ==============

Afterwards you can delete the migration from the db/migrate folder, for example:

<AppRoot>$ rm db/migrate/20220225121500_create_roles.rb

I would then suggest attempting to create a database from scratch... like an automated test database (I really, really hope you have tests!) to verify that the migration can run without error prior to checking in your code and new schema file to your code versioning system (please tell me you are using some sort of version control system, like Git!)


Your mileage may vary. Obviously, you likely have additional work to do in order to integrate any new capability that you were replacing, updating your automated tests, etc...


Disclaimer

This blog is intended for entertainment and/or informational purposes only, and for use by persons having appropriate technical skill, at their own discretion and risk.

19 views0 comments
bottom of page