Railsで複数DBのmigration

大規模なRailsアプリケーションだったり、旧来のシステムをRailsに置き換えたりしてると、どうしても複数DBを扱いたくなってくる。

その場合は例えば、以下のようなlib/tasks/database_foo.rakeを作成します。

namespace :foo do
  desc 'Configure the variables that rails need in order to look up for the db
    configuration in a different folder'
  task :set_custom_db_config_paths do
    ENV['SCHEMA']                                     = 'db_foo/schema.rb'
    ENV['DB_STRUCTURE']                               = 'db_foo/structure.sql'
    Rails.application.config.paths['db']              = ['db_foo']
    Rails.application.config.paths['db/migrate']      = ['db_foo/migrate']
    Rails.application.config.paths['db/seeds.rb']     = ['db_foo/seeds.rb']
    Rails.application.config.paths['config/database'] = ['config/database_foo.yml']
    ActiveRecord::Migrator.migrations_paths           = 'db_foo/migrate'

    # db_fooディレクトリを作りたくない場合は、以下のようにするとよい。
    # ENV['SCHEMA']                                     = 'db/schema_foo.rb'
    # ENV['DB_STRUCTURE']                               = 'db/structure_foo.sql'
    # Rails.application.config.paths['db']              = ['db']
    # Rails.application.config.paths['db/migrate']      = ['db/migrate_foo']
    # Rails.application.config.paths['db/seeds.rb']     = ['db/seeds_foo.rb']
    # Rails.application.config.paths['config/database'] = ['config/database_foo.yml']
    # ActiveRecord::Migrator.migrations_paths           = 'db/migrate_foo'
  end

  namespace :db do
    task drop: :set_custom_db_config_paths do
      Rake::Task['db:drop'].invoke
    end

    task create: :set_custom_db_config_paths do
      Rake::Task['db:create'].invoke
    end

    task migrate: :set_custom_db_config_paths do
      Rake::Task['db:migrate'].invoke
    end

    namespace :migrate do
      task up: :set_custom_db_config_paths do
        Rake::Task['db:migrate:up'].invoke
      end
      task down: :set_custom_db_config_paths do
        Rake::Task['db:migrate:down'].invoke
      end
    end

    task rollback: :set_custom_db_config_paths do
      Rake::Task['db:rollback'].invoke
    end

    task reset: :set_custom_db_config_paths do
      Rake::Task['db:drop'].invoke
      Rake::Task['db:create'].invoke
      Rake::Task['db:migrate'].invoke
    end

    namespace :schema do
      task dump: :set_custom_db_config_paths do
        Rake::Task['db:schema:dump'].invoke
      end
      task load: :set_custom_db_config_paths do
        Rake::Task['db:schema:load'].invoke
      end
    end

    namespace :structure do
      task dump: :set_custom_db_config_paths do
        Rake::Task['db:structure:dump'].invoke
      end
      task load: :set_custom_db_config_paths do
        Rake::Task['db:structure:load'].invoke
      end
    end

    task version: :set_custom_db_config_paths do
      Rake::Task['db:version'].invoke
    end

    task seed: :set_custom_db_config_paths do
      Rake::Task['db:seed'].invoke
    end

    namespace :test do
      task prepare: :set_custom_db_config_paths do
        Rake::Task['db:drop'].invoke
        Rake::Task['db:create'].invoke
        Rake::Task['db:migrate'].invoke
      end
    end
  end
end

すると、fooというDBに対して

  • rake foo:db:create
  • rake foo:db:drop
  • rake foo:db:migrate
  • rake foo:db:migrate:up
  • rake foo:db:migrate:down
  • rake foo:db:schema:dump
  • rake foo:db:schema:load

等々が実行できるようになります。