Rails has long supported database migrations to help you evolve your database schema over time, but traditionally migrations are used strictly to alter the schema of the database. However, mature Rails applications often need migration-like tasks which may not alter the schema, or may have special considerations. I prefer to use an after-deploy migration for any task that is so rare I don’t anticipate repeating it, or so complex I simply will not be able to reuse that code. Specifically, I’ve used them to fix corrupt data, perform a 1-time import process, and rebuild denormalized data. You’ll note that each of these examples are not schema changes.
Late-night migrations fall into a different classification. They might be schema changes that can lock a table or cause other issues that would arise during the day. They also may just be after-deploy migrations which consume a lot of resources, and are best ran during times of low customer use.
Rails 5 introduced multi-database support, which also benefits from multiple directories for migrations. You can leverage that logic and create a new task for special migrations like this:
namespace :db do desc "Migrate the database through scripts in db/migrate_after_deploy. Target specific version with VERSION=x. Turn off output with VERBOSE=false." task :migrate_after_deploy => :environment do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true ActiveRecord::MigrationContext.new('db/migrate_after_deploy').migrate(ENV["VERSION"] ? ENV["VERSION"].to_i : nil) end end
Now, you can run
rake db:migrate_after_deploy to run the migrations inside the
Read more about this change here.