From 7cc27d749c3563e6b278ad01d233cb92ea3b7935 Mon Sep 17 00:00:00 2001 From: eileencodes Date: Thu, 30 May 2019 08:25:05 -0400 Subject: [PATCH] Move SchemaMigration to migration_context This PR moves the `schema_migration` to `migration_context` so that we can access the `schema_migration` per connection. This does not change behavior of the SchemaMigration if you are using one database. This also does not change behavior of any public APIs. `Migrator` is private as is `MigrationContext` so we can change these as needed. We now need to pass a `schema_migration` to `Migrator` so that we can run migrations on the right connection outside the context of a rake task. The bugs this fixes were discovered while debugging the issues around the SchemaCache on initialization with multiple database. It was clear that `get_all_versions` wouldn't work without these changes outside the context of a rake task (because in the rake task we establish a connection and change AR::Base.connection to the db we're running on). Because the `SchemaCache` relies on the `SchemaMigration` information we need to make sure we store it per-connection rather than on ActiveRecord::Base. [Eileen M. Uchitelle & Aaron Patterson] --- .../abstract/schema_statements.rb | 8 +- .../connection_adapters/abstract_adapter.rb | 17 +- activerecord/lib/active_record/migration.rb | 43 ++-- activerecord/lib/active_record/schema.rb | 2 +- .../lib/active_record/schema_migration.rb | 2 +- .../lib/active_record/tasks/database_tasks.rb | 12 +- .../adapters/mysql2/table_options_test.rb | 4 +- .../postgresql/extension_migration_test.rb | 4 +- .../cases/adapters/postgresql/uuid_test.rb | 8 +- activerecord/test/cases/ar_schema_test.rb | 27 +-- .../cases/migration/compatibility_test.rb | 29 +-- .../test/cases/migration/logger_test.rb | 9 +- activerecord/test/cases/migration_test.rb | 33 +-- activerecord/test/cases/migrator_test.rb | 137 ++++++----- .../test/cases/multi_db_migrator_test.rb | 218 ++++++++++++++++++ railties/test/application/loading_test.rb | 7 +- railties/test/railties/engine_test.rb | 2 +- 17 files changed, 412 insertions(+), 150 deletions(-) create mode 100644 activerecord/test/cases/multi_db_migrator_test.rb diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb index c85ea8e1daf34..79dc98607a48b 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb @@ -1064,8 +1064,8 @@ def foreign_key_options(from_table, to_table, options) # :nodoc: options end - def dump_schema_information #:nodoc: - versions = ActiveRecord::SchemaMigration.all_versions + def dump_schema_information # :nodoc: + versions = schema_migration.all_versions insert_versions_sql(versions) if versions.any? end @@ -1081,7 +1081,7 @@ def assume_migrated_upto_version(version, migrations_paths = nil) end version = version.to_i - sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name) + sm_table = quote_table_name(schema_migration.table_name) migrated = migration_context.get_all_versions versions = migration_context.migrations.map(&:version) @@ -1454,7 +1454,7 @@ def remove_columns_for_alter(table_name, *column_names) end def insert_versions_sql(versions) - sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name) + sm_table = quote_table_name(schema_migration.table_name) if versions.is_a?(Array) sql = +"INSERT INTO #{sm_table} (version) VALUES\n" diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index cfd986ebf9407..7d3ec7ecfd62d 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -163,7 +163,22 @@ def migrations_paths # :nodoc: end def migration_context # :nodoc: - MigrationContext.new(migrations_paths) + MigrationContext.new(migrations_paths, schema_migration) + end + + def schema_migration # :nodoc: + @schema_migration ||= begin + conn = self + spec_name = conn.pool.spec.name + name = "#{spec_name}::SchemaMigration" + + Class.new(ActiveRecord::SchemaMigration) do + define_singleton_method(:name) { name } + define_singleton_method(:to_s) { name } + + self.connection_specification_name = spec_name + end + end end class Version diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index fa9b650416c07..c749e92c77c8f 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -884,13 +884,14 @@ def method_missing(method, *arguments, &block) def copy(destination, sources, options = {}) copied = [] + schema_migration = options[:schema_migration] || ActiveRecord::SchemaMigration FileUtils.mkdir_p(destination) unless File.exist?(destination) - destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations + destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration).migrations last = destination_migrations.last sources.each do |scope, path| - source_migrations = ActiveRecord::MigrationContext.new(path).migrations + source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations source_migrations.each do |migration| source = File.binread(migration.filename) @@ -1012,10 +1013,11 @@ def mtime end class MigrationContext #:nodoc: - attr_reader :migrations_paths + attr_reader :migrations_paths, :schema_migration - def initialize(migrations_paths) + def initialize(migrations_paths, schema_migration) @migrations_paths = migrations_paths + @schema_migration = schema_migration end def migrate(target_version = nil, &block) @@ -1046,7 +1048,7 @@ def up(target_version = nil) migrations end - Migrator.new(:up, selected_migrations, target_version).migrate + Migrator.new(:up, selected_migrations, schema_migration, target_version).migrate end def down(target_version = nil) @@ -1056,20 +1058,20 @@ def down(target_version = nil) migrations end - Migrator.new(:down, selected_migrations, target_version).migrate + Migrator.new(:down, selected_migrations, schema_migration, target_version).migrate end def run(direction, target_version) - Migrator.new(direction, migrations, target_version).run + Migrator.new(direction, migrations, schema_migration, target_version).run end def open - Migrator.new(:up, migrations, nil) + Migrator.new(:up, migrations, schema_migration) end def get_all_versions - if SchemaMigration.table_exists? - SchemaMigration.all_versions.map(&:to_i) + if schema_migration.table_exists? + schema_migration.all_versions else [] end @@ -1106,12 +1108,12 @@ def migrations end def migrations_status - db_list = ActiveRecord::SchemaMigration.normalized_versions + db_list = schema_migration.normalized_versions file_list = migration_files.map do |file| version, name, scope = parse_migration_filename(file) raise IllegalMigrationNameError.new(file) unless version - version = ActiveRecord::SchemaMigration.normalize_migration_number(version) + version = schema_migration.normalize_migration_number(version) status = db_list.delete(version) ? "up" : "down" [status, version, (name + scope).humanize] end.compact @@ -1151,7 +1153,7 @@ def parse_migration_filename(filename) end def move(direction, steps) - migrator = Migrator.new(direction, migrations) + migrator = Migrator.new(direction, migrations, schema_migration) if current_version != 0 && !migrator.current_migration raise UnknownMigrationVersionError.new(current_version) @@ -1170,27 +1172,28 @@ def move(direction, steps) end end - class Migrator #:nodoc: + class Migrator # :nodoc: class << self attr_accessor :migrations_paths # For cases where a table doesn't exist like loading from schema cache def current_version - MigrationContext.new(migrations_paths).current_version + MigrationContext.new(migrations_paths, SchemaMigration).current_version end end self.migrations_paths = ["db/migrate"] - def initialize(direction, migrations, target_version = nil) + def initialize(direction, migrations, schema_migration, target_version = nil) @direction = direction @target_version = target_version @migrated_versions = nil @migrations = migrations + @schema_migration = schema_migration validate(@migrations) - ActiveRecord::SchemaMigration.create_table + @schema_migration.create_table ActiveRecord::InternalMetadata.create_table end @@ -1244,7 +1247,7 @@ def migrated end def load_migrated - @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions) + @migrated_versions = Set.new(@schema_migration.all_versions) end private @@ -1327,10 +1330,10 @@ def validate(migrations) def record_version_state_after_migrating(version) if down? migrated.delete(version) - ActiveRecord::SchemaMigration.delete_by(version: version.to_s) + @schema_migration.delete_by(version: version.to_s) else migrated << version - ActiveRecord::SchemaMigration.create!(version: version.to_s) + @schema_migration.create!(version: version.to_s) end end diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb index 76bf53387ddb4..aba25fb3757ca 100644 --- a/activerecord/lib/active_record/schema.rb +++ b/activerecord/lib/active_record/schema.rb @@ -50,7 +50,7 @@ def define(info, &block) # :nodoc: instance_eval(&block) if info[:version].present? - ActiveRecord::SchemaMigration.create_table + connection.schema_migration.create_table connection.assume_migrated_upto_version(info[:version]) end diff --git a/activerecord/lib/active_record/schema_migration.rb b/activerecord/lib/active_record/schema_migration.rb index dec7fee98642e..58b21d2cc8a1f 100644 --- a/activerecord/lib/active_record/schema_migration.rb +++ b/activerecord/lib/active_record/schema_migration.rb @@ -45,7 +45,7 @@ def normalized_versions end def all_versions - order(:version).pluck(:version) + order(:version).pluck(:version).map(&:to_i) end end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index cf98a203bdee2..aecc9350e8efc 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -200,9 +200,10 @@ def drop_current(environment = env) def truncate_tables(configuration) ActiveRecord::Base.connected_to(database: { truncation: configuration }) do - table_names = ActiveRecord::Base.connection.tables + conn = ActiveRecord::Base.connection + table_names = conn.tables table_names -= [ - SchemaMigration.table_name, + conn.schema_migration.table_name, InternalMetadata.table_name ] @@ -233,7 +234,7 @@ def migrate end def migrate_status - unless ActiveRecord::SchemaMigration.table_exists? + unless ActiveRecord::Base.connection.schema_migration.table_exists? Kernel.abort "Schema migrations table does not exist yet." end @@ -328,6 +329,7 @@ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc: require "active_record/schema_dumper" filename = dump_filename(spec_name, format) + connection = ActiveRecord::Base.connection case format when :ruby @@ -336,9 +338,9 @@ def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_n end when :sql structure_dump(configuration, filename) - if ActiveRecord::SchemaMigration.table_exists? + if connection.schema_migration.table_exists? File.open(filename, "a") do |f| - f.puts ActiveRecord::Base.connection.dump_schema_information + f.puts connection.dump_schema_information f.print "\n" end end diff --git a/activerecord/test/cases/adapters/mysql2/table_options_test.rb b/activerecord/test/cases/adapters/mysql2/table_options_test.rb index 1c92df940f82e..13cf1daa08ca1 100644 --- a/activerecord/test/cases/adapters/mysql2/table_options_test.rb +++ b/activerecord/test/cases/adapters/mysql2/table_options_test.rb @@ -73,7 +73,7 @@ def migrate(x) end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate output = dump_table_schema("mysql_table_options") options = %r{create_table "mysql_table_options", options: "(?.*)"}.match(output)[:options] @@ -112,7 +112,7 @@ def migrate(x) end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate assert_match %r{ENGINE=InnoDB}, @log.string end diff --git a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb index 0fd7b2c6edc71..00ba549c97409 100644 --- a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb +++ b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb @@ -50,7 +50,7 @@ def test_enable_extension_migration_ignores_prefix_and_suffix @connection.disable_extension("hstore") migrations = [EnableHstore.new(nil, 1)] - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, ActiveRecord::Base.connection.schema_migration).migrate assert @connection.extension_enabled?("hstore"), "extension hstore should be enabled" end @@ -58,7 +58,7 @@ def test_disable_extension_migration_ignores_prefix_and_suffix @connection.enable_extension("hstore") migrations = [DisableHstore.new(nil, 1)] - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, ActiveRecord::Base.connection.schema_migration).migrate assert_not @connection.extension_enabled?("hstore"), "extension hstore should not be enabled" end end diff --git a/activerecord/test/cases/adapters/postgresql/uuid_test.rb b/activerecord/test/cases/adapters/postgresql/uuid_test.rb index 2be67aae20822..a1c985fc710aa 100644 --- a/activerecord/test/cases/adapters/postgresql/uuid_test.rb +++ b/activerecord/test/cases/adapters/postgresql/uuid_test.rb @@ -293,14 +293,14 @@ def migrate(x) create_table("pg_uuids_4", id: :uuid) end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate schema = dump_table_schema "pg_uuids_4" assert_match(/\bcreate_table "pg_uuids_4", id: :uuid, default: -> { "uuid_generate_v4\(\)" }/, schema) ensure drop_table "pg_uuids_4" ActiveRecord::Migration.verbose = @verbose_was - ActiveRecord::SchemaMigration.delete_all + ActiveRecord::Base.connection.schema_migration.delete_all end uses_transaction :test_schema_dumper_for_uuid_primary_key_default_in_legacy_migration end @@ -343,14 +343,14 @@ def migrate(x) create_table("pg_uuids_4", id: :uuid, default: nil) end end.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], ActiveRecord::Base.connection.schema_migration).migrate schema = dump_table_schema "pg_uuids_4" assert_match(/\bcreate_table "pg_uuids_4", id: :uuid, default: nil/, schema) ensure drop_table "pg_uuids_4" ActiveRecord::Migration.verbose = @verbose_was - ActiveRecord::SchemaMigration.delete_all + ActiveRecord::Base.connection.schema_migration.delete_all end uses_transaction :test_schema_dumper_for_uuid_primary_key_with_default_nil_in_legacy_migration end diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb index 7aa6d089c5f41..2d5a06a4ac459 100644 --- a/activerecord/test/cases/ar_schema_test.rb +++ b/activerecord/test/cases/ar_schema_test.rb @@ -9,7 +9,8 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase @original_verbose = ActiveRecord::Migration.verbose ActiveRecord::Migration.verbose = false @connection = ActiveRecord::Base.connection - ActiveRecord::SchemaMigration.drop_table + @schema_migration = @connection.schema_migration + @schema_migration.drop_table end teardown do @@ -18,21 +19,21 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase @connection.drop_table :nep_schema_migrations rescue nil @connection.drop_table :has_timestamps rescue nil @connection.drop_table :multiple_indexes rescue nil - ActiveRecord::SchemaMigration.delete_all rescue nil + @schema_migration.delete_all rescue nil ActiveRecord::Migration.verbose = @original_verbose end def test_has_primary_key old_primary_key_prefix_type = ActiveRecord::Base.primary_key_prefix_type ActiveRecord::Base.primary_key_prefix_type = :table_name_with_underscore - assert_equal "version", ActiveRecord::SchemaMigration.primary_key + assert_equal "version", @schema_migration.primary_key - ActiveRecord::SchemaMigration.create_table - assert_difference "ActiveRecord::SchemaMigration.count", 1 do - ActiveRecord::SchemaMigration.create version: 12 + @schema_migration.create_table + assert_difference "@schema_migration.count", 1 do + @schema_migration.create version: 12 end ensure - ActiveRecord::SchemaMigration.drop_table + @schema_migration.drop_table ActiveRecord::Base.primary_key_prefix_type = old_primary_key_prefix_type end @@ -54,7 +55,7 @@ def test_schema_define def test_schema_define_with_table_name_prefix old_table_name_prefix = ActiveRecord::Base.table_name_prefix ActiveRecord::Base.table_name_prefix = "nep_" - ActiveRecord::SchemaMigration.reset_table_name + @schema_migration.reset_table_name ActiveRecord::InternalMetadata.reset_table_name ActiveRecord::Schema.define(version: 7) do create_table :fruits do |t| @@ -67,7 +68,7 @@ def test_schema_define_with_table_name_prefix assert_equal 7, @connection.migration_context.current_version ensure ActiveRecord::Base.table_name_prefix = old_table_name_prefix - ActiveRecord::SchemaMigration.reset_table_name + @schema_migration.reset_table_name ActiveRecord::InternalMetadata.reset_table_name end @@ -89,10 +90,10 @@ def test_schema_subclass end def test_normalize_version - assert_equal "118", ActiveRecord::SchemaMigration.normalize_migration_number("0000118") - assert_equal "002", ActiveRecord::SchemaMigration.normalize_migration_number("2") - assert_equal "017", ActiveRecord::SchemaMigration.normalize_migration_number("0017") - assert_equal "20131219224947", ActiveRecord::SchemaMigration.normalize_migration_number("20131219224947") + assert_equal "118", @schema_migration.normalize_migration_number("0000118") + assert_equal "002", @schema_migration.normalize_migration_number("2") + assert_equal "017", @schema_migration.normalize_migration_number("0017") + assert_equal "20131219224947", @schema_migration.normalize_migration_number("20131219224947") end def test_schema_load_with_multiple_indexes_for_column_of_different_names diff --git a/activerecord/test/cases/migration/compatibility_test.rb b/activerecord/test/cases/migration/compatibility_test.rb index 726ccf925e684..ff2a694e66ca8 100644 --- a/activerecord/test/cases/migration/compatibility_test.rb +++ b/activerecord/test/cases/migration/compatibility_test.rb @@ -12,6 +12,7 @@ class CompatibilityTest < ActiveRecord::TestCase def setup super @connection = ActiveRecord::Base.connection + @schema_migration = @connection.schema_migration @verbose_was = ActiveRecord::Migration.verbose ActiveRecord::Migration.verbose = false @@ -38,7 +39,7 @@ def migrate(x) }.new assert connection.index_exists?(:testings, :foo, name: "custom_index_name") - assert_raise(StandardError) { ActiveRecord::Migrator.new(:up, [migration]).migrate } + assert_raise(StandardError) { ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate } assert connection.index_exists?(:testings, :foo, name: "custom_index_name") end @@ -53,7 +54,7 @@ def migrate(x) }.new assert connection.index_exists?(:testings, :bar) - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_not connection.index_exists?(:testings, :bar) end @@ -67,7 +68,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_not connection.index_exists?(:more_testings, :foo_id) assert_not connection.index_exists?(:more_testings, :bar_id) @@ -84,7 +85,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:more_testings, :created_at, null: true) assert connection.column_exists?(:more_testings, :updated_at, null: true) @@ -101,7 +102,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: true) assert connection.column_exists?(:testings, :updated_at, null: true) @@ -117,7 +118,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: true) assert connection.column_exists?(:testings, :updated_at, null: true) @@ -131,7 +132,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: true) assert connection.column_exists?(:testings, :updated_at, null: true) @@ -146,7 +147,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:more_testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:more_testings, :updated_at, null: false, **precision_implicit_default) @@ -163,7 +164,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:testings, :updated_at, null: false, **precision_implicit_default) @@ -179,7 +180,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:testings, :updated_at, null: false, **precision_implicit_default) @@ -193,7 +194,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :created_at, null: false, **precision_implicit_default) assert connection.column_exists?(:testings, :updated_at, null: false, **precision_implicit_default) @@ -230,7 +231,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert connection.column_exists?(:testings, :foo, comment: "comment") end @@ -243,7 +244,7 @@ def migrate(x) end }.new - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_equal "comment", connection.table_comment("testings") end @@ -261,7 +262,7 @@ def migrate(x) }.new Testing.create! - ActiveRecord::Migrator.new(:up, [migration]).migrate + ActiveRecord::Migrator.new(:up, [migration], @schema_migration).migrate assert_equal ["foobar"], Testing.all.map(&:foo) ensure ActiveRecord::Base.clear_cache! diff --git a/activerecord/test/cases/migration/logger_test.rb b/activerecord/test/cases/migration/logger_test.rb index 28f4cc124b4ed..431047f957bf9 100644 --- a/activerecord/test/cases/migration/logger_test.rb +++ b/activerecord/test/cases/migration/logger_test.rb @@ -17,19 +17,20 @@ def migrate(direction) def setup super - ActiveRecord::SchemaMigration.create_table - ActiveRecord::SchemaMigration.delete_all + @schema_migration = ActiveRecord::Base.connection.schema_migration + @schema_migration.create_table + @schema_migration.delete_all end teardown do - ActiveRecord::SchemaMigration.drop_table + @schema_migration.drop_table end def test_migration_should_be_run_without_logger previous_logger = ActiveRecord::Base.logger ActiveRecord::Base.logger = nil migrations = [Migration.new("a", 1), Migration.new("b", 2), Migration.new("c", 3)] - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration).migrate ensure ActiveRecord::Base.logger = previous_logger end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index a557225528664..20f577b2c5adf 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -38,6 +38,7 @@ def setup end Reminder.reset_column_information @verbose_was, ActiveRecord::Migration.verbose = ActiveRecord::Migration.verbose, false + @schema_migration = ActiveRecord::Base.connection.schema_migration ActiveRecord::Base.connection.schema_cache.clear! end @@ -84,7 +85,7 @@ def test_migration_version_matches_component_version def test_migrator_versions migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) migrator.up assert_equal 3, migrator.current_version @@ -102,23 +103,23 @@ def test_migration_detection_without_schema_migration_table ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) assert_equal true, migrator.needs_migration? end def test_any_migrations - migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid") + migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration) assert_predicate migrator, :any_migrations? - migrator_empty = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/empty") + migrator_empty = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/empty", @schema_migration) assert_not_predicate migrator_empty, :any_migrations? end def test_migration_version - migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/version_check") + migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/version_check", @schema_migration) assert_equal 0, migrator.current_version migrator.up(20131219224947) assert_equal 20131219224947, migrator.current_version @@ -249,7 +250,7 @@ def test_filtering_migrations assert_not_predicate Reminder, :table_exists? name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" } - migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid") + migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", @schema_migration) migrator.up(&name_filter) assert_column Person, :last_name @@ -311,7 +312,7 @@ def migrate(x) end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) e = assert_raise(StandardError) { migrator.migrate } @@ -332,7 +333,7 @@ def migrate(x) end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) e = assert_raise(StandardError) { migrator.run } @@ -355,7 +356,7 @@ def migrate(x) end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 101) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 101) e = assert_raise(StandardError) { migrator.migrate } assert_equal "An error has occurred, all later migrations canceled:\n\nSomething broke", e.message @@ -414,7 +415,7 @@ def test_internal_metadata_table_name def test_internal_metadata_stores_environment current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) migrator.up assert_equal current_env, ActiveRecord::InternalMetadata[:environment] @@ -442,7 +443,7 @@ def test_internal_metadata_stores_environment_when_other_data_exists current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call migrations_path = MIGRATIONS_ROOT + "/valid" - migrator = ActiveRecord::MigrationContext.new(migrations_path) + migrator = ActiveRecord::MigrationContext.new(migrations_path, @schema_migration) migrator.up assert_equal current_env, ActiveRecord::InternalMetadata[:environment] assert_equal "bar", ActiveRecord::InternalMetadata[:foo] @@ -639,7 +640,7 @@ def test_invalid_text_size_should_raise if ActiveRecord::Base.connection.supports_advisory_locks? def test_migrator_generates_valid_lock_id migration = Class.new(ActiveRecord::Migration::Current).new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) @@ -653,7 +654,7 @@ def test_generate_migrator_advisory_lock_id # It is important we are consistent with how we generate this so that # exclusive locking works across migrator versions migration = Class.new(ActiveRecord::Migration::Current).new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) @@ -675,7 +676,7 @@ def migrate(x) end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) with_another_process_holding_lock(lock_id) do @@ -696,7 +697,7 @@ def migrate(x) end }.new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) with_another_process_holding_lock(lock_id) do @@ -709,7 +710,7 @@ def migrate(x) def test_with_advisory_lock_raises_the_right_error_when_it_fails_to_release_lock migration = Class.new(ActiveRecord::Migration::Current).new - migrator = ActiveRecord::Migrator.new(:up, [migration], 100) + migrator = ActiveRecord::Migrator.new(:up, [migration], @schema_migration, 100) lock_id = migrator.send(:generate_migrator_advisory_lock_id) e = assert_raises(ActiveRecord::ConcurrentMigrationError) do diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb index 0c2ff9509935f..aeba8e1d14b51 100644 --- a/activerecord/test/cases/migrator_test.rb +++ b/activerecord/test/cases/migrator_test.rb @@ -23,8 +23,9 @@ def down; @went_down = true; end def setup super - ActiveRecord::SchemaMigration.create_table - ActiveRecord::SchemaMigration.delete_all rescue nil + @schema_migration = ActiveRecord::Base.connection.schema_migration + @schema_migration.create_table + @schema_migration.delete_all rescue nil @verbose_was = ActiveRecord::Migration.verbose ActiveRecord::Migration.message_count = 0 ActiveRecord::Migration.class_eval do @@ -36,7 +37,7 @@ def puts(*) end teardown do - ActiveRecord::SchemaMigration.delete_all rescue nil + @schema_migration.delete_all rescue nil ActiveRecord::Migration.verbose = @verbose_was ActiveRecord::Migration.class_eval do undef :puts @@ -49,7 +50,7 @@ def puts(*) def test_migrator_with_duplicate_names e = assert_raises(ActiveRecord::DuplicateMigrationNameError) do list = [ActiveRecord::Migration.new("Chunky"), ActiveRecord::Migration.new("Chunky")] - ActiveRecord::Migrator.new(:up, list) + ActiveRecord::Migrator.new(:up, list, @schema_migration) end assert_match(/Multiple migrations have the name Chunky/, e.message) end @@ -57,39 +58,40 @@ def test_migrator_with_duplicate_names def test_migrator_with_duplicate_versions assert_raises(ActiveRecord::DuplicateMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 1)] - ActiveRecord::Migrator.new(:up, list) + ActiveRecord::Migrator.new(:up, list, @schema_migration) end end def test_migrator_with_missing_version_numbers assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, 3).run + ActiveRecord::Migrator.new(:up, list, @schema_migration, 3).run end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, -1).run + ActiveRecord::Migrator.new(:up, list, @schema_migration, -1).run end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, 0).run + ActiveRecord::Migrator.new(:up, list, @schema_migration, 0).run end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, 3).migrate + ActiveRecord::Migrator.new(:up, list, @schema_migration, 3).migrate end assert_raises(ActiveRecord::UnknownMigrationVersionError) do list = [ActiveRecord::Migration.new("Foo", 1), ActiveRecord::Migration.new("Bar", 2)] - ActiveRecord::Migrator.new(:up, list, -1).migrate + ActiveRecord::Migrator.new(:up, list, @schema_migration, -1).migrate end end def test_finds_migrations - migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid").migrations + schema_migration = ActiveRecord::Base.connection.schema_migration + migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", schema_migration).migrations [[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i| assert_equal migrations[i].version, pair.first @@ -98,7 +100,8 @@ def test_finds_migrations end def test_finds_migrations_in_subdirectories - migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations + schema_migration = ActiveRecord::Base.connection.schema_migration + migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid_with_subdirectories", schema_migration).migrations [[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i| assert_equal migrations[i].version, pair.first @@ -107,8 +110,9 @@ def test_finds_migrations_in_subdirectories end def test_finds_migrations_from_two_directories + schema_migration = ActiveRecord::Base.connection.schema_migration directories = [MIGRATIONS_ROOT + "/valid_with_timestamps", MIGRATIONS_ROOT + "/to_copy_with_timestamps"] - migrations = ActiveRecord::MigrationContext.new(directories).migrations + migrations = ActiveRecord::MigrationContext.new(directories, schema_migration).migrations [[20090101010101, "PeopleHaveHobbies"], [20090101010202, "PeopleHaveDescriptions"], @@ -121,14 +125,16 @@ def test_finds_migrations_from_two_directories end def test_finds_migrations_in_numbered_directory - migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/10_urban").migrations + schema_migration = ActiveRecord::Base.connection.schema_migration + migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/10_urban", schema_migration).migrations assert_equal 9, migrations[0].version assert_equal "AddExpressions", migrations[0].name end def test_relative_migrations + schema_migration = ActiveRecord::Base.connection.schema_migration list = Dir.chdir(MIGRATIONS_ROOT) do - ActiveRecord::MigrationContext.new("valid").migrations + ActiveRecord::MigrationContext.new("valid", schema_migration).migrations end migration_proxy = list.find { |item| @@ -138,9 +144,9 @@ def test_relative_migrations end def test_finds_pending_migrations - ActiveRecord::SchemaMigration.create!(version: "1") + @schema_migration.create!(version: "1") migration_list = [ActiveRecord::Migration.new("foo", 1), ActiveRecord::Migration.new("bar", 3)] - migrations = ActiveRecord::Migrator.new(:up, migration_list).pending_migrations + migrations = ActiveRecord::Migrator.new(:up, migration_list, @schema_migration).pending_migrations assert_equal 1, migrations.size assert_equal migration_list.last, migrations.first @@ -148,35 +154,38 @@ def test_finds_pending_migrations def test_migrations_status path = MIGRATIONS_ROOT + "/valid" + schema_migration = ActiveRecord::Base.connection.schema_migration - ActiveRecord::SchemaMigration.create(version: 2) - ActiveRecord::SchemaMigration.create(version: 10) + @schema_migration.create(version: 2) + @schema_migration.create(version: 10) assert_equal [ ["down", "001", "Valid people have last names"], ["up", "002", "We need reminders"], ["down", "003", "Innocent jointable"], ["up", "010", "********** NO FILE **********"], - ], ActiveRecord::MigrationContext.new(path).migrations_status + ], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status end def test_migrations_status_in_subdirectories path = MIGRATIONS_ROOT + "/valid_with_subdirectories" + schema_migration = ActiveRecord::Base.connection.schema_migration - ActiveRecord::SchemaMigration.create(version: 2) - ActiveRecord::SchemaMigration.create(version: 10) + @schema_migration.create(version: 2) + @schema_migration.create(version: 10) assert_equal [ ["down", "001", "Valid people have last names"], ["up", "002", "We need reminders"], ["down", "003", "Innocent jointable"], ["up", "010", "********** NO FILE **********"], - ], ActiveRecord::MigrationContext.new(path).migrations_status + ], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status end def test_migrations_status_with_schema_define_in_subdirectories path = MIGRATIONS_ROOT + "/valid_with_subdirectories" prev_paths = ActiveRecord::Migrator.migrations_paths + schema_migration = ActiveRecord::Base.connection.schema_migration ActiveRecord::Migrator.migrations_paths = path ActiveRecord::Schema.define(version: 3) do @@ -186,16 +195,17 @@ def test_migrations_status_with_schema_define_in_subdirectories ["up", "001", "Valid people have last names"], ["up", "002", "We need reminders"], ["up", "003", "Innocent jointable"], - ], ActiveRecord::MigrationContext.new(path).migrations_status + ], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status ensure ActiveRecord::Migrator.migrations_paths = prev_paths end def test_migrations_status_from_two_directories paths = [MIGRATIONS_ROOT + "/valid_with_timestamps", MIGRATIONS_ROOT + "/to_copy_with_timestamps"] + schema_migration = ActiveRecord::Base.connection.schema_migration - ActiveRecord::SchemaMigration.create(version: "20100101010101") - ActiveRecord::SchemaMigration.create(version: "20160528010101") + @schema_migration.create(version: "20100101010101") + @schema_migration.create(version: "20160528010101") assert_equal [ ["down", "20090101010101", "People have hobbies"], @@ -204,18 +214,18 @@ def test_migrations_status_from_two_directories ["down", "20100201010101", "Valid with timestamps we need reminders"], ["down", "20100301010101", "Valid with timestamps innocent jointable"], ["up", "20160528010101", "********** NO FILE **********"], - ], ActiveRecord::MigrationContext.new(paths).migrations_status + ], ActiveRecord::MigrationContext.new(paths, schema_migration).migrations_status end def test_migrator_interleaved_migrations pass_one = [Sensor.new("One", 1)] - ActiveRecord::Migrator.new(:up, pass_one).migrate + ActiveRecord::Migrator.new(:up, pass_one, @schema_migration).migrate assert pass_one.first.went_up assert_not pass_one.first.went_down pass_two = [Sensor.new("One", 1), Sensor.new("Three", 3)] - ActiveRecord::Migrator.new(:up, pass_two).migrate + ActiveRecord::Migrator.new(:up, pass_two, @schema_migration).migrate assert_not pass_two[0].went_up assert pass_two[1].went_up assert pass_two.all? { |x| !x.went_down } @@ -224,7 +234,7 @@ def test_migrator_interleaved_migrations Sensor.new("Two", 2), Sensor.new("Three", 3)] - ActiveRecord::Migrator.new(:down, pass_three).migrate + ActiveRecord::Migrator.new(:down, pass_three, @schema_migration).migrate assert pass_three[0].went_down assert_not pass_three[1].went_down assert pass_three[2].went_down @@ -232,7 +242,7 @@ def test_migrator_interleaved_migrations def test_up_calls_up migrations = [Sensor.new(nil, 0), Sensor.new(nil, 1), Sensor.new(nil, 2)] - migrator = ActiveRecord::Migrator.new(:up, migrations) + migrator = ActiveRecord::Migrator.new(:up, migrations, @schema_migration) migrator.migrate assert migrations.all?(&:went_up) assert migrations.all? { |m| !m.went_down } @@ -243,7 +253,7 @@ def test_down_calls_down test_up_calls_up migrations = [Sensor.new(nil, 0), Sensor.new(nil, 1), Sensor.new(nil, 2)] - migrator = ActiveRecord::Migrator.new(:down, migrations) + migrator = ActiveRecord::Migrator.new(:down, migrations, @schema_migration) migrator.migrate assert migrations.all? { |m| !m.went_up } assert migrations.all?(&:went_down) @@ -251,30 +261,31 @@ def test_down_calls_down end def test_current_version - ActiveRecord::SchemaMigration.create!(version: "1000") - migrator = ActiveRecord::MigrationContext.new("db/migrate") + @schema_migration.create!(version: "1000") + schema_migration = ActiveRecord::Base.connection.schema_migration + migrator = ActiveRecord::MigrationContext.new("db/migrate", schema_migration) assert_equal 1000, migrator.current_version end def test_migrator_one_up calls, migrations = sensors(3) - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal [[:up, 1]], calls calls.clear - ActiveRecord::Migrator.new(:up, migrations, 2).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 2).migrate assert_equal [[:up, 2]], calls end def test_migrator_one_down calls, migrations = sensors(3) - ActiveRecord::Migrator.new(:up, migrations).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration).migrate assert_equal [[:up, 1], [:up, 2], [:up, 3]], calls calls.clear - ActiveRecord::Migrator.new(:down, migrations, 1).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 1).migrate assert_equal [[:down, 3], [:down, 2]], calls end @@ -282,17 +293,17 @@ def test_migrator_one_down def test_migrator_one_up_one_down calls, migrations = sensors(3) - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal [[:up, 1]], calls calls.clear - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal [[:down, 1]], calls end def test_migrator_double_up calls, migrations = sensors(3) - migrator = ActiveRecord::Migrator.new(:up, migrations, 1) + migrator = ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1) assert_equal(0, migrator.current_version) migrator.migrate @@ -305,7 +316,7 @@ def test_migrator_double_up def test_migrator_double_down calls, migrations = sensors(3) - migrator = ActiveRecord::Migrator.new(:up, migrations, 1) + migrator = ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1) assert_equal 0, migrator.current_version @@ -313,7 +324,7 @@ def test_migrator_double_down assert_equal [[:up, 1]], calls calls.clear - migrator = ActiveRecord::Migrator.new(:down, migrations, 1) + migrator = ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 1) migrator.run assert_equal [[:down, 1]], calls calls.clear @@ -328,12 +339,12 @@ def test_migrator_verbosity _, migrations = sensors(3) ActiveRecord::Migration.verbose = true - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_not_equal 0, ActiveRecord::Migration.message_count ActiveRecord::Migration.message_count = 0 - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_not_equal 0, ActiveRecord::Migration.message_count end @@ -341,9 +352,9 @@ def test_migrator_verbosity_off _, migrations = sensors(3) ActiveRecord::Migration.verbose = false - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal 0, ActiveRecord::Migration.message_count - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal 0, ActiveRecord::Migration.message_count end @@ -351,23 +362,24 @@ def test_target_version_zero_should_run_only_once calls, migrations = sensors(3) # migrate up to 1 - ActiveRecord::Migrator.new(:up, migrations, 1).migrate + ActiveRecord::Migrator.new(:up, migrations, @schema_migration, 1).migrate assert_equal [[:up, 1]], calls calls.clear # migrate down to 0 - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal [[:down, 1]], calls calls.clear # migrate down to 0 again - ActiveRecord::Migrator.new(:down, migrations, 0).migrate + ActiveRecord::Migrator.new(:down, migrations, @schema_migration, 0).migrate assert_equal [], calls end def test_migrator_going_down_due_to_version_target + schema_migration = ActiveRecord::Base.connection.schema_migration calls, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.up(1) assert_equal [[:up, 1]], calls @@ -382,8 +394,9 @@ def test_migrator_going_down_due_to_version_target end def test_migrator_output_when_running_multiple_migrations + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) result = migrator.migrate assert_equal(3, result.count) @@ -397,8 +410,9 @@ def test_migrator_output_when_running_multiple_migrations end def test_migrator_output_when_running_single_migration + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(1) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) result = migrator.run(:up, 1) @@ -406,8 +420,9 @@ def test_migrator_output_when_running_single_migration end def test_migrator_rollback + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.migrate assert_equal(3, migrator.current_version) @@ -426,8 +441,9 @@ def test_migrator_rollback end def test_migrator_db_has_no_schema_migrations_table + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) ActiveRecord::SchemaMigration.drop_table assert_not_predicate ActiveRecord::SchemaMigration, :table_exists? @@ -436,8 +452,9 @@ def test_migrator_db_has_no_schema_migrations_table end def test_migrator_forward + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("/valid") + migrator = migrator.new("/valid", schema_migration) migrator.migrate(1) assert_equal(1, migrator.current_version) @@ -450,18 +467,20 @@ def test_migrator_forward def test_only_loads_pending_migrations # migrate up to 1 - ActiveRecord::SchemaMigration.create!(version: "1") + @schema_migration.create!(version: "1") + schema_migration = ActiveRecord::Base.connection.schema_migration calls, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.migrate assert_equal [[:up, 2], [:up, 3]], calls end def test_get_all_versions + schema_migration = ActiveRecord::Base.connection.schema_migration _, migrator = migrator_class(3) - migrator = migrator.new("valid") + migrator = migrator.new("valid", schema_migration) migrator.migrate assert_equal([1, 2, 3], migrator.get_all_versions) diff --git a/activerecord/test/cases/multi_db_migrator_test.rb b/activerecord/test/cases/multi_db_migrator_test.rb new file mode 100644 index 0000000000000..650b3af6f00ec --- /dev/null +++ b/activerecord/test/cases/multi_db_migrator_test.rb @@ -0,0 +1,218 @@ +# frozen_string_literal: true + +require "cases/helper" +require "cases/migration/helper" + +class MultiDbMigratorTest < ActiveRecord::TestCase + self.use_transactional_tests = false + + # Use this class to sense if migrations have gone + # up or down. + class Sensor < ActiveRecord::Migration::Current + attr_reader :went_up, :went_down + + def initialize(name = self.class.name, version = nil) + super + @went_up = false + @went_down = false + end + + def up; @went_up = true; end + def down; @went_down = true; end + end + + def setup + super + @connection_a = ActiveRecord::Base.connection + @connection_b = ARUnit2Model.connection + + @connection_a.schema_migration.create_table + @connection_b.schema_migration.create_table + + @connection_a.schema_migration.delete_all rescue nil + @connection_b.schema_migration.delete_all rescue nil + + @path_a = MIGRATIONS_ROOT + "/valid" + @path_b = MIGRATIONS_ROOT + "/to_copy" + + @schema_migration_a = @connection_a.schema_migration + @migrations_a = ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a).migrations + @schema_migration_b = @connection_b.schema_migration + @migrations_b = ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b).migrations + + @migrations_a_list = [[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]] + @migrations_b_list = [[1, "PeopleHaveHobbies"], [2, "PeopleHaveDescriptions"]] + + @verbose_was = ActiveRecord::Migration.verbose + + ActiveRecord::Migration.message_count = 0 + ActiveRecord::Migration.class_eval do + undef :puts + def puts(*) + ActiveRecord::Migration.message_count += 1 + end + end + end + + teardown do + @connection_a.schema_migration.delete_all rescue nil + @connection_b.schema_migration.delete_all rescue nil + + ActiveRecord::Migration.verbose = @verbose_was + ActiveRecord::Migration.class_eval do + undef :puts + def puts(*) + super + end + end + end + + def test_finds_migrations + @migrations_a_list.each_with_index do |pair, i| + assert_equal @migrations_a[i].version, pair.first + assert_equal @migrations_a[i].name, pair.last + end + + @migrations_b_list.each_with_index do |pair, i| + assert_equal @migrations_b[i].version, pair.first + assert_equal @migrations_b[i].name, pair.last + end + end + + def test_migrations_status + @schema_migration_a.create(version: 2) + @schema_migration_a.create(version: 10) + + assert_equal [ + ["down", "001", "Valid people have last names"], + ["up", "002", "We need reminders"], + ["down", "003", "Innocent jointable"], + ["up", "010", "********** NO FILE **********"], + ], ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a).migrations_status + + @schema_migration_b.create(version: 4) + + assert_equal [ + ["down", "001", "People have hobbies"], + ["down", "002", "People have descriptions"], + ["up", "004", "********** NO FILE **********"] + ], ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b).migrations_status + end + + def test_get_all_versions + _, migrator_a = migrator_class(3) + migrator_a = migrator_a.new(@path_a, @schema_migration_a) + + migrator_a.migrate + assert_equal([1, 2, 3], migrator_a.get_all_versions) + + migrator_a.rollback + assert_equal([1, 2], migrator_a.get_all_versions) + + migrator_a.rollback + assert_equal([1], migrator_a.get_all_versions) + + migrator_a.rollback + assert_equal([], migrator_a.get_all_versions) + + _, migrator_b = migrator_class(2) + migrator_b = migrator_b.new(@path_b, @schema_migration_b) + + migrator_b.migrate + assert_equal([1, 2], migrator_b.get_all_versions) + + migrator_b.rollback + assert_equal([1], migrator_b.get_all_versions) + + migrator_b.rollback + assert_equal([], migrator_b.get_all_versions) + end + + def test_finds_pending_migrations + @schema_migration_a.create!(version: "1") + migration_list_a = [ActiveRecord::Migration.new("foo", 1), ActiveRecord::Migration.new("bar", 3)] + migrations_a = ActiveRecord::Migrator.new(:up, migration_list_a, @schema_migration_a).pending_migrations + + assert_equal 1, migrations_a.size + assert_equal migration_list_a.last, migrations_a.first + + @schema_migration_b.create!(version: "1") + migration_list_b = [ActiveRecord::Migration.new("foo", 1), ActiveRecord::Migration.new("bar", 3)] + migrations_b = ActiveRecord::Migrator.new(:up, migration_list_b, @schema_migration_b).pending_migrations + + assert_equal 1, migrations_b.size + assert_equal migration_list_b.last, migrations_b.first + end + + def test_migrator_db_has_no_schema_migrations_table + _, migrator = migrator_class(3) + migrator = migrator.new(@path_a, @schema_migration_a) + + @schema_migration_a.drop_table + assert_not @connection_a.table_exists?("schema_migrations") + migrator.migrate(1) + assert @connection_a.table_exists?("schema_migrations") + + _, migrator = migrator_class(3) + migrator = migrator.new(@path_b, @schema_migration_b) + + @schema_migration_b.drop_table + assert_not @connection_b.table_exists?("schema_migrations") + migrator.migrate(1) + assert @connection_b.table_exists?("schema_migrations") + end + + def test_migrator_forward + _, migrator = migrator_class(3) + migrator = migrator.new(@path_a, @schema_migration_a) + migrator.migrate(1) + assert_equal(1, migrator.current_version) + + migrator.forward(2) + assert_equal(3, migrator.current_version) + + migrator.forward + assert_equal(3, migrator.current_version) + + _, migrator_b = migrator_class(3) + migrator_b = migrator_b.new(@path_b, @schema_migration_b) + migrator_b.migrate(1) + assert_equal(1, migrator_b.current_version) + + migrator_b.forward(2) + assert_equal(3, migrator_b.current_version) + + migrator_b.forward + assert_equal(3, migrator_b.current_version) + end + + private + def m(name, version) + x = Sensor.new name, version + x.extend(Module.new { + define_method(:up) { yield(:up, x); super() } + define_method(:down) { yield(:down, x); super() } + }) if block_given? + end + + def sensors(count) + calls = [] + migrations = count.times.map { |i| + m(nil, i + 1) { |c, migration| + calls << [c, migration.version] + } + } + [calls, migrations] + end + + def migrator_class(count) + calls, migrations = sensors(count) + + migrator = Class.new(ActiveRecord::MigrationContext) { + define_method(:migrations) { |*| + migrations + } + } + [calls, migrator] + end +end diff --git a/railties/test/application/loading_test.rb b/railties/test/application/loading_test.rb index c262a6435e381..9ab400acfcbd9 100644 --- a/railties/test/application/loading_test.rb +++ b/railties/test/application/loading_test.rb @@ -133,11 +133,12 @@ class Post < ApplicationRecord require "#{rails_root}/config/environment" setup_ar! - assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort + initial = [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord, "primary::SchemaMigration"].collect(&:to_s).sort + assert_equal initial, ActiveRecord::Base.descendants.collect(&:to_s).sort get "/load" - assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord, Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort + assert_equal [Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort - initial get "/unload" - assert_equal [ActiveStorage::Blob, ActiveStorage::Attachment, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort + assert_equal ["ActiveRecord::InternalMetadata", "ActiveRecord::SchemaMigration", "primary::SchemaMigration"], ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq end test "initialize cant be called twice" do diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb index 8ce68dbcfa29c..7f05b9d9cfb08 100644 --- a/railties/test/railties/engine_test.rb +++ b/railties/test/railties/engine_test.rb @@ -34,7 +34,7 @@ def boot_rails def migrations migration_root = File.expand_path(ActiveRecord::Migrator.migrations_paths.first, app_path) - ActiveRecord::MigrationContext.new(migration_root).migrations + ActiveRecord::MigrationContext.new(migration_root, ActiveRecord::SchemaMigration).migrations end test "serving sprocket's assets" do