Move SchemaMigration to an independent object

Previously, SchemaMigration inherited from ActiveRecord::Base. This is
problematic for multiple databases and resulted in building the code in
AbstractAdapter that was previously there. Rather than hacking around
the fact that SchemaMigration inherits from Base, this PR makes
SchemaMigration an independent object. Then each connection can get it's
own SchemaMigration object. This change required defining the methods
that SchemaMigration was depending on ActiveRecord::Base for (ex
create!). I reimplemented only the methods called by the framework as
this class is no-doc's so it doesn't need to implement anything beyond
that. Now each connection gets it's own SchemaMigration object which
stores the connection. I also decided to update the method names (create
-> create_version, delete_by -> delete_version, delete_all ->
delete_all_versions) to be more explicit.

This change also required adding a NullSchemaMigraiton class for cases
when we don't have a connection yet but still need to copy migrations
from the MigrationContext. Ultimately I think this is a little weird -
we need to do so much work to pick up a set of files? Maybe something to
explore in the future.

Aside from removing the hack we added back in #36439 this change will
enable my work to stop clobbering and depending directly on
Base.connection in the rake tasks. While working on this I discovered
that we always have a `ActiveRecord::SchemaMigration` because the
connection is always on `Base` in the rake tasks. This will free us up
to do less hacky stuff in the migrations and tasks.
This commit is contained in:
eileencodes 2022-08-26 10:47:00 -04:00
parent e24fbf71fa
commit 436277da88
No known key found for this signature in database
GPG Key ID: BA5C575120BBE8DF
20 changed files with 210 additions and 162 deletions

@ -1,3 +1,9 @@
* Move `ActiveRecord::SchemaMigration` to an independent object.
`ActiveRecord::SchemaMigration` no longer inherits from `ActiveRecord::Base` and is now an independent object that should be instantiated with a `connection`. This class is private and should not be used by applications directly. If you want to interact with the schema migrations table, please access it on the connection directly, for example: `ActiveRecord::Base.connection.schema_migration`.
*Eileen M. Uchitelle*
* Deprecate `all_connection_pools` and make `connection_pool_list` more explicit.
Following on #45924 `all_connection_pools` is now deprecated. `connection_pool_list` will either take an explicit role or applications can opt into the new behavior by passing `:all`.

@ -1270,7 +1270,7 @@ def check_constraint_exists?(table_name, **options)
end
def dump_schema_information # :nodoc:
versions = schema_migration.all_versions
versions = schema_migration.versions
insert_versions_sql(versions) if versions.any?
end

@ -193,21 +193,7 @@ def migration_context # :nodoc:
end
def schema_migration # :nodoc:
@schema_migration ||= begin
conn = self
connection_name = conn.pool.pool_config.connection_name
return ActiveRecord::SchemaMigration if connection_name == "ActiveRecord::Base"
schema_migration_name = "#{connection_name}::SchemaMigration"
Class.new(ActiveRecord::SchemaMigration) do
define_singleton_method(:name) { schema_migration_name }
define_singleton_method(:to_s) { schema_migration_name }
self.connection_specification_name = connection_name
end
end
SchemaMigration.new(self)
end
def internal_metadata # :nodoc:

@ -950,14 +950,13 @@ 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, schema_migration).migrations
destination_migrations = ActiveRecord::MigrationContext.new(destination, SchemaMigration::NullSchemaMigration.new).migrations
last = destination_migrations.last
sources.each do |scope, path|
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration).migrations
source_migrations = ActiveRecord::MigrationContext.new(path, SchemaMigration::NullSchemaMigration.new).migrations
source_migrations.each do |migration|
source = File.binread(migration.filename)
@ -1018,7 +1017,7 @@ def next_migration_number(number)
if ActiveRecord.timestamped_migrations
[Time.now.utc.strftime("%Y%m%d%H%M%S"), "%.14d" % number].max
else
SchemaMigration.normalize_migration_number(number)
"%.3d" % number.to_i
end
end
@ -1076,15 +1075,21 @@ def load_migration
#
# A migration context requires the path to the migrations is set
# in the +migrations_paths+ parameter. Optionally a +schema_migration+
# class can be provided. For most applications, +SchemaMigration+ is
# sufficient. Multiple database applications need a +SchemaMigration+
# per primary database.
# class can be provided. Multiple database applications will instantiate
# a +SchemaMigration+ object per database. From the Rake tasks, Rails will
# handle this for you.
class MigrationContext
attr_reader :migrations_paths, :schema_migration, :internal_metadata
def initialize(migrations_paths, schema_migration = SchemaMigration, internal_metadata = InternalMetadata)
def initialize(migrations_paths, schema_migration = nil, internal_metadata = InternalMetadata)
if schema_migration == SchemaMigration
schema_migration = SchemaMigration.new(ActiveRecord::Base.connection)
ActiveSupport::Deprecation.warn("SchemaMigration no longer inherits from ActiveRecord::Base. Please instaniate a new SchemaMigration object with the desired connection, ie `ActiveRecord::SchemaMigration.new(ActiveRecord::Base.connection)`.")
end
@migrations_paths = migrations_paths
@schema_migration = schema_migration
@schema_migration = schema_migration || SchemaMigration.new(ActiveRecord::Base.connection)
@internal_metadata = internal_metadata
end
@ -1152,7 +1157,7 @@ def open # :nodoc:
def get_all_versions # :nodoc:
if schema_migration.table_exists?
schema_migration.all_versions.map(&:to_i)
schema_migration.integer_versions
else
[]
end
@ -1257,7 +1262,9 @@ class << self
# For cases where a table doesn't exist like loading from schema cache
def current_version
MigrationContext.new(migrations_paths, SchemaMigration, InternalMetadata).current_version
schema_migration = SchemaMigration.new(ActiveRecord::Base.connection)
MigrationContext.new(migrations_paths, schema_migration, InternalMetadata).current_version
end
end
@ -1327,7 +1334,7 @@ def migrated
end
def load_migrated
@migrated_versions = Set.new(@schema_migration.all_versions.map(&:to_i))
@migrated_versions = Set.new(@schema_migration.integer_versions)
end
private
@ -1406,10 +1413,10 @@ def validate(migrations)
def record_version_state_after_migrating(version)
if down?
migrated.delete(version)
@schema_migration.delete_by(version: version.to_s)
@schema_migration.delete_version(version.to_s)
else
migrated << version
@schema_migration.create!(version: version.to_s)
@schema_migration.create_version(version.to_s)
end
end

@ -1,54 +1,87 @@
# frozen_string_literal: true
require "active_record/scoping/default"
require "active_record/scoping/named"
module ActiveRecord
# This class is used to create a table that keeps track of which migrations
# have been applied to a given database. When a migration is run, its schema
# number is inserted in to the `SchemaMigration.table_name` so it doesn't need
# number is inserted in to the schema migrations table so it doesn't need
# to be executed the next time.
class SchemaMigration < ActiveRecord::Base # :nodoc:
class << self
def primary_key
"version"
end
class SchemaMigration # :nodoc:
attr_reader :connection, :arel_table
def table_name
"#{table_name_prefix}#{schema_migrations_table_name}#{table_name_suffix}"
end
def initialize(connection)
@connection = connection
@arel_table = Arel::Table.new(table_name)
end
def create_table
unless connection.table_exists?(table_name)
connection.create_table(table_name, id: false) do |t|
t.string :version, **connection.internal_string_options_for_primary_key
end
end
end
def create_version(version)
im = Arel::InsertManager.new(arel_table)
im.insert(arel_table[primary_key] => version)
connection.insert(im, "#{self} Create", primary_key, version)
end
def drop_table
connection.drop_table table_name, if_exists: true
end
def delete_version(version)
dm = Arel::DeleteManager.new(arel_table)
dm.wheres = [arel_table[primary_key].eq(version)]
def normalize_migration_number(number)
"%.3d" % number.to_i
end
connection.delete(dm, "#{self} Destroy")
end
def normalized_versions
all_versions.map { |v| normalize_migration_number v }
end
def all_versions
order(:version).pluck(:version)
end
def table_exists?
connection.data_source_exists?(table_name)
def delete_all_versions
versions.each do |version|
delete_version(version)
end
end
def version
super.to_i
def primary_key
"version"
end
def table_name
"#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.schema_migrations_table_name}#{ActiveRecord::Base.table_name_suffix}"
end
def create_table
unless connection.table_exists?(table_name)
connection.create_table(table_name, id: false) do |t|
t.string :version, **connection.internal_string_options_for_primary_key
end
end
end
def drop_table
connection.drop_table table_name, if_exists: true
end
def normalize_migration_number(number)
"%.3d" % number.to_i
end
def normalized_versions
versions.map { |v| normalize_migration_number v }
end
def versions
sm = Arel::SelectManager.new(arel_table)
sm.project(arel_table[primary_key])
sm.order(arel_table[primary_key].asc)
connection.select_values(sm)
end
def integer_versions
versions.map(&:to_i)
end
def count
sm = Arel::SelectManager.new(arel_table)
sm.project(*Arel::Nodes::Count.new([Arel.star]))
connection.select_values(sm).first
end
def table_exists?
connection.data_source_exists?(table_name)
end
class NullSchemaMigration
end
end
end

@ -192,7 +192,7 @@ def prepare_all
ActiveRecord::Base.establish_connection(db_config)
begin
database_initialized = ActiveRecord::SchemaMigration.table_exists?
database_initialized = ActiveRecord::Base.connection.schema_migration.table_exists?
rescue ActiveRecord::NoDatabaseError
create(db_config)
retry

@ -20,7 +20,7 @@ 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
@schema_migration.delete_all rescue nil
@schema_migration.delete_all_versions rescue nil
ActiveRecord::Migration.verbose = @original_verbose
end
@ -31,7 +31,7 @@ def test_has_primary_key
@schema_migration.create_table
assert_difference "@schema_migration.count", 1 do
@schema_migration.create version: 12
@schema_migration.create_version(12)
end
ensure
@schema_migration.drop_table
@ -69,7 +69,6 @@ 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_"
@schema_migration.reset_table_name
@internal_metadata.reset_table_name
ActiveRecord::Schema.define(version: 7) do
create_table :fruits do |t|
@ -82,7 +81,6 @@ 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
@schema_migration.reset_table_name
@internal_metadata.reset_table_name
end

@ -5,6 +5,10 @@
class SchemaMigrationsTest < ActiveRecord::Mysql2TestCase
self.use_transactional_tests = false
def setup
@schema_migration = ActiveRecord::Base.connection.schema_migration
end
def test_renaming_index_on_foreign_key
connection.add_index "engines", "car_id"
connection.add_foreign_key :engines, :cars, name: "fk_engines_cars"
@ -17,10 +21,10 @@ def test_renaming_index_on_foreign_key
def test_initializes_schema_migrations_for_encoding_utf8mb4
with_encoding_utf8mb4 do
table_name = ActiveRecord::SchemaMigration.table_name
table_name = @schema_migration.table_name
connection.drop_table table_name, if_exists: true
ActiveRecord::SchemaMigration.create_table
@schema_migration.create_table
assert connection.column_exists?(table_name, :version, :string)
end

@ -94,7 +94,7 @@ def teardown
ActiveRecord::Base.logger = @logger_was
ActiveRecord::Migration.verbose = @verbose_was
ActiveRecord::Base.connection.drop_table "mysql_table_options", if_exists: true
ActiveRecord::SchemaMigration.delete_all rescue nil
ActiveRecord::Base.connection.schema_migration.delete_all_versions rescue nil
end
test "new migrations do not contain default ENGINE=InnoDB option" do

@ -27,20 +27,18 @@ def setup
ActiveRecord::Base.table_name_prefix = "p_"
ActiveRecord::Base.table_name_suffix = "_s"
@connection.schema_migration.reset_table_name
@connection.internal_metadata.reset_table_name
@connection.schema_migration.delete_all rescue nil
@connection.schema_migration.delete_all_versions rescue nil
ActiveRecord::Migration.verbose = false
end
def teardown
@connection.schema_migration.delete_all rescue nil
@connection.schema_migration.delete_all_versions rescue nil
ActiveRecord::Migration.verbose = true
ActiveRecord::Base.table_name_prefix = @old_table_name_prefix
ActiveRecord::Base.table_name_suffix = @old_table_name_suffix
@connection.schema_migration.reset_table_name
@connection.internal_metadata.reset_table_name
super

@ -308,7 +308,7 @@ def migrate(x)
ensure
drop_table "pg_uuids_4"
ActiveRecord::Migration.verbose = @verbose_was
ActiveRecord::Base.connection.schema_migration.delete_all
ActiveRecord::Base.connection.schema_migration.delete_all_versions
end
uses_transaction :test_schema_dumper_for_uuid_primary_key_default_in_legacy_migration
end
@ -360,7 +360,7 @@ def migrate(x)
ensure
drop_table "pg_uuids_4"
ActiveRecord::Migration.verbose = @verbose_was
ActiveRecord::Base.connection.schema_migration.delete_all
ActiveRecord::Base.connection.schema_migration.delete_all_versions
end
uses_transaction :test_schema_dumper_for_uuid_primary_key_with_default_nil_in_legacy_migration
end

@ -30,7 +30,7 @@ def setup
teardown do
connection.drop_table :testings rescue nil
ActiveRecord::Migration.verbose = @verbose_was
@schema_migration.delete_all rescue nil
@schema_migration.delete_all_versions rescue nil
end
def test_migration_doesnt_remove_named_index
@ -685,7 +685,7 @@ def setup
def teardown
ActiveRecord::Migration.verbose = @verbose_was
@schema_migration.delete_all rescue nil
@schema_migration.delete_all_versions rescue nil
connection.drop_table :testings rescue nil
end
@ -812,7 +812,7 @@ def setup
def teardown
@migration.migrate(:down) if @migration
ActiveRecord::Migration.verbose = @verbose_was
ActiveRecord::SchemaMigration.delete_all rescue nil
ActiveRecord::Base.connection.schema_migration.delete_all_versions rescue nil
LegacyPrimaryKey.reset_column_information
end

@ -19,7 +19,7 @@ def setup
super
@schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create_table
@schema_migration.delete_all
@schema_migration.delete_all_versions
@internal_metadata = ActiveRecord::Base.connection.internal_metadata
end

@ -53,8 +53,8 @@ def setup
ActiveRecord::Base.table_name_prefix = ""
ActiveRecord::Base.table_name_suffix = ""
ActiveRecord::SchemaMigration.create_table
ActiveRecord::SchemaMigration.delete_all
@schema_migration.create_table
@schema_migration.delete_all_versions
%w(things awesome_things prefix_things_suffix p_awesome_things_s).each do |table|
Thing.connection.drop_table(table) rescue nil
@ -79,6 +79,22 @@ def setup
ActiveRecord::Migration.verbose = @verbose_was
end
def test_passing_a_schema_migration_class_to_migration_context_is_deprecated
migrations_path = MIGRATIONS_ROOT + "/valid"
migrator = assert_deprecated { ActiveRecord::MigrationContext.new(migrations_path, ActiveRecord::SchemaMigration) }
migrator.up
assert_equal 3, migrator.current_version
assert_equal false, migrator.needs_migration?
migrator.down
assert_equal 0, migrator.current_version
assert_equal true, migrator.needs_migration?
@schema_migration.create_version(3)
assert_equal true, migrator.needs_migration?
end
def test_migration_context_with_default_schema_migration
migrations_path = MIGRATIONS_ROOT + "/valid"
migrator = ActiveRecord::MigrationContext.new(migrations_path)
@ -91,7 +107,7 @@ def test_migration_context_with_default_schema_migration
assert_equal 0, migrator.current_version
assert_equal true, migrator.needs_migration?
ActiveRecord::SchemaMigration.create!(version: 3)
@schema_migration.create_version(3)
assert_equal true, migrator.needs_migration?
end
@ -111,7 +127,7 @@ def test_migrator_versions
assert_equal 0, migrator.current_version
assert_equal true, migrator.needs_migration?
ActiveRecord::SchemaMigration.create!(version: 3)
@schema_migration.create_version(3)
assert_equal true, migrator.needs_migration?
end
@ -635,21 +651,20 @@ def migrate(x)
def test_schema_migrations_table_name
original_schema_migrations_table_name = ActiveRecord::Base.schema_migrations_table_name
assert_equal "schema_migrations", ActiveRecord::SchemaMigration.table_name
assert_equal "schema_migrations", @schema_migration.table_name
ActiveRecord::Base.table_name_prefix = "prefix_"
ActiveRecord::Base.table_name_suffix = "_suffix"
Reminder.reset_table_name
assert_equal "prefix_schema_migrations_suffix", ActiveRecord::SchemaMigration.table_name
assert_equal "prefix_schema_migrations_suffix", @schema_migration.table_name
ActiveRecord::Base.schema_migrations_table_name = "changed"
Reminder.reset_table_name
assert_equal "prefix_changed_suffix", ActiveRecord::SchemaMigration.table_name
assert_equal "prefix_changed_suffix", @schema_migration.table_name
ActiveRecord::Base.table_name_prefix = ""
ActiveRecord::Base.table_name_suffix = ""
Reminder.reset_table_name
assert_equal "changed", ActiveRecord::SchemaMigration.table_name
assert_equal "changed", @schema_migration.table_name
ensure
ActiveRecord::Base.schema_migrations_table_name = original_schema_migrations_table_name
ActiveRecord::SchemaMigration.reset_table_name
Reminder.reset_table_name
end
@ -774,28 +789,26 @@ def test_internal_metadata_create_table_wont_be_affected_by_schema_cache
end
def test_schema_migration_create_table_wont_be_affected_by_schema_cache
ActiveRecord::SchemaMigration.drop_table
assert_not_predicate ActiveRecord::SchemaMigration, :table_exists?
@schema_migration.drop_table
assert_not_predicate @schema_migration, :table_exists?
ActiveRecord::SchemaMigration.connection.transaction do
ActiveRecord::SchemaMigration.create_table
assert_predicate ActiveRecord::SchemaMigration, :table_exists?
@schema_migration.connection.transaction do
@schema_migration.create_table
assert_predicate @schema_migration, :table_exists?
schema_migration = ActiveRecord::SchemaMigration.create!(version: "foo")
assert_equal "foo", schema_migration[:version]
assert_equal "foo", @schema_migration.create_version("foo")
raise ActiveRecord::Rollback
end
ActiveRecord::SchemaMigration.connection.transaction do
ActiveRecord::SchemaMigration.create_table
assert_predicate ActiveRecord::SchemaMigration, :table_exists?
@schema_migration.connection.transaction do
@schema_migration.create_table
assert_predicate @schema_migration, :table_exists?
schema_migration = ActiveRecord::SchemaMigration.create!(version: "bar")
assert_equal "bar", schema_migration[:version]
assert_equal "bar", @schema_migration.create_version("bar")
raise ActiveRecord::Rollback
end
ensure
ActiveRecord::SchemaMigration.create_table
@schema_migration.create_table
end
def test_proper_table_name_on_migration

@ -25,7 +25,7 @@ def setup
super
@schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create_table
@schema_migration.delete_all rescue nil
@schema_migration.delete_all_versions rescue nil
@internal_metadata = ActiveRecord::Base.connection.internal_metadata
@verbose_was = ActiveRecord::Migration.verbose
ActiveRecord::Migration.message_count = 0
@ -38,7 +38,7 @@ def puts(*)
end
teardown do
@schema_migration.delete_all rescue nil
@schema_migration.delete_all_versions rescue nil
ActiveRecord::Migration.verbose = @verbose_was
ActiveRecord::Migration.class_eval do
undef :puts
@ -145,7 +145,7 @@ def test_relative_migrations
end
def test_finds_pending_migrations
@schema_migration.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, @schema_migration, @internal_metadata).pending_migrations
@ -157,8 +157,8 @@ def test_migrations_status
path = MIGRATIONS_ROOT + "/valid"
schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create(version: 2)
@schema_migration.create(version: 10)
@schema_migration.create_version(2)
@schema_migration.create_version(10)
assert_equal [
["down", "001", "Valid people have last names"],
@ -172,10 +172,10 @@ def test_migrations_status_order_new_and_old_version
path = MIGRATIONS_ROOT + "/old_and_new_versions"
schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create(version: 230)
@schema_migration.create(version: 231)
@schema_migration.create(version: 20210716122844)
@schema_migration.create(version: 20210716123013)
@schema_migration.create_version(230)
@schema_migration.create_version(231)
@schema_migration.create_version(20210716122844)
@schema_migration.create_version(20210716123013)
assert_equal [
["up", "230", "Add people hobby"],
@ -189,14 +189,14 @@ def test_migrations_status_order_new_and_old_version_applied_out_of_order
path = MIGRATIONS_ROOT + "/old_and_new_versions"
schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create(version: 230)
@schema_migration.create(version: 231)
@schema_migration.create_version(230)
@schema_migration.create_version(231)
# "Apply" a newer migration and not an older to simulate out-of-order
# migration application which should not affect ordering in status and is
# possible if a branch is merged which contains a migration which has an
# earlier version but is judged to be compatible with existing migrations.
@schema_migration.create(version: 20210716123013)
@schema_migration.create_version(20210716123013)
assert_equal [
["up", "230", "Add people hobby"],
@ -210,8 +210,8 @@ def test_migrations_status_in_subdirectories
path = MIGRATIONS_ROOT + "/valid_with_subdirectories"
schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create(version: 2)
@schema_migration.create(version: 10)
@schema_migration.create_version(2)
@schema_migration.create_version(10)
assert_equal [
["down", "001", "Valid people have last names"],
@ -243,8 +243,8 @@ 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
@schema_migration.create(version: "20100101010101")
@schema_migration.create(version: "20160528010101")
@schema_migration.create_version("20100101010101")
@schema_migration.create_version("20160528010101")
assert_equal [
["down", "20090101010101", "People have hobbies"],
@ -300,7 +300,7 @@ def test_down_calls_down
end
def test_current_version
@schema_migration.create!(version: "1000")
@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
@ -455,7 +455,7 @@ def test_migrator_output_when_running_single_migration
result = migrator.run(:up, 1)
assert_equal(1, result.version)
assert_equal("1", result)
end
def test_migrator_rollback
@ -484,10 +484,10 @@ def test_migrator_db_has_no_schema_migrations_table
_, migrator = migrator_class(3)
migrator = migrator.new("valid", schema_migration)
ActiveRecord::SchemaMigration.drop_table
assert_not_predicate ActiveRecord::SchemaMigration, :table_exists?
@schema_migration.drop_table
assert_not_predicate @schema_migration, :table_exists?
migrator.migrate(1)
assert_predicate ActiveRecord::SchemaMigration, :table_exists?
assert_predicate @schema_migration, :table_exists?
end
def test_migrator_forward
@ -506,7 +506,7 @@ def test_migrator_forward
def test_only_loads_pending_migrations
# migrate up to 1
@schema_migration.create!(version: "1")
@schema_migration.create_version("1")
schema_migration = ActiveRecord::Base.connection.schema_migration
calls, migrator = migrator_class(3)

@ -29,8 +29,8 @@ def setup
@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
@connection_a.schema_migration.delete_all_versions rescue nil
@connection_b.schema_migration.delete_all_versions rescue nil
@path_a = MIGRATIONS_ROOT + "/valid"
@path_b = MIGRATIONS_ROOT + "/to_copy"
@ -57,8 +57,8 @@ def puts(*)
end
teardown do
@connection_a.schema_migration.delete_all rescue nil
@connection_b.schema_migration.delete_all rescue nil
@connection_a.schema_migration.delete_all_versions rescue nil
@connection_b.schema_migration.delete_all_versions rescue nil
ActiveRecord::Migration.verbose = @verbose_was
ActiveRecord::Migration.class_eval do
@ -69,9 +69,11 @@ def puts(*)
end
end
def test_schema_migration_class_names
assert_equal "ActiveRecord::SchemaMigration", @schema_migration_a.name
assert_equal "ARUnit2Model::SchemaMigration", @schema_migration_b.name
def test_schema_migration_is_different_for_different_connections
assert_not_equal @schema_migration_a, @schema_migration_b
assert_not_equal @schema_migration_a.connection, @schema_migration_b.connection
assert "ActiveRecord::Base", @schema_migration_a.connection.pool.pool_config.connection_name
assert "Arunit2", @schema_migration_b.connection.pool.pool_config.connection_name
end
def test_finds_migrations
@ -87,8 +89,8 @@ def test_finds_migrations
end
def test_migrations_status
@schema_migration_a.create(version: 2)
@schema_migration_a.create(version: 10)
@schema_migration_a.create_version(2)
@schema_migration_a.create_version(10)
assert_equal [
["down", "001", "Valid people have last names"],
@ -97,7 +99,7 @@ def test_migrations_status
["up", "010", "********** NO FILE **********"],
], ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a).migrations_status
@schema_migration_b.create(version: 4)
@schema_migration_b.create_version(4)
assert_equal [
["down", "001", "People have hobbies"],
@ -136,14 +138,14 @@ def test_get_all_versions
end
def test_finds_pending_migrations
@schema_migration_a.create!(version: "1")
@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, @internal_metadata_a).pending_migrations
assert_equal 1, migrations_a.size
assert_equal migration_list_a.last, migrations_a.first
@schema_migration_b.create!(version: "1")
@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, @internal_metadata_b).pending_migrations

@ -8,7 +8,8 @@ class SchemaDumperTest < ActiveRecord::TestCase
self.use_transactional_tests = false
setup do
ActiveRecord::SchemaMigration.create_table
@schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create_table
end
def standard_dump
@ -16,7 +17,7 @@ def standard_dump
end
def test_dump_schema_information_with_empty_versions
ActiveRecord::SchemaMigration.delete_all
@schema_migration.delete_all_versions
schema_info = ActiveRecord::Base.connection.dump_schema_information
assert_no_match(/INSERT INTO/, schema_info)
end
@ -24,7 +25,7 @@ def test_dump_schema_information_with_empty_versions
def test_dump_schema_information_outputs_lexically_reverse_ordered_versions_regardless_of_database_order
versions = %w{ 20100101010101 20100201010101 20100301010101 }
versions.shuffle.each do |v|
ActiveRecord::SchemaMigration.create!(version: v)
@schema_migration.create_version(v)
end
schema_info = ActiveRecord::Base.connection.dump_schema_information
@ -37,7 +38,7 @@ def test_dump_schema_information_outputs_lexically_reverse_ordered_versions_rega
STR
assert_equal expected, schema_info
ensure
ActiveRecord::SchemaMigration.delete_all
@schema_migration.delete_all_versions
end
def test_schema_dump_include_migration_version

@ -1031,14 +1031,18 @@ def test_migrate_using_empty_scope_and_verbose_mode
end
class DatabaseTasksMigrateStatusTest < DatabaseTasksMigrationTestCase
def setup
@schema_migration = ActiveRecord::Base.connection.schema_migration
end
def test_migrate_status_table
ActiveRecord::SchemaMigration.create_table
@schema_migration.create_table
output = capture_migration_status
assert_match(/database: :memory:/, output)
assert_match(/down 001 Valid people have last names/, output)
assert_match(/down 002 We need reminders/, output)
assert_match(/down 003 Innocent jointable/, output)
ActiveRecord::SchemaMigration.drop_table
@schema_migration.drop_table
end
private
@ -1169,25 +1173,27 @@ class DatabaseTasksTruncateAllTest < ActiveRecord::TestCase
fixtures :authors, :author_addresses
def setup
SchemaMigration.create_table
SchemaMigration.create!(version: SchemaMigration.table_name)
@schema_migration = ActiveRecord::Base.connection.schema_migration
@schema_migration.create_table
@schema_migration.create_version(@schema_migration.table_name)
InternalMetadata.create_table
InternalMetadata.create!(key: InternalMetadata.table_name)
@old_configurations = ActiveRecord::Base.configurations
end
def teardown
SchemaMigration.delete_all
@schema_migration.delete_all_versions
InternalMetadata.delete_all
clean_up_connection_handler
ActiveRecord::Base.configurations = @old_configurations
end
def test_truncate_tables
assert_operator SchemaMigration.count, :>, 0
assert_operator @schema_migration.count, :>, 0
assert_operator InternalMetadata.count, :>, 0
assert_operator Author.count, :>, 0
assert_operator AuthorAddress.count, :>, 0
old_configurations = ActiveRecord::Base.configurations
db_config = ActiveRecord::Base.configurations.configs_for(env_name: "arunit", name: "primary")
configurations = { development: db_config.configuration_hash }
ActiveRecord::Base.configurations = configurations
@ -1198,12 +1204,10 @@ def test_truncate_tables
)
end
assert_operator SchemaMigration.count, :>, 0
assert_operator @schema_migration.count, :>, 0
assert_operator InternalMetadata.count, :>, 0
assert_equal 0, Author.count
assert_equal 0, AuthorAddress.count
ensure
ActiveRecord::Base.configurations = old_configurations
end
end
@ -1211,14 +1215,12 @@ class DatabaseTasksTruncateAllWithPrefixTest < DatabaseTasksTruncateAllTest
setup do
ActiveRecord::Base.table_name_prefix = "p_"
SchemaMigration.reset_table_name
InternalMetadata.reset_table_name
end
teardown do
ActiveRecord::Base.table_name_prefix = nil
SchemaMigration.reset_table_name
InternalMetadata.reset_table_name
end
end
@ -1227,14 +1229,12 @@ class DatabaseTasksTruncateAllWithSuffixTest < DatabaseTasksTruncateAllTest
setup do
ActiveRecord::Base.table_name_suffix = "_s"
SchemaMigration.reset_table_name
InternalMetadata.reset_table_name
end
teardown do
ActiveRecord::Base.table_name_suffix = nil
SchemaMigration.reset_table_name
InternalMetadata.reset_table_name
end
end

@ -135,14 +135,14 @@ class Post < ApplicationRecord
initial = [
ActiveStorage::Record, ActiveStorage::Blob, ActiveStorage::Attachment,
ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata, ApplicationRecord
ActiveRecord::InternalMetadata, ApplicationRecord
].collect(&:to_s).sort
assert_equal initial, ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq
get "/load"
assert_equal [Post].collect(&:to_s).sort, ActiveRecord::Base.descendants.collect(&:to_s).sort - initial
get "/unload"
assert_equal ["ActiveRecord::InternalMetadata", "ActiveRecord::SchemaMigration"], ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq
assert_equal ["ActiveRecord::InternalMetadata"], ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq
end
test "initialize can't be called twice" do

@ -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, ActiveRecord::SchemaMigration).migrations
ActiveRecord::MigrationContext.new(migration_root, ActiveRecord::SchemaMigration::NullSchemaMigration.new).migrations
end
test "serving sprocket's assets" do