Request for improvements of migration rake commands

I decided to describe here a number of things I miss in my developer routines regarding migrations.

db:rollback task

Currently, to rollback you have to find a specific migration name and execute rake 'db:migrate[12345678123456]'. Additional complication is that rom-sql documentation on migrations lacks information about rollbacks, and sequel docs only mention “specifying the target version”.

I think that by far the most common use case for a rollback is when a developer wants to rollback the last one or two migrations locally during development. So, it would be nice to have a db:rollback command to simplify that process.

Additionally, would be cool to support rake db:rollback STEP=2 syntax (matching rails) to rollback several migrations at once. This can be done with Sequel::Migrator’s relative option

allow_missing_migration_files support for db:migrate

I switch between features-in-development branches several times a day. Some of them have migrations, and whenever I switch to another one forgetting to revert them, db:migrate starts failing with “migration … is not in the filesystem”.

This makes me wish that I could pass migrator: {allow_missing_migration_files: true} to ROM::Configuration.new in development only. Currently this is not possible, cause db:migrate doesn’t pass that option by itself for obvious reasons, and ROM::SQL::Migrations::Migrator doesn’t mix it into Sequel::Migrator options in #run

Wdyt? Does any of that sound reasonable?

Regarding the db:rollback, something like this would be ideal:

desc 'Rollback the database (options: STEP, VERSION)'
task rollback: :rom_configuration do
  step = ENV["STEP"]&.to_i
  version = ENV["VERSION"]&.to_i

  raise "Specify either STEP or VERSION, but not both" if step && version

  options = version ? {target: version} : {relative: -(step || 1)}

  ROM::SQL::RakeSupport.run_migrations(**options)
  puts "<= db:rollback #{"STEP=#{step}" if step}#{"VERSION=#{version}" if version} executed"
end

It seems though that rom-sql uses the default way of passing arguments to rake (rake db:rollback[...]), but this approach is:

  • Not nice for either-or kind of arguments. You’ll have to remember the order of arguments and call either db:rollback[2] or db:rollback[,1234567890]. And there will be even more confusion when the user uses sequential integer versioning
  • Not handy in some systems. Some shells (zsh, maybe some others as well) parse square brackets as a globbing pattern and fail if there are no matching files. With zsh, users always have to quote tasks with arguments (rake 'db:migrate[1234567890]'), which is a bit annoying

Might it be worth supporting both approaches (db:rollback[2] and db:rollback STEP=2), extending the other tasks similarily?