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:
parent
d695972025
commit
93ddf338a0
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user