That's not the only bug here though. For me to get it to work, I
had to modify the rake tasks by creating
lib/tasks/datamapper.rake:

namespace :db do
namespace :migrate do
desc 'Migrate up using migrations'
task :up, :version, :needs => :load do |t, args|
migrate_up!(args[:version])
end
desc 'Migrate down using migrations'
task :down, :version, :needs => :load do |t, args|
migrate_down!(args[:version])
end
end
end

This is because the :load task runs migration files
which call the migration method included in the global
Object, whereas the current definition of :up and
:down specifies
::DataMapper::MigrationRunner.migrate_up! (and
down).

If this works in 1.8.7, then it's a 1.9.1 bug, and they must
have changed the way instance variables are located. The contents
of @migrations "disappears" between the two locations of calling
the methods (global Object vs named module).

Once upon a time I wrote a server process that migrated its own
database. I kept getting into duplicate migration conflicts until I
realised MigrationRunner is effectively a singleton.
The workaround was to hideously monkey-patch
MigrationRunner so it could be included in another
object.

IMO the real issue here is that MigrationRunners
need to be first class objects, so you can instantiate one, used it
as the scope to load the migrations, run it, and discard it. This
type of bug would not be possible under those circumstances.

Here is a rake task I am using to monkey patch the gem to make
the rake tasks work from my own code base:

# Need to be able to monkey-patch MigrationRunner before all migrations
# are loaded to work around a bug, so replace db:migrate:load with our own
# version
# From http://github.com/eugenebolshakov/override_rake_task
Rake::TaskManager.class_eval do
def alias_task(old_name, new_name)
@tasks[new_name] = @tasks.delete(old_name)
end
end
def alias_task(old_name, new_name)
Rake.application.alias_task(old_name, new_name)
end
def override_task(*args, &block)
name, params, deps = Rake.application.resolve_args(args.dup)
alias_task name.to_s, "#{name}:original"
Rake::Task.define_task(*args, &block)
end
override_task :'db:migrate:load' => :environment do
require 'dm-migrations/migration_runner'
# Original version has an instance var, not a class, and doesn't work
# for me
module DataMapper
module MigrationRunner
def migrations
@@migrations ||= []
end
end
end
# Code from original task
FileList['db/migrate/*.rb'].each do |migration|
load migration
end
end