Move InternalMetadata to an independent object

Followup to #45908 to match the same behavior as SchemaMigration

Previously, InternalMetadata 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 InternalMetadata inherits from Base, this PR makes
InternalMetadata an independent object. Then each connection can get it's
own InternalMetadata object. This change required defining the methods
that InternalMetadata 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 InternalMetadata object which
stores the connection.

This change also required adding a NullInternalMetadata 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::InternalMetadata 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.

Both schema migration and internal metadata are blockers to removing
`Base.connection` and `Base.establish_connection` from rake tasks, work
that is required to drop the reliance on `Base.connection` which will
enable more robust (and correct) sharding behavior in Rails..
This commit is contained in:
eileencodes 2022-09-08 14:47:36 -04:00
parent d695972025
commit 93ddf338a0
No known key found for this signature in database
GPG Key ID: BA5C575120BBE8DF
13 changed files with 205 additions and 118 deletions

@ -1,3 +1,9 @@
* Move `ActiveRecord::InternalMetadata` to an independent object.
`ActiveRecord::InternalMetadata` 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 quoting `ActiveSupport::Duration` as an integer
Using ActiveSupport::Duration as an interpolated bind parameter in a SQL

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

@ -9,58 +9,135 @@ module ActiveRecord
#
# This is enabled by default. To disable this functionality set
# `use_metadata_table` to false in your database configuration.
class InternalMetadata < ActiveRecord::Base # :nodoc:
self.record_timestamps = true
class InternalMetadata # :nodoc:
class NullInternalMetadata
end
class << self
def enabled?
connection.use_metadata_table?
attr_reader :connection, :arel_table
def initialize(connection)
@connection = connection
@arel_table = Arel::Table.new(table_name)
end
def enabled?
connection.use_metadata_table?
end
def primary_key
"key"
end
def value_key
"value"
end
def table_name
"#{ActiveRecord::Base.table_name_prefix}#{ActiveRecord::Base.internal_metadata_table_name}#{ActiveRecord::Base.table_name_suffix}"
end
def []=(key, value)
return unless enabled?
update_or_create_entry(key, value)
end
def [](key)
return unless enabled?
if entry = select_entry(key)
entry[value_key]
end
end
def primary_key
"key"
def delete_all_entries
dm = Arel::DeleteManager.new(arel_table)
connection.delete(dm, "#{self} Destroy")
end
def count
sm = Arel::SelectManager.new(arel_table)
sm.project(*Arel::Nodes::Count.new([Arel.star]))
connection.select_values(sm).first
end
def create_table_and_set_flags(environment, schema_sha1 = nil)
create_table
update_or_create_entry(:environment, environment)
update_or_create_entry(:schema_sha1, schema_sha1) if schema_sha1
end
# Creates an internal metadata table with columns +key+ and +value+
def create_table
return unless enabled?
unless connection.table_exists?(table_name)
connection.create_table(table_name, id: false) do |t|
t.string :key, **connection.internal_string_options_for_primary_key
t.string :value
t.timestamps
end
end
end
def table_name
"#{table_name_prefix}#{internal_metadata_table_name}#{table_name_suffix}"
end
def drop_table
return unless enabled?
def []=(key, value)
return unless enabled?
connection.drop_table table_name, if_exists: true
end
find_or_initialize_by(key: key).update!(value: value)
end
def table_exists?
connection.schema_cache.data_source_exists?(table_name)
end
def [](key)
return unless enabled?
private
def update_or_create_entry(key, value)
entry = select_entry(key)
where(key: key).pick(:value)
end
def create_table_and_set_flags(environment, schema_sha1 = nil)
create_table
self[:environment] = environment
self[:schema_sha1] = schema_sha1 if schema_sha1
end
# Creates an internal metadata table with columns +key+ and +value+
def create_table
return unless enabled?
unless connection.table_exists?(table_name)
connection.create_table(table_name, id: false) do |t|
t.string :key, **connection.internal_string_options_for_primary_key
t.string :value
t.timestamps
end
if entry
update_entry(key, value)
else
create_entry(key, value)
end
end
def drop_table
return unless enabled?
connection.drop_table table_name, if_exists: true
def current_time
connection.default_timezone == :utc ? Time.now.utc : Time.now
end
def create_entry(key, value)
im = Arel::InsertManager.new(arel_table)
im.insert [
[arel_table[primary_key], key],
[arel_table[value_key], value],
[arel_table[:created_at], current_time],
[arel_table[:updated_at], current_time]
]
connection.insert(im, "#{self} Create", primary_key, key)
end
def update_entry(key, new_value)
um = Arel::UpdateManager.new(arel_table)
um.set [
[arel_table[value_key], new_value],
[arel_table[:updated_at], current_time]
]
um.where(arel_table[primary_key].eq(key))
connection.update(um, "#{self} Update")
end
def select_entry(key)
sm = Arel::SelectManager.new(arel_table)
sm.project(Arel::Nodes::SqlLiteral.new("*"))
sm.where(arel_table[primary_key].eq(Arel::Nodes::BindParam.new(key)))
sm.order(arel_table[primary_key].asc)
sm.limit = 1
connection.select_all(sm).first
end
end
end
end

@ -952,11 +952,13 @@ def copy(destination, sources, options = {})
copied = []
FileUtils.mkdir_p(destination) unless File.exist?(destination)
schema_migration = SchemaMigration::NullSchemaMigration.new
internal_metadata = InternalMetadata::NullInternalMetadata.new
destination_migrations = ActiveRecord::MigrationContext.new(destination, SchemaMigration::NullSchemaMigration.new).migrations
destination_migrations = ActiveRecord::MigrationContext.new(destination, schema_migration, internal_metadata).migrations
last = destination_migrations.last
sources.each do |scope, path|
source_migrations = ActiveRecord::MigrationContext.new(path, SchemaMigration::NullSchemaMigration.new).migrations
source_migrations = ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations
source_migrations.each do |migration|
source = File.binread(migration.filename)
@ -1081,16 +1083,22 @@ def load_migration
class MigrationContext
attr_reader :migrations_paths, :schema_migration, :internal_metadata
def initialize(migrations_paths, schema_migration = nil, internal_metadata = InternalMetadata)
def initialize(migrations_paths, schema_migration = nil, internal_metadata = nil)
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
if internal_metadata == InternalMetadata
internal_metadata = InternalMetadata.new(ActiveRecord::Base.connection)
ActiveSupport::Deprecation.warn("InternalMetadata no longer inherits from ActiveRecord::Base. Please instaniate a new InternalMetadata object with the desired connection, ie `ActiveRecord::InternalMetadata.new(ActiveRecord::Base.connection)`.")
end
@migrations_paths = migrations_paths
@schema_migration = schema_migration || SchemaMigration.new(ActiveRecord::Base.connection)
@internal_metadata = internal_metadata
@internal_metadata = internal_metadata || InternalMetadata.new(ActiveRecord::Base.connection)
end
# Runs the migrations in the +migrations_path+.
@ -1263,8 +1271,9 @@ class << self
# For cases where a table doesn't exist like loading from schema cache
def current_version
schema_migration = SchemaMigration.new(ActiveRecord::Base.connection)
internal_metadata = InternalMetadata.new(ActiveRecord::Base.connection)
MigrationContext.new(migrations_paths, schema_migration, InternalMetadata).current_version
MigrationContext.new(migrations_paths, schema_migration, internal_metadata).current_version
end
end

@ -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_"
@internal_metadata.reset_table_name
ActiveRecord::Schema.define(version: 7) do
create_table :fruits do |t|
t.column :color, :string
@ -81,7 +80,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
@internal_metadata.reset_table_name
end
def test_schema_raises_an_error_for_invalid_column_type

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

@ -81,7 +81,7 @@ def setup
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 = assert_deprecated { ActiveRecord::MigrationContext.new(migrations_path, ActiveRecord::SchemaMigration, ActiveRecord::InternalMetadata) }
migrator.up
assert_equal 3, migrator.current_version
@ -671,21 +671,20 @@ def test_schema_migrations_table_name
def test_internal_metadata_table_name
original_internal_metadata_table_name = ActiveRecord::Base.internal_metadata_table_name
assert_equal "ar_internal_metadata", ActiveRecord::InternalMetadata.table_name
assert_equal "ar_internal_metadata", @internal_metadata.table_name
ActiveRecord::Base.table_name_prefix = "p_"
ActiveRecord::Base.table_name_suffix = "_s"
Reminder.reset_table_name
assert_equal "p_ar_internal_metadata_s", ActiveRecord::InternalMetadata.table_name
assert_equal "p_ar_internal_metadata_s", @internal_metadata.table_name
ActiveRecord::Base.internal_metadata_table_name = "changed"
Reminder.reset_table_name
assert_equal "p_changed_s", ActiveRecord::InternalMetadata.table_name
assert_equal "p_changed_s", @internal_metadata.table_name
ActiveRecord::Base.table_name_prefix = ""
ActiveRecord::Base.table_name_suffix = ""
Reminder.reset_table_name
assert_equal "changed", ActiveRecord::InternalMetadata.table_name
assert_equal "changed", @internal_metadata.table_name
ensure
ActiveRecord::Base.internal_metadata_table_name = original_internal_metadata_table_name
ActiveRecord::InternalMetadata.reset_table_name
Reminder.reset_table_name
end
@ -714,7 +713,7 @@ def test_internal_metadata_stores_environment
end
def test_internal_metadata_stores_environment_when_migration_fails
@internal_metadata.delete_all
@internal_metadata.delete_all_entries
current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
migration = Class.new(ActiveRecord::Migration::Current) {
@ -730,7 +729,7 @@ def migrate(x)
end
def test_internal_metadata_stores_environment_when_other_data_exists
@internal_metadata.delete_all
@internal_metadata.delete_all_entries
@internal_metadata[:foo] = "bar"
current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call

@ -92,7 +92,8 @@ def test_migrator_with_missing_version_numbers
def test_finds_migrations
schema_migration = ActiveRecord::Base.connection.schema_migration
migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", schema_migration).migrations
internal_metadata = ActiveRecord::Base.connection.internal_metadata
migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid", schema_migration, internal_metadata).migrations
[[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i|
assert_equal migrations[i].version, pair.first
@ -102,7 +103,8 @@ def test_finds_migrations
def test_finds_migrations_in_subdirectories
schema_migration = ActiveRecord::Base.connection.schema_migration
migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid_with_subdirectories", schema_migration).migrations
internal_metadata = ActiveRecord::Base.connection.internal_metadata
migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid_with_subdirectories", schema_migration, internal_metadata).migrations
[[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i|
assert_equal migrations[i].version, pair.first
@ -112,8 +114,9 @@ def test_finds_migrations_in_subdirectories
def test_finds_migrations_from_two_directories
schema_migration = ActiveRecord::Base.connection.schema_migration
internal_metadata = ActiveRecord::Base.connection.internal_metadata
directories = [MIGRATIONS_ROOT + "/valid_with_timestamps", MIGRATIONS_ROOT + "/to_copy_with_timestamps"]
migrations = ActiveRecord::MigrationContext.new(directories, schema_migration).migrations
migrations = ActiveRecord::MigrationContext.new(directories, schema_migration, internal_metadata).migrations
[[20090101010101, "PeopleHaveHobbies"],
[20090101010202, "PeopleHaveDescriptions"],
@ -127,15 +130,17 @@ def test_finds_migrations_from_two_directories
def test_finds_migrations_in_numbered_directory
schema_migration = ActiveRecord::Base.connection.schema_migration
migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/10_urban", schema_migration).migrations
internal_metadata = ActiveRecord::Base.connection.internal_metadata
migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/10_urban", schema_migration, internal_metadata).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
internal_metadata = ActiveRecord::Base.connection.internal_metadata
list = Dir.chdir(MIGRATIONS_ROOT) do
ActiveRecord::MigrationContext.new("valid", schema_migration).migrations
ActiveRecord::MigrationContext.new("valid", schema_migration, internal_metadata).migrations
end
migration_proxy = list.find { |item|
@ -156,6 +161,7 @@ def test_finds_pending_migrations
def test_migrations_status
path = MIGRATIONS_ROOT + "/valid"
schema_migration = ActiveRecord::Base.connection.schema_migration
internal_metadata = ActiveRecord::Base.connection.internal_metadata
@schema_migration.create_version(2)
@schema_migration.create_version(10)
@ -165,12 +171,13 @@ def test_migrations_status
["up", "002", "We need reminders"],
["down", "003", "Innocent jointable"],
["up", "010", "********** NO FILE **********"],
], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status
], ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations_status
end
def test_migrations_status_order_new_and_old_version
path = MIGRATIONS_ROOT + "/old_and_new_versions"
schema_migration = ActiveRecord::Base.connection.schema_migration
internal_metadata = ActiveRecord::Base.connection.internal_metadata
@schema_migration.create_version(230)
@schema_migration.create_version(231)
@ -182,12 +189,13 @@ def test_migrations_status_order_new_and_old_version
["up", "231", "Add people last name"],
["up", "20210716122844", "Add people description"],
["up", "20210716123013", "Add people number of legs"],
], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status
], ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations_status
end
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
internal_metadata = ActiveRecord::Base.connection.internal_metadata
@schema_migration.create_version(230)
@schema_migration.create_version(231)
@ -203,12 +211,13 @@ def test_migrations_status_order_new_and_old_version_applied_out_of_order
["up", "231", "Add people last name"],
["down", "20210716122844", "Add people description"],
["up", "20210716123013", "Add people number of legs"],
], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status
], ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations_status
end
def test_migrations_status_in_subdirectories
path = MIGRATIONS_ROOT + "/valid_with_subdirectories"
schema_migration = ActiveRecord::Base.connection.schema_migration
internal_metadata = ActiveRecord::Base.connection.internal_metadata
@schema_migration.create_version(2)
@schema_migration.create_version(10)
@ -218,13 +227,14 @@ def test_migrations_status_in_subdirectories
["up", "002", "We need reminders"],
["down", "003", "Innocent jointable"],
["up", "010", "********** NO FILE **********"],
], ActiveRecord::MigrationContext.new(path, schema_migration).migrations_status
], ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).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
internal_metadata = ActiveRecord::Base.connection.internal_metadata
ActiveRecord::Migrator.migrations_paths = path
ActiveRecord::Schema.define(version: 3) do
@ -234,7 +244,7 @@ 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, schema_migration).migrations_status
], ActiveRecord::MigrationContext.new(path, schema_migration, internal_metadata).migrations_status
ensure
ActiveRecord::Migrator.migrations_paths = prev_paths
end
@ -242,6 +252,7 @@ def test_migrations_status_with_schema_define_in_subdirectories
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
internal_metadata = ActiveRecord::Base.connection.internal_metadata
@schema_migration.create_version("20100101010101")
@schema_migration.create_version("20160528010101")
@ -253,7 +264,7 @@ 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, schema_migration).migrations_status
], ActiveRecord::MigrationContext.new(paths, schema_migration, internal_metadata).migrations_status
end
def test_migrator_interleaved_migrations
@ -302,7 +313,8 @@ def test_down_calls_down
def test_current_version
@schema_migration.create_version("1000")
schema_migration = ActiveRecord::Base.connection.schema_migration
migrator = ActiveRecord::MigrationContext.new("db/migrate", schema_migration)
internal_metadata = ActiveRecord::Base.connection.internal_metadata
migrator = ActiveRecord::MigrationContext.new("db/migrate", schema_migration, internal_metadata)
assert_equal 1000, migrator.current_version
end

@ -36,11 +36,12 @@ def setup
@path_b = MIGRATIONS_ROOT + "/to_copy"
@schema_migration_a = @connection_a.schema_migration
@migrations_a = ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a).migrations
@internal_metadata_a = @connection_a.internal_metadata
@migrations_a = ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a, @internal_metadata_a).migrations
@schema_migration_b = @connection_b.schema_migration
@migrations_b = ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b).migrations
@internal_metadata_b = @connection_b.internal_metadata
@migrations_b = ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b, @internal_metadata_b).migrations
@migrations_a_list = [[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]]
@migrations_b_list = [[1, "PeopleHaveHobbies"], [2, "PeopleHaveDescriptions"]]
@ -97,7 +98,7 @@ def test_migrations_status
["up", "002", "We need reminders"],
["down", "003", "Innocent jointable"],
["up", "010", "********** NO FILE **********"],
], ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a).migrations_status
], ActiveRecord::MigrationContext.new(@path_a, @schema_migration_a, @internal_metadata_a).migrations_status
@schema_migration_b.create_version(4)
@ -105,7 +106,7 @@ def test_migrations_status
["down", "001", "People have hobbies"],
["down", "002", "People have descriptions"],
["up", "004", "********** NO FILE **********"]
], ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b).migrations_status
], ActiveRecord::MigrationContext.new(@path_b, @schema_migration_b, @internal_metadata_b).migrations_status
end
def test_get_all_versions

@ -108,17 +108,22 @@ def test_raises_an_error_when_called_with_protected_environment_which_name_is_a_
end
def test_raises_an_error_if_no_migrations_have_been_made
ActiveRecord::Base.connection.internal_metadata.stub(:table_exists?, false) do
assert_called_on_instance_of(
ActiveRecord::MigrationContext,
:current_version,
returns: 1
) do
assert_raise(ActiveRecord::NoEnvironmentInSchemaError) do
ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
end
end
connection = ActiveRecord::Base.connection
internal_metadata = connection.internal_metadata
schema_migration = connection.schema_migration
schema_migration.create_table
schema_migration.create_version("1")
assert_predicate internal_metadata, :table_exists?
internal_metadata.drop_table
assert_not_predicate internal_metadata, :table_exists?
assert_raises(ActiveRecord::NoEnvironmentInSchemaError) do
ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
end
ensure
schema_migration.delete_version("1")
internal_metadata.create_table
end
end
@ -1176,21 +1181,24 @@ def setup
@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)
@internal_metadata = ActiveRecord::Base.connection.internal_metadata
@internal_metadata.create_table
@internal_metadata[@internal_metadata.table_name] = nil
@old_configurations = ActiveRecord::Base.configurations
end
def teardown
@schema_migration.delete_all_versions
InternalMetadata.delete_all
@internal_metadata.delete_all_entries
clean_up_connection_handler
ActiveRecord::Base.configurations = @old_configurations
end
def test_truncate_tables
assert_operator @schema_migration.count, :>, 0
assert_operator InternalMetadata.count, :>, 0
assert_operator @internal_metadata.count, :>, 0
assert_operator Author.count, :>, 0
assert_operator AuthorAddress.count, :>, 0
@ -1205,7 +1213,7 @@ def test_truncate_tables
end
assert_operator @schema_migration.count, :>, 0
assert_operator InternalMetadata.count, :>, 0
assert_operator @internal_metadata.count, :>, 0
assert_equal 0, Author.count
assert_equal 0, AuthorAddress.count
end
@ -1214,28 +1222,20 @@ def test_truncate_tables
class DatabaseTasksTruncateAllWithPrefixTest < DatabaseTasksTruncateAllTest
setup do
ActiveRecord::Base.table_name_prefix = "p_"
InternalMetadata.reset_table_name
end
teardown do
ActiveRecord::Base.table_name_prefix = nil
InternalMetadata.reset_table_name
end
end
class DatabaseTasksTruncateAllWithSuffixTest < DatabaseTasksTruncateAllTest
setup do
ActiveRecord::Base.table_name_suffix = "_s"
InternalMetadata.reset_table_name
end
teardown do
ActiveRecord::Base.table_name_suffix = nil
InternalMetadata.reset_table_name
end
end
end

@ -134,15 +134,14 @@ class Post < ApplicationRecord
setup_ar!
initial = [
ActiveStorage::Record, ActiveStorage::Blob, ActiveStorage::Attachment,
ActiveRecord::InternalMetadata, ApplicationRecord
ActiveStorage::Record, ActiveStorage::Blob, ActiveStorage::Attachment, 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::Base.descendants.collect(&:to_s).sort.uniq
assert_equal [], ActiveRecord::Base.descendants.collect(&:to_s).sort.uniq
end
test "initialize can't be called twice" do

@ -586,8 +586,8 @@ def db_fixtures_load(expected_database)
app_file "db/schema.rb", ""
rails "db:setup"
test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip }
development_environment = lambda { rails("runner", "puts ActiveRecord::InternalMetadata[:environment]").strip }
test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::Base.connection.internal_metadata[:environment]").strip }
development_environment = lambda { rails("runner", "puts ActiveRecord::Base.connection.internal_metadata[:environment]").strip }
assert_equal "test", test_environment.call
assert_equal "development", development_environment.call
@ -607,7 +607,7 @@ def db_fixtures_load(expected_database)
app_file "db/schema.rb", ""
rails "db:test:prepare"
test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::InternalMetadata[:environment]").strip }
test_environment = lambda { rails("runner", "-e", "test", "puts ActiveRecord::Base.connection.internal_metadata[:environment]").strip }
assert_equal "test", test_environment.call

@ -34,7 +34,9 @@ def boot_rails
def migrations
migration_root = File.expand_path(ActiveRecord::Migrator.migrations_paths.first, app_path)
ActiveRecord::MigrationContext.new(migration_root, ActiveRecord::SchemaMigration::NullSchemaMigration.new).migrations
sm = ActiveRecord::SchemaMigration::NullSchemaMigration.new
im = ActiveRecord::InternalMetadata::NullInternalMetadata.new
ActiveRecord::MigrationContext.new(migration_root, sm, im).migrations
end
test "serving sprocket's assets" do