Skip to content

Commit

Permalink
Multiple databases support (#56)
Browse files Browse the repository at this point in the history
* multidb support

* fix phantom_migrations rake task

* fix tests

* fix cop
  • Loading branch information
ka8725 authored May 6, 2024
1 parent 8cf43a4 commit 1935548
Show file tree
Hide file tree
Showing 12 changed files with 380 additions and 51 deletions.
4 changes: 4 additions & 0 deletions .rubocop.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,7 @@ Metrics/BlockLength:
Metrics/MethodLength:
Exclude:
- test/**/*

Metrics/ClassLength:
Exclude:
- test/**/*
8 changes: 8 additions & 0 deletions lib/actual_db_schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,14 @@ def self.migrations_paths
def self.migration_filename(fullpath)
fullpath.split("/").last
end

def self.for_each_db_connection
configs = ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env)
configs.each do |db_config|
ActiveRecord::Base.establish_connection(db_config)
yield
end
end
end

ActiveRecord::MigrationProxy.prepend(ActualDbSchema::Patches::MigrationProxy)
4 changes: 0 additions & 4 deletions lib/actual_db_schema/commands/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@ def call
raise "ActualDbSchema is disabled. Set ActualDbSchema.config[:enabled] = true to enable it."
end

if ActiveRecord::Migration.current_version >= 6
ActiveRecord::Tasks::DatabaseTasks.raise_for_multi_db(command: "db:rollback_branches")
end

call_impl
end

Expand Down
1 change: 0 additions & 1 deletion lib/actual_db_schema/patches/migration_context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ module Patches
# Add new command to roll back the phantom migrations
module MigrationContext
def rollback_branches
ActualDbSchema.failed = []
migrations.reverse_each do |migration|
migrator = down_migrator_for(migration)
migrator.extend(ActualDbSchema::Patches::Migrator)
Expand Down
11 changes: 8 additions & 3 deletions lib/tasks/db.rake
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,18 @@
namespace :db do
desc "Rollback migrations that were run inside not a merged branch."
task rollback_branches: :load_config do
ActualDbSchema::Commands::Rollback.new.call
ActualDbSchema.failed = []
ActualDbSchema.for_each_db_connection do
ActualDbSchema::Commands::Rollback.new.call
end
end

desc "List all phantom migrations - non-relevant migrations that were run inside not a merged branch."
task phantom_migrations: :load_config do
ActualDbSchema::Commands::List.new.call
ActualDbSchema.for_each_db_connection do
ActualDbSchema::Commands::List.new.call
end
end

task _dump: :rollback_branches
task "schema:dump" => :rollback_branches
end
File renamed without changes.
14 changes: 14 additions & 0 deletions test/dummy_app/db/secondary_schema.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# This file is auto-generated from the current state of the database. Instead
# of editing this file, please use the migrations feature of Active Record to
# incrementally modify your database, and then regenerate this schema definition.
#
# This file is the source Rails uses to define your schema when running `bin/rails
# db:schema:load`. When creating a new database, `bin/rails db:schema:load` tends to
# be faster and is potentially less error prone than running all of your
# migrations from scratch. Old migrations may fail to apply correctly if those
# migrations use external dependencies or application code.
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.0].define(version: 2013_09_06_111513) do
end
86 changes: 86 additions & 0 deletions test/rake_task_secondary_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# frozen_string_literal: true

require "test_helper"

describe "second db support" do
let(:utils) do
TestUtils.new(migrations_path: "db/migrate_secondary", migrated_path: "tmp/migrated_migrate_secondary")
end

before do
ActiveRecord::Base.configurations = { "test" => TestingState.db_config["secondary"] }
ActiveRecord::Tasks::DatabaseTasks.database_configuration = { "test" => TestingState.db_config["secondary"] }
ActiveRecord::Base.establish_connection(**TestingState.db_config["secondary"])
utils.cleanup
end

describe "db:rollback_branches" do
it "creates the tmp/migrated_migrate_secondary folder" do
refute File.exist?(utils.app_file("tmp/migrated_migrate_secondary"))
utils.run_migrations
assert File.exist?(utils.app_file("tmp/migrated_migrate_secondary"))
end

it "migrates the migrations" do
assert_empty utils.applied_migrations
utils.run_migrations
assert_equal %w[20130906111511 20130906111512], utils.applied_migrations
end

it "keeps migrated migrations in tmp/migrated folder" do
utils.run_migrations
assert_equal %w[20130906111511_first.rb 20130906111512_second.rb], utils.migrated_files
end

it "rolls back the migrations in the reversed order" do
utils.prepare_phantom_migrations
assert_empty TestingState.down
utils.run_migrations
assert_equal %i[second first], TestingState.down
end

describe "with irreversible migration" do
before do
utils.define_migration_file("20130906111513_irreversible.rb", <<~RUBY)
class Irreversible < ActiveRecord::Migration[6.0]
def up
TestingState.up << :irreversible
end
def down
raise ActiveRecord::IrreversibleMigration
end
end
RUBY
end

it "keeps track of the irreversible migrations" do
utils.prepare_phantom_migrations
assert_equal %i[first second irreversible], TestingState.up
assert_empty ActualDbSchema.failed
utils.run_migrations
assert_equal(%w[20130906111513_irreversible.rb], ActualDbSchema.failed.map { |m| File.basename(m.filename) })
end
end
end

describe "db:phantom_migrations" do
it "shows the list of phantom migrations" do
ActualDbSchema::Git.stub(:current_branch, "fix-bug") do
utils.prepare_phantom_migrations
Rake::Task["db:phantom_migrations"].invoke
Rake::Task["db:phantom_migrations"].reenable
assert_match(/ Status Migration ID Branch Migration File/, TestingState.output)
assert_match(/---------------------------------------------------/, TestingState.output)
assert_match(
%r{ up 20130906111511 fix-bug tmp/migrated_migrate_secondary/20130906111511_first.rb},
TestingState.output
)
assert_match(
%r{ up 20130906111512 fix-bug tmp/migrated_migrate_secondary/20130906111512_second.rb},
TestingState.output
)
end
end
end
end
7 changes: 6 additions & 1 deletion test/rake_task_test.rb → test/rake_task_tes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
describe "single db" do
let(:utils) { TestUtils.new }

before { utils.cleanup }
before do
ActiveRecord::Base.configurations = { "test" => TestingState.db_config["primary"] }
ActiveRecord::Tasks::DatabaseTasks.database_configuration = { "test" => TestingState.db_config["primary"] }
ActiveRecord::Base.establish_connection(**TestingState.db_config["primary"])
utils.cleanup
end

describe "db:rollback_branches" do
it "creates the tmp/migrated folder" do
Expand Down
115 changes: 115 additions & 0 deletions test/rake_tasks_all_databases_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
# frozen_string_literal: true

require "test_helper"

describe "multipe db support" do
let(:utils) do
TestUtils.new(
migrations_path: ["db/migrate", "db/migrate_secondary"],
migrated_path: ["tmp/migrated", "tmp/migrated_migrate_secondary"]
)
end

before do
ActiveRecord::Base.configurations = { "test" => TestingState.db_config }
ActiveRecord::Tasks::DatabaseTasks.database_configuration = { "test" => TestingState.db_config }
utils.cleanup(TestingState.db_config)
end

describe "db:rollback_branches" do
it "creates the tmp/migrated folder" do
refute File.exist?(utils.app_file("tmp/migrated"))
refute File.exist?(utils.app_file("tmp/migrated_migrate_secondary"))
utils.run_migrations
assert File.exist?(utils.app_file("tmp/migrated"))
assert File.exist?(utils.app_file("tmp/migrated_migrate_secondary"))
end

it "migrates the migrations" do
assert_empty utils.applied_migrations(TestingState.db_config)
utils.run_migrations
assert_equal(
%w[20130906111511 20130906111512 20130906111514 20130906111515],
utils.applied_migrations(TestingState.db_config)
)
end

it "keeps migrated migrations in tmp/migrated folder" do
utils.run_migrations
assert_equal(
%w[
20130906111511_first_primary.rb
20130906111512_second_primary.rb
20130906111514_first_secondary.rb
20130906111515_second_secondary.rb
],
utils.migrated_files(TestingState.db_config)
)
end

it "rolls back the migrations in the reversed order" do
utils.prepare_phantom_migrations(TestingState.db_config)
assert_empty TestingState.down
utils.run_migrations
assert_equal %i[second_primary first_primary second_secondary first_secondary], TestingState.down
end

describe "with irreversible migration" do
before do
%w[primary secondary].each do |prefix|
utils.define_migration_file("20130906111513_irreversible_#{prefix}.rb", <<~RUBY, prefix: prefix)
class Irreversible#{prefix.camelize} < ActiveRecord::Migration[6.0]
def up
TestingState.up << :irreversible_#{prefix}
end
def down
raise ActiveRecord::IrreversibleMigration
end
end
RUBY
end
end

it "keeps track of the irreversible migrations" do
utils.prepare_phantom_migrations(TestingState.db_config)
assert_equal(
%i[first_primary second_primary irreversible_primary irreversible_secondary first_secondary second_secondary],
TestingState.up
)
assert_empty ActualDbSchema.failed
utils.run_migrations
failed = ActualDbSchema.failed.map { |m| File.basename(m.filename) }
assert_equal(%w[20130906111513_irreversible_primary.rb 20130906111513_irreversible_secondary.rb], failed)
end
end
end

describe "db:phantom_migrations" do
it "shows the list of phantom migrations" do
ActualDbSchema::Git.stub(:current_branch, "fix-bug") do
utils.prepare_phantom_migrations(TestingState.db_config)
Rake::Task["db:phantom_migrations"].invoke
Rake::Task["db:phantom_migrations"].reenable
assert_match(/ Status Migration ID Branch Migration File/, TestingState.output)
assert_match(/---------------------------------------------------/, TestingState.output)
assert_match(
%r{ up 20130906111511 fix-bug tmp/migrated/20130906111511_first_primary.rb},
TestingState.output
)
assert_match(
%r{ up 20130906111512 fix-bug tmp/migrated/20130906111512_second_primary.rb},
TestingState.output
)
assert_match(
%r{ up 20130906111514 fix-bug tmp/migrated_migrate_secondary/20130906111514_first_secondary.rb},
TestingState.output
)
assert_match(
%r{ up 20130906111515 fix-bug tmp/migrated_migrate_secondary/20130906111515_second_secondary.rb},
TestingState.output
)
end
end
end
end
Loading

0 comments on commit 1935548

Please sign in to comment.