aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoreileencodes <eileencodes@gmail.com>2018-01-10 10:25:13 -0500
committereileencodes <eileencodes@gmail.com>2018-01-18 08:55:03 -0500
commita2827ec9811b5012e8e366011fd44c8eb53fc714 (patch)
treece158384df40f9cfe128bb659b0372a6e7bb8f07
parent198e3e3cb784dae54d8d4346667d3fb08c889335 (diff)
downloadrails-a2827ec9811b5012e8e366011fd44c8eb53fc714.tar.gz
rails-a2827ec9811b5012e8e366011fd44c8eb53fc714.tar.bz2
rails-a2827ec9811b5012e8e366011fd44c8eb53fc714.zip
Refactor migration to move migrations paths to connection
Rails has some support for multiple databases but it can be hard to handle migrations with those. The easiest way to implement multiple databases is to contain migrations into their own folder ("db/migrate" for the primary db and "db/seconddb_migrate" for the second db). Without this you would need to write code that allowed you to switch connections in migrations. I can tell you from experience that is not a fun way to implement multiple databases. This refactoring is a pre-requisite for implementing other features related to parallel testing and improved handling for multiple databases. The refactoring here moves the class methods from the `Migrator` class into it's own new class `MigrationContext`. The goal was to move the `migrations_paths` method off of the `Migrator` class and onto the connection. This allows users to do the following in their `database.yml`: ``` development: adapter: mysql2 username: root password: development_seconddb: adapter: mysql2 username: root password: migrations_paths: "db/second_db_migrate" ``` Migrations for the `seconddb` can now be store in the `db/second_db_migrate` directory. Migrations for the primary database are stored in `db/migrate`". The refactoring here drastically reduces the internal API for migrations since we don't need to pass `migrations_paths` around to every single method. Additionally this change does not require any Rails applications to make changes unless they want to use the new public API. All of the class methods from the `Migrator` class were `nodoc`'d except for the `migrations_paths` and `migrations_path` getter/setters respectively.
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb4
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb8
-rw-r--r--activerecord/lib/active_record/connection_adapters/schema_cache.rb4
-rw-r--r--activerecord/lib/active_record/migration.rb256
-rw-r--r--activerecord/lib/active_record/railtie.rb1
-rw-r--r--activerecord/lib/active_record/railties/databases.rake19
-rw-r--r--activerecord/lib/active_record/schema.rb2
-rw-r--r--activerecord/lib/active_record/schema_dumper.rb2
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb12
-rw-r--r--activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb2
-rw-r--r--activerecord/test/cases/ar_schema_test.rb4
-rw-r--r--activerecord/test/cases/migration/pending_migrations_test.rb50
-rw-r--r--activerecord/test/cases/migration_test.rb71
-rw-r--r--activerecord/test/cases/migrator_test.rb148
-rw-r--r--activerecord/test/cases/tasks/database_tasks_test.rb124
-rw-r--r--activestorage/test/database/setup.rb2
-rw-r--r--railties/lib/rails/info.rb2
-rw-r--r--railties/test/application/rake/migrations_test.rb12
-rw-r--r--railties/test/railties/engine_test.rb2
19 files changed, 417 insertions, 308 deletions
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
index 4f58b0242c..c32a234be4 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_statements.rb
@@ -1049,8 +1049,8 @@ module ActiveRecord
sm_table = quote_table_name(ActiveRecord::SchemaMigration.table_name)
migrated = ActiveRecord::SchemaMigration.all_versions.map(&:to_i)
- versions = ActiveRecord::Migrator.migration_files(migrations_paths).map do |file|
- ActiveRecord::Migrator.parse_migration_filename(file).first.to_i
+ versions = migration_context.migration_files.map do |file|
+ migration_context.parse_migration_filename(file).first.to_i
end
unless migrated.include?(version)
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index 2655407d75..7bd54f777e 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -119,6 +119,14 @@ module ActiveRecord
end
end
+ def migrations_paths
+ @config[:migrations_paths] || Migrator.migrations_paths
+ end
+
+ def migration_context
+ MigrationContext.new(migrations_paths)
+ end
+
class Version
include Comparable
diff --git a/activerecord/lib/active_record/connection_adapters/schema_cache.rb b/activerecord/lib/active_record/connection_adapters/schema_cache.rb
index f34b6733da..c29cf1f9a1 100644
--- a/activerecord/lib/active_record/connection_adapters/schema_cache.rb
+++ b/activerecord/lib/active_record/connection_adapters/schema_cache.rb
@@ -28,7 +28,7 @@ module ActiveRecord
coder["columns_hash"] = @columns_hash
coder["primary_keys"] = @primary_keys
coder["data_sources"] = @data_sources
- coder["version"] = ActiveRecord::Migrator.current_version
+ coder["version"] = connection.migration_context.current_version
end
def init_with(coder)
@@ -100,7 +100,7 @@ module ActiveRecord
def marshal_dump
# if we get current version during initialization, it happens stack over flow.
- @version = ActiveRecord::Migrator.current_version
+ @version = connection.migration_context.current_version
[@version, @columns, @columns_hash, @primary_keys, @data_sources]
end
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index f6648a4e3d..4e36e49905 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -3,6 +3,7 @@
require "set"
require "zlib"
require "active_support/core_ext/module/attribute_accessors"
+require "active_record/tasks/database_tasks"
module ActiveRecord
class MigrationError < ActiveRecordError#:nodoc:
@@ -550,7 +551,7 @@ module ActiveRecord
end
def call(env)
- mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
+ mtime = ActiveRecord::Base.connection.migration_context.last_migration.mtime.to_i
if @last_check < mtime
ActiveRecord::Migration.check_pending!(connection)
@last_check = mtime
@@ -575,11 +576,11 @@ module ActiveRecord
# Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
def check_pending!(connection = Base.connection)
- raise ActiveRecord::PendingMigrationError if ActiveRecord::Migrator.needs_migration?(connection)
+ raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
end
def load_schema_if_pending!
- if ActiveRecord::Migrator.needs_migration? || !ActiveRecord::Migrator.any_migrations?
+ if Base.connection.migration_context.needs_migration? || !Base.connection.migration_context.any_migrations?
# Roundtrip to Rake to allow plugins to hook into database initialization.
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
FileUtils.cd(root) do
@@ -876,10 +877,10 @@ module ActiveRecord
FileUtils.mkdir_p(destination) unless File.exist?(destination)
- destination_migrations = ActiveRecord::Migrator.migrations(destination)
+ destination_migrations = ActiveRecord::MigrationContext.new(destination).migrations
last = destination_migrations.last
sources.each do |scope, path|
- source_migrations = ActiveRecord::Migrator.migrations(path)
+ source_migrations = ActiveRecord::MigrationContext.new(path).migrations
source_migrations.each do |migration|
source = File.binread(migration.filename)
@@ -997,132 +998,147 @@ module ActiveRecord
end
end
- class Migrator#:nodoc:
- class << self
- attr_writer :migrations_paths
- alias :migrations_path= :migrations_paths=
-
- def migrate(migrations_paths, target_version = nil, &block)
- case
- when target_version.nil?
- up(migrations_paths, target_version, &block)
- when current_version == 0 && target_version == 0
- []
- when current_version > target_version
- down(migrations_paths, target_version, &block)
- else
- up(migrations_paths, target_version, &block)
- end
- end
+ class MigrationContext # :nodoc:
+ attr_reader :migrations_paths
- def rollback(migrations_paths, steps = 1)
- move(:down, migrations_paths, steps)
- end
+ def initialize(migrations_paths)
+ @migrations_paths = migrations_paths
+ end
- def forward(migrations_paths, steps = 1)
- move(:up, migrations_paths, steps)
+ def migrate(target_version = nil, &block)
+ case
+ when target_version.nil?
+ up(target_version, &block)
+ when current_version == 0 && target_version == 0
+ []
+ when current_version > target_version
+ down(target_version, &block)
+ else
+ up(target_version, &block)
end
+ end
- def up(migrations_paths, target_version = nil)
- migrations = migrations(migrations_paths)
- migrations.select! { |m| yield m } if block_given?
+ def rollback(steps = 1)
+ move(:down, steps)
+ end
- new(:up, migrations, target_version).migrate
+ def forward(steps = 1)
+ move(:up, steps)
+ end
+
+ def up(target_version = nil)
+ selected_migrations = if block_given?
+ migrations.select { |m| yield m }
+ else
+ migrations
end
- def down(migrations_paths, target_version = nil)
- migrations = migrations(migrations_paths)
- migrations.select! { |m| yield m } if block_given?
+ Migrator.new(:up, selected_migrations, target_version).migrate
+ end
- new(:down, migrations, target_version).migrate
+ def down(target_version = nil)
+ selected_migrations = if block_given?
+ migrations.select { |m| yield m }
+ else
+ migrations
end
- def run(direction, migrations_paths, target_version)
- new(direction, migrations(migrations_paths), target_version).run
- end
+ Migrator.new(:down, migrations, target_version).migrate
+ end
- def open(migrations_paths)
- new(:up, migrations(migrations_paths), nil)
- end
+ def run(direction, target_version)
+ Migrator.new(direction, migrations, target_version).run
+ end
- def get_all_versions
- if SchemaMigration.table_exists?
- SchemaMigration.all_versions.map(&:to_i)
- else
- []
- end
- end
+ def open
+ Migrator.new(:up, migrations, nil)
+ end
- def current_version(connection = nil)
- get_all_versions.max || 0
- rescue ActiveRecord::NoDatabaseError
+ def get_all_versions
+ if SchemaMigration.table_exists?
+ SchemaMigration.all_versions.map(&:to_i)
+ else
+ []
end
+ end
- def needs_migration?(connection = nil)
- (migrations(migrations_paths).collect(&:version) - get_all_versions).size > 0
- end
+ def current_version(connection = nil)
+ get_all_versions.max || 0
+ rescue ActiveRecord::NoDatabaseError
+ end
- def any_migrations?
- migrations(migrations_paths).any?
- end
+ def needs_migration?
+ (migrations.collect(&:version) - get_all_versions).size > 0
+ end
- def last_migration #:nodoc:
- migrations(migrations_paths).last || NullMigration.new
- end
+ def any_migrations?
+ migrations.any?
+ end
- def migrations_paths
- @migrations_paths ||= ["db/migrate"]
- # just to not break things if someone uses: migrations_path = some_string
- Array(@migrations_paths)
- end
+ def last_migration #:nodoc:
+ migrations.last || NullMigration.new
+ end
- def parse_migration_filename(filename) # :nodoc:
- File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
+ def parse_migration_filename(filename) # :nodoc:
+ File.basename(filename).scan(Migration::MigrationFilenameRegexp).first
+ end
+
+ def migrations
+ migrations = migration_files.map do |file|
+ version, name, scope = parse_migration_filename(file)
+ raise IllegalMigrationNameError.new(file) unless version
+ version = version.to_i
+ name = name.camelize
+
+ MigrationProxy.new(name, version, file, scope)
end
- def migrations(paths)
- paths = Array(paths)
+ migrations.sort_by(&:version)
+ end
- migrations = migration_files(paths).map do |file|
- version, name, scope = parse_migration_filename(file)
- raise IllegalMigrationNameError.new(file) unless version
- version = version.to_i
- name = name.camelize
+ def migrations_status
+ db_list = ActiveRecord::SchemaMigration.normalized_versions
- MigrationProxy.new(name, version, file, scope)
- end
+ file_list = migration_files.map do |file|
+ version, name, scope = parse_migration_filename(file)
+ raise IllegalMigrationNameError.new(file) unless version
+ version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
+ status = db_list.delete(version) ? "up" : "down"
+ [status, version, (name + scope).humanize]
+ end.compact
- migrations.sort_by(&:version)
+ db_list.map! do |version|
+ ["up", version, "********** NO FILE **********"]
end
- def migrations_status(paths)
- paths = Array(paths)
-
- db_list = ActiveRecord::SchemaMigration.normalized_versions
+ (db_list + file_list).sort_by { |_, version, _| version }
+ end
- file_list = migration_files(paths).map do |file|
- version, name, scope = parse_migration_filename(file)
- raise IllegalMigrationNameError.new(file) unless version
- version = ActiveRecord::SchemaMigration.normalize_migration_number(version)
- status = db_list.delete(version) ? "up" : "down"
- [status, version, (name + scope).humanize]
- end.compact
+ def migration_files
+ paths = Array(migrations_paths)
+ Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
+ end
- db_list.map! do |version|
- ["up", version, "********** NO FILE **********"]
- end
+ def current_environment
+ ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
+ end
- (db_list + file_list).sort_by { |_, version, _| version }
- end
+ def protected_environment?
+ ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
+ end
- def migration_files(paths)
- Dir[*paths.flat_map { |path| "#{path}/**/[0-9]*_*.rb" }]
- end
+ def last_stored_environment
+ return nil if current_version == 0
+ raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
- private
+ environment = ActiveRecord::InternalMetadata[:environment]
+ raise NoEnvironmentInSchemaError unless environment
+ environment
+ end
- def move(direction, migrations_paths, steps)
- migrator = new(direction, migrations(migrations_paths))
+ private
+ def move(direction, steps)
+ migrator = Migrator.new(direction, migrations)
if current_version != 0 && !migrator.current_migration
raise UnknownMigrationVersionError.new(current_version)
@@ -1137,10 +1153,29 @@ module ActiveRecord
finish = migrator.migrations[start_index + steps]
version = finish ? finish.version : 0
- send(direction, migrations_paths, version)
+ send(direction, version)
+ end
+ end
+
+ class Migrator # :nodoc:
+ class << self
+ attr_accessor :migrations_paths
+
+ def migrations_path=(path)
+ ActiveSupport::Deprecation.warn \
+ "ActiveRecord::Migrator.migrations_paths= is now deprecated and will be removed in Rails 6.0." \
+ "You can set the `migrations_paths` on the `connection` instead through the `database.yml`."
+ self.migrations_paths = [path]
+ end
+
+ # For cases where a table doesn't exist like loading from schema cache
+ def current_version(connection = nil)
+ MigrationContext.new(migrations_paths).current_version(connection)
end
end
+ self.migrations_paths = ["db/migrate"]
+
def initialize(direction, migrations, target_version = nil)
@direction = direction
@target_version = target_version
@@ -1203,7 +1238,7 @@ module ActiveRecord
end
def load_migrated
- @migrated_versions = Set.new(self.class.get_all_versions)
+ @migrated_versions = Set.new(Base.connection.migration_context.get_all_versions)
end
private
@@ -1235,7 +1270,7 @@ module ActiveRecord
# Stores the current environment in the database.
def record_environment
return if down?
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
end
def ran?(migration)
@@ -1294,23 +1329,6 @@ module ActiveRecord
end
end
- def self.last_stored_environment
- return nil if current_version == 0
- raise NoEnvironmentInSchemaError unless ActiveRecord::InternalMetadata.table_exists?
-
- environment = ActiveRecord::InternalMetadata[:environment]
- raise NoEnvironmentInSchemaError unless environment
- environment
- end
-
- def self.current_environment
- ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
- end
-
- def self.protected_environment?
- ActiveRecord::Base.protected_environments.include?(last_stored_environment) if last_stored_environment
- end
-
def up?
@direction == :up
end
diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb
index 4538ed6a5f..7b4b59ac4b 100644
--- a/activerecord/lib/active_record/railtie.rb
+++ b/activerecord/lib/active_record/railtie.rb
@@ -91,6 +91,7 @@ module ActiveRecord
if File.file?(filename)
current_version = ActiveRecord::Migrator.current_version
+
next if current_version.nil?
cache = YAML.load(File.read(filename))
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index fce3e1c5cf..2e55713311 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -6,7 +6,7 @@ db_namespace = namespace :db do
desc "Set the environment value for the database"
task "environment:set" => :load_config do
ActiveRecord::InternalMetadata.create_table
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
+ ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Base.connection.migration_context.current_environment
end
task check_protected_environments: :load_config do
@@ -99,9 +99,8 @@ db_namespace = namespace :db do
ActiveRecord::Tasks::DatabaseTasks.check_target_version
- ActiveRecord::Migrator.run(
+ ActiveRecord::Base.connection.migration_context.run(
:up,
- ActiveRecord::Tasks::DatabaseTasks.migrations_paths,
ActiveRecord::Tasks::DatabaseTasks.target_version
)
db_namespace["_dump"].invoke
@@ -113,9 +112,8 @@ db_namespace = namespace :db do
ActiveRecord::Tasks::DatabaseTasks.check_target_version
- ActiveRecord::Migrator.run(
+ ActiveRecord::Base.connection.migration_context.run(
:down,
- ActiveRecord::Tasks::DatabaseTasks.migrations_paths,
ActiveRecord::Tasks::DatabaseTasks.target_version
)
db_namespace["_dump"].invoke
@@ -131,8 +129,7 @@ db_namespace = namespace :db do
puts "\ndatabase: #{ActiveRecord::Base.connection_config[:database]}\n\n"
puts "#{'Status'.center(8)} #{'Migration ID'.ljust(14)} Migration Name"
puts "-" * 50
- paths = ActiveRecord::Tasks::DatabaseTasks.migrations_paths
- ActiveRecord::Migrator.migrations_status(paths).each do |status, version, name|
+ ActiveRecord::Base.connection.migration_context.migrations_status.each do |status, version, name|
puts "#{status.center(8)} #{version.ljust(14)} #{name}"
end
puts
@@ -142,14 +139,14 @@ db_namespace = namespace :db do
desc "Rolls the schema back to the previous version (specify steps w/ STEP=n)."
task rollback: :load_config do
step = ENV["STEP"] ? ENV["STEP"].to_i : 1
- ActiveRecord::Migrator.rollback(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
+ ActiveRecord::Base.connection.migration_context.rollback(step)
db_namespace["_dump"].invoke
end
# desc 'Pushes the schema to the next version (specify steps w/ STEP=n).'
task forward: :load_config do
step = ENV["STEP"] ? ENV["STEP"].to_i : 1
- ActiveRecord::Migrator.forward(ActiveRecord::Tasks::DatabaseTasks.migrations_paths, step)
+ ActiveRecord::Base.connection.migration_context.forward(step)
db_namespace["_dump"].invoke
end
@@ -172,12 +169,12 @@ db_namespace = namespace :db do
desc "Retrieves the current schema version number"
task version: :load_config do
- puts "Current version: #{ActiveRecord::Migrator.current_version}"
+ puts "Current version: #{ActiveRecord::Base.connection.migration_context.current_version}"
end
# desc "Raises an error if there are pending migrations"
task abort_if_pending_migrations: :load_config do
- pending_migrations = ActiveRecord::Migrator.open(ActiveRecord::Tasks::DatabaseTasks.migrations_paths).pending_migrations
+ pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
if pending_migrations.any?
puts "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}"
diff --git a/activerecord/lib/active_record/schema.rb b/activerecord/lib/active_record/schema.rb
index 1e121f2a09..216359867c 100644
--- a/activerecord/lib/active_record/schema.rb
+++ b/activerecord/lib/active_record/schema.rb
@@ -55,7 +55,7 @@ module ActiveRecord
end
ActiveRecord::InternalMetadata.create_table
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
+ ActiveRecord::InternalMetadata[:environment] = connection.migration_context.current_environment
end
private
diff --git a/activerecord/lib/active_record/schema_dumper.rb b/activerecord/lib/active_record/schema_dumper.rb
index 16ccba6b6c..b8d848b999 100644
--- a/activerecord/lib/active_record/schema_dumper.rb
+++ b/activerecord/lib/active_record/schema_dumper.rb
@@ -44,7 +44,7 @@ module ActiveRecord
def initialize(connection, options = {})
@connection = connection
- @version = Migrator::current_version rescue nil
+ @version = connection.migration_context.current_version rescue nil
@options = options
end
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb
index 4657e51e6d..d34fbfd4a9 100644
--- a/activerecord/lib/active_record/tasks/database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/database_tasks.rb
@@ -54,10 +54,10 @@ module ActiveRecord
def check_protected_environments!
unless ENV["DISABLE_DATABASE_ENVIRONMENT_CHECK"]
- current = ActiveRecord::Migrator.current_environment
- stored = ActiveRecord::Migrator.last_stored_environment
+ current = ActiveRecord::Base.connection.migration_context.current_environment
+ stored = ActiveRecord::Base.connection.migration_context.last_stored_environment
- if ActiveRecord::Migrator.protected_environment?
+ if ActiveRecord::Base.connection.migration_context.protected_environment?
raise ActiveRecord::ProtectedEnvironmentError.new(stored)
end
@@ -85,6 +85,10 @@ module ActiveRecord
@migrations_paths ||= Rails.application.paths["db/migrate"].to_a
end
+ def migration_context
+ MigrationContext.new(migrations_paths)
+ end
+
def fixtures_path
@fixtures_path ||= if ENV["FIXTURES_PATH"]
File.join(root, ENV["FIXTURES_PATH"])
@@ -169,7 +173,7 @@ module ActiveRecord
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] != "false" : true
scope = ENV["SCOPE"]
verbose_was, Migration.verbose = Migration.verbose, verbose
- Migrator.migrate(migrations_paths, target_version) do |migration|
+ Base.connection.migration_context.migrate(target_version) do |migration|
scope.blank? || scope == migration.scope
end
ActiveRecord::Base.clear_cache!
diff --git a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
index 62abd694bb..d7d9a2d732 100644
--- a/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
+++ b/activerecord/test/cases/adapters/mysql2/schema_migrations_test.rb
@@ -36,7 +36,7 @@ class SchemaMigrationsTest < ActiveRecord::Mysql2TestCase
assert connection.column_exists?(table_name, :key, :string)
end
ensure
- ActiveRecord::InternalMetadata[:environment] = ActiveRecord::Migrator.current_environment
+ ActiveRecord::InternalMetadata[:environment] = connection.migration_context.current_environment
end
private
diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb
index 83974f327e..140d7cbcae 100644
--- a/activerecord/test/cases/ar_schema_test.rb
+++ b/activerecord/test/cases/ar_schema_test.rb
@@ -48,7 +48,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase
assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" }
assert_nothing_raised { @connection.select_all "SELECT * FROM schema_migrations" }
- assert_equal 7, ActiveRecord::Migrator::current_version
+ assert_equal 7, @connection.migration_context.current_version
end
def test_schema_define_w_table_name_prefix
@@ -64,7 +64,7 @@ class ActiveRecordSchemaTest < ActiveRecord::TestCase
t.column :flavor, :string
end
end
- assert_equal 7, ActiveRecord::Migrator::current_version
+ assert_equal 7, @connection.migration_context.current_version
ensure
ActiveRecord::Base.table_name_prefix = old_table_name_prefix
ActiveRecord::SchemaMigration.table_name = table_name
diff --git a/activerecord/test/cases/migration/pending_migrations_test.rb b/activerecord/test/cases/migration/pending_migrations_test.rb
index d0066f68be..dedb5ea502 100644
--- a/activerecord/test/cases/migration/pending_migrations_test.rb
+++ b/activerecord/test/cases/migration/pending_migrations_test.rb
@@ -4,37 +4,37 @@ require "cases/helper"
module ActiveRecord
class Migration
- class PendingMigrationsTest < ActiveRecord::TestCase
- def setup
- super
- @connection = Minitest::Mock.new
- @app = Minitest::Mock.new
- conn = @connection
- @pending = Class.new(CheckPending) {
- define_method(:connection) { conn }
- }.new(@app)
- @pending.instance_variable_set :@last_check, -1 # Force checking
- end
+ if current_adapter?(:SQLite3Adapter) && !in_memory_db?
+ class PendingMigrationsTest < ActiveRecord::TestCase
+ setup do
+ file = ActiveRecord::Base.connection.raw_connection.filename
+ @conn = ActiveRecord::Base.establish_connection adapter: "sqlite3", database: ":memory:", migrations_paths: MIGRATIONS_ROOT + "/valid"
+ source_db = SQLite3::Database.new file
+ dest_db = ActiveRecord::Base.connection.raw_connection
+ backup = SQLite3::Backup.new(dest_db, "main", source_db, "main")
+ backup.step(-1)
+ backup.finish
+ end
- def teardown
- assert @connection.verify
- assert @app.verify
- super
- end
+ teardown do
+ @conn.release_connection if @conn
+ ActiveRecord::Base.establish_connection :arunit
+ end
+
+ def test_errors_if_pending
+ ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true
- def test_errors_if_pending
- ActiveRecord::Migrator.stub :needs_migration?, true do
- assert_raise ActiveRecord::PendingMigrationError do
- @pending.call(nil)
+ assert_raises ActiveRecord::PendingMigrationError do
+ CheckPending.new(Proc.new {}).call({})
end
end
- end
- def test_checks_if_supported
- @app.expect :call, nil, [:foo]
+ def test_checks_if_supported
+ ActiveRecord::SchemaMigration.create_table
+ migrator = Base.connection.migration_context
+ capture(:stdout) { migrator.migrate }
- ActiveRecord::Migrator.stub :needs_migration?, false do
- @pending.call(:foo)
+ assert_nil CheckPending.new(Proc.new {}).call({})
end
end
end
diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb
index a3ebc8070a..ffcf6a588e 100644
--- a/activerecord/test/cases/migration_test.rb
+++ b/activerecord/test/cases/migration_test.rb
@@ -71,6 +71,16 @@ class MigrationTest < ActiveRecord::TestCase
ActiveRecord::Migration.verbose = @verbose_was
end
+ def test_migrator_migrations_path_is_deprecated
+ assert_deprecated do
+ ActiveRecord::Migrator.migrations_path = "/whatever"
+ end
+ ensure
+ assert_deprecated do
+ ActiveRecord::Migrator.migrations_path = "db/migrate"
+ end
+ end
+
def test_migration_version_matches_component_version
assert_equal ActiveRecord::VERSION::STRING.to_f, ActiveRecord::Migration.current_version
end
@@ -78,20 +88,20 @@ class MigrationTest < ActiveRecord::TestCase
def test_migrator_versions
migrations_path = MIGRATIONS_ROOT + "/valid"
old_path = ActiveRecord::Migrator.migrations_paths
- ActiveRecord::Migrator.migrations_paths = migrations_path
+ migrator = ActiveRecord::MigrationContext.new(migrations_path)
- ActiveRecord::Migrator.up(migrations_path)
- assert_equal 3, ActiveRecord::Migrator.current_version
- assert_equal false, ActiveRecord::Migrator.needs_migration?
+ migrator.up
+ assert_equal 3, migrator.current_version
+ assert_equal false, migrator.needs_migration?
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid")
- assert_equal 0, ActiveRecord::Migrator.current_version
- assert_equal true, ActiveRecord::Migrator.needs_migration?
+ migrator.down
+ assert_equal 0, migrator.current_version
+ assert_equal true, migrator.needs_migration?
ActiveRecord::SchemaMigration.create!(version: 3)
- assert_equal true, ActiveRecord::Migrator.needs_migration?
+ assert_equal true, migrator.needs_migration?
ensure
- ActiveRecord::Migrator.migrations_paths = old_path
+ ActiveRecord::MigrationContext.new(old_path)
end
def test_migration_detection_without_schema_migration_table
@@ -99,28 +109,31 @@ class MigrationTest < ActiveRecord::TestCase
migrations_path = MIGRATIONS_ROOT + "/valid"
old_path = ActiveRecord::Migrator.migrations_paths
- ActiveRecord::Migrator.migrations_paths = migrations_path
+ migrator = ActiveRecord::MigrationContext.new(migrations_path)
- assert_equal true, ActiveRecord::Migrator.needs_migration?
+ assert_equal true, migrator.needs_migration?
ensure
- ActiveRecord::Migrator.migrations_paths = old_path
+ ActiveRecord::MigrationContext.new(old_path)
end
def test_any_migrations
old_path = ActiveRecord::Migrator.migrations_paths
- ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/valid"
+ migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid")
- assert ActiveRecord::Migrator.any_migrations?
+ assert migrator.any_migrations?
- ActiveRecord::Migrator.migrations_paths = MIGRATIONS_ROOT + "/empty"
+ migrator_empty = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/empty")
- assert_not ActiveRecord::Migrator.any_migrations?
+ assert_not migrator_empty.any_migrations?
ensure
- ActiveRecord::Migrator.migrations_paths = old_path
+ ActiveRecord::MigrationContext.new(old_path)
end
def test_migration_version
- assert_nothing_raised { ActiveRecord::Migrator.run(:up, MIGRATIONS_ROOT + "/version_check", 20131219224947) }
+ migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/version_check")
+ assert_equal 0, migrator.current_version
+ migrator.up(20131219224947)
+ assert_equal 20131219224947, migrator.current_version
end
def test_create_table_with_force_true_does_not_drop_nonexisting_table
@@ -219,12 +232,13 @@ class MigrationTest < ActiveRecord::TestCase
assert !Reminder.table_exists?
name_filter = lambda { |migration| migration.name == "ValidPeopleHaveLastNames" }
- ActiveRecord::Migrator.up(MIGRATIONS_ROOT + "/valid", &name_filter)
+ migrator = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid")
+ migrator.up(&name_filter)
assert_column Person, :last_name
assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
- ActiveRecord::Migrator.down(MIGRATIONS_ROOT + "/valid", &name_filter)
+ migrator.down(&name_filter)
assert_no_column Person, :last_name
assert_raise(ActiveRecord::StatementInvalid) { Reminder.first }
@@ -382,9 +396,9 @@ class MigrationTest < ActiveRecord::TestCase
current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
migrations_path = MIGRATIONS_ROOT + "/valid"
old_path = ActiveRecord::Migrator.migrations_paths
- ActiveRecord::Migrator.migrations_paths = migrations_path
+ migrator = ActiveRecord::MigrationContext.new(migrations_path)
- ActiveRecord::Migrator.up(migrations_path)
+ migrator.up
assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
original_rails_env = ENV["RAILS_ENV"]
@@ -395,13 +409,13 @@ class MigrationTest < ActiveRecord::TestCase
refute_equal current_env, new_env
sleep 1 # mysql by default does not store fractional seconds in the database
- ActiveRecord::Migrator.up(migrations_path)
+ migrator.up
assert_equal new_env, ActiveRecord::InternalMetadata[:environment]
ensure
- ActiveRecord::Migrator.migrations_paths = old_path
+ migrator = ActiveRecord::MigrationContext.new(old_path)
ENV["RAILS_ENV"] = original_rails_env
ENV["RACK_ENV"] = original_rack_env
- ActiveRecord::Migrator.up(migrations_path)
+ migrator.up
end
def test_internal_metadata_stores_environment_when_other_data_exists
@@ -411,14 +425,15 @@ class MigrationTest < ActiveRecord::TestCase
current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
migrations_path = MIGRATIONS_ROOT + "/valid"
old_path = ActiveRecord::Migrator.migrations_paths
- ActiveRecord::Migrator.migrations_paths = migrations_path
current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
- ActiveRecord::Migrator.up(migrations_path)
+ migrator = ActiveRecord::MigrationContext.new(migrations_path)
+ migrator.up
assert_equal current_env, ActiveRecord::InternalMetadata[:environment]
assert_equal "bar", ActiveRecord::InternalMetadata[:foo]
ensure
- ActiveRecord::Migrator.migrations_paths = old_path
+ migrator = ActiveRecord::MigrationContext.new(old_path)
+ migrator.up
end
def test_proper_table_name_on_migration
diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb
index 1047ba1367..d674e4506e 100644
--- a/activerecord/test/cases/migrator_test.rb
+++ b/activerecord/test/cases/migrator_test.rb
@@ -89,7 +89,7 @@ class MigratorTest < ActiveRecord::TestCase
end
def test_finds_migrations
- migrations = ActiveRecord::Migrator.migrations(MIGRATIONS_ROOT + "/valid")
+ migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid").migrations
[[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i|
assert_equal migrations[i].version, pair.first
@@ -98,7 +98,8 @@ class MigratorTest < ActiveRecord::TestCase
end
def test_finds_migrations_in_subdirectories
- migrations = ActiveRecord::Migrator.migrations(MIGRATIONS_ROOT + "/valid_with_subdirectories")
+ migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/valid_with_subdirectories").migrations
+
[[1, "ValidPeopleHaveLastNames"], [2, "WeNeedReminders"], [3, "InnocentJointable"]].each_with_index do |pair, i|
assert_equal migrations[i].version, pair.first
@@ -108,7 +109,7 @@ class MigratorTest < ActiveRecord::TestCase
def test_finds_migrations_from_two_directories
directories = [MIGRATIONS_ROOT + "/valid_with_timestamps", MIGRATIONS_ROOT + "/to_copy_with_timestamps"]
- migrations = ActiveRecord::Migrator.migrations directories
+ migrations = ActiveRecord::MigrationContext.new(directories).migrations
[[20090101010101, "PeopleHaveHobbies"],
[20090101010202, "PeopleHaveDescriptions"],
@@ -121,14 +122,14 @@ class MigratorTest < ActiveRecord::TestCase
end
def test_finds_migrations_in_numbered_directory
- migrations = ActiveRecord::Migrator.migrations [MIGRATIONS_ROOT + "/10_urban"]
+ migrations = ActiveRecord::MigrationContext.new(MIGRATIONS_ROOT + "/10_urban").migrations
assert_equal 9, migrations[0].version
assert_equal "AddExpressions", migrations[0].name
end
def test_relative_migrations
list = Dir.chdir(MIGRATIONS_ROOT) do
- ActiveRecord::Migrator.migrations("valid")
+ ActiveRecord::MigrationContext.new("valid").migrations
end
migration_proxy = list.find { |item|
@@ -157,7 +158,7 @@ class MigratorTest < ActiveRecord::TestCase
["up", "002", "We need reminders"],
["down", "003", "Innocent jointable"],
["up", "010", "********** NO FILE **********"],
- ], ActiveRecord::Migrator.migrations_status(path)
+ ], ActiveRecord::MigrationContext.new(path).migrations_status
end
def test_migrations_status_in_subdirectories
@@ -171,24 +172,20 @@ class MigratorTest < ActiveRecord::TestCase
["up", "002", "We need reminders"],
["down", "003", "Innocent jointable"],
["up", "010", "********** NO FILE **********"],
- ], ActiveRecord::Migrator.migrations_status(path)
+ ], ActiveRecord::MigrationContext.new(path).migrations_status
end
def test_migrations_status_with_schema_define_in_subdirectories
- path = MIGRATIONS_ROOT + "/valid_with_subdirectories"
- prev_paths = ActiveRecord::Migrator.migrations_paths
- ActiveRecord::Migrator.migrations_paths = path
+ _, migrator = migrator_class(3)
+ migrator = migrator.new("valid_with_subdirectories")
- ActiveRecord::Schema.define(version: 3) do
- end
+ migrator.migrate
assert_equal [
- ["up", "001", "Valid people have last names"],
- ["up", "002", "We need reminders"],
- ["up", "003", "Innocent jointable"],
- ], ActiveRecord::Migrator.migrations_status(path)
- ensure
- ActiveRecord::Migrator.migrations_paths = prev_paths
+ ["up", "001", "********** NO FILE **********"],
+ ["up", "002", "********** NO FILE **********"],
+ ["up", "003", "********** NO FILE **********"],
+ ], migrator.migrations_status
end
def test_migrations_status_from_two_directories
@@ -204,7 +201,7 @@ class MigratorTest < ActiveRecord::TestCase
["down", "20100201010101", "Valid with timestamps we need reminders"],
["down", "20100301010101", "Valid with timestamps innocent jointable"],
["up", "20160528010101", "********** NO FILE **********"],
- ], ActiveRecord::Migrator.migrations_status(paths)
+ ], ActiveRecord::MigrationContext.new(paths).migrations_status
end
def test_migrator_interleaved_migrations
@@ -232,25 +229,28 @@ class MigratorTest < ActiveRecord::TestCase
def test_up_calls_up
migrations = [Sensor.new(nil, 0), Sensor.new(nil, 1), Sensor.new(nil, 2)]
- ActiveRecord::Migrator.new(:up, migrations).migrate
+ migrator = ActiveRecord::Migrator.new(:up, migrations)
+ migrator.migrate
assert migrations.all?(&:went_up)
assert migrations.all? { |m| !m.went_down }
- assert_equal 2, ActiveRecord::Migrator.current_version
+ assert_equal 2, migrator.current_version
end
def test_down_calls_down
test_up_calls_up
migrations = [Sensor.new(nil, 0), Sensor.new(nil, 1), Sensor.new(nil, 2)]
- ActiveRecord::Migrator.new(:down, migrations).migrate
+ migrator = ActiveRecord::Migrator.new(:down, migrations)
+ migrator.migrate
assert migrations.all? { |m| !m.went_up }
assert migrations.all?(&:went_down)
- assert_equal 0, ActiveRecord::Migrator.current_version
+ assert_equal 0, migrator.current_version
end
def test_current_version
ActiveRecord::SchemaMigration.create!(version: "1000")
- assert_equal 1000, ActiveRecord::Migrator.current_version
+ migrator = ActiveRecord::MigrationContext.new("db/migrate")
+ assert_equal 1000, migrator.current_version
end
def test_migrator_one_up
@@ -289,33 +289,36 @@ class MigratorTest < ActiveRecord::TestCase
def test_migrator_double_up
calls, migrations = sensors(3)
- assert_equal(0, ActiveRecord::Migrator.current_version)
+ migrator = ActiveRecord::Migrator.new(:up, migrations, 1)
+ assert_equal(0, migrator.current_version)
- ActiveRecord::Migrator.new(:up, migrations, 1).migrate
+ migrator.migrate
assert_equal [[:up, 1]], calls
calls.clear
- ActiveRecord::Migrator.new(:up, migrations, 1).migrate
+ migrator.migrate
assert_equal [], calls
end
def test_migrator_double_down
calls, migrations = sensors(3)
+ migrator = ActiveRecord::Migrator.new(:up, migrations, 1)
- assert_equal(0, ActiveRecord::Migrator.current_version)
+ assert_equal 0, migrator.current_version
- ActiveRecord::Migrator.new(:up, migrations, 1).run
+ migrator.run
assert_equal [[:up, 1]], calls
calls.clear
- ActiveRecord::Migrator.new(:down, migrations, 1).run
+ migrator = ActiveRecord::Migrator.new(:down, migrations, 1)
+ migrator.run
assert_equal [[:down, 1]], calls
calls.clear
- ActiveRecord::Migrator.new(:down, migrations, 1).run
+ migrator.run
assert_equal [], calls
- assert_equal(0, ActiveRecord::Migrator.current_version)
+ assert_equal 0, migrator.current_version
end
def test_migrator_verbosity
@@ -361,78 +364,85 @@ class MigratorTest < ActiveRecord::TestCase
def test_migrator_going_down_due_to_version_target
calls, migrator = migrator_class(3)
+ migrator = migrator.new("valid")
- migrator.up("valid", 1)
+ migrator.up(1)
assert_equal [[:up, 1]], calls
calls.clear
- migrator.migrate("valid", 0)
+ migrator.migrate(0)
assert_equal [[:down, 1]], calls
calls.clear
- migrator.migrate("valid")
+ migrator.migrate
assert_equal [[:up, 1], [:up, 2], [:up, 3]], calls
end
def test_migrator_output_when_running_multiple_migrations
_, migrator = migrator_class(3)
+ migrator = migrator.new("valid")
- result = migrator.migrate("valid")
+ result = migrator.migrate
assert_equal(3, result.count)
# Nothing migrated from duplicate run
- result = migrator.migrate("valid")
+ result = migrator.migrate
assert_equal(0, result.count)
- result = migrator.rollback("valid")
+ result = migrator.rollback
assert_equal(1, result.count)
end
def test_migrator_output_when_running_single_migration
_, migrator = migrator_class(1)
- result = migrator.run(:up, "valid", 1)
+ migrator = migrator.new("valid")
+
+ result = migrator.run(:up, 1)
assert_equal(1, result.version)
end
def test_migrator_rollback
_, migrator = migrator_class(3)
+ migrator = migrator.new("valid")
- migrator.migrate("valid")
- assert_equal(3, ActiveRecord::Migrator.current_version)
+ migrator.migrate
+ assert_equal(3, migrator.current_version)
- migrator.rollback("valid")
- assert_equal(2, ActiveRecord::Migrator.current_version)
+ migrator.rollback
+ assert_equal(2, migrator.current_version)
- migrator.rollback("valid")
- assert_equal(1, ActiveRecord::Migrator.current_version)
+ migrator.rollback
+ assert_equal(1, migrator.current_version)
- migrator.rollback("valid")
- assert_equal(0, ActiveRecord::Migrator.current_version)
+ migrator.rollback
+ assert_equal(0, migrator.current_version)
- migrator.rollback("valid")
- assert_equal(0, ActiveRecord::Migrator.current_version)
+ migrator.rollback
+ assert_equal(0, migrator.current_version)
end
def test_migrator_db_has_no_schema_migrations_table
_, migrator = migrator_class(3)
+ migrator = migrator.new("valid")
ActiveRecord::Base.connection.drop_table "schema_migrations", if_exists: true
assert_not ActiveRecord::Base.connection.table_exists?("schema_migrations")
- migrator.migrate("valid", 1)
+ migrator.migrate(1)
assert ActiveRecord::Base.connection.table_exists?("schema_migrations")
end
def test_migrator_forward
_, migrator = migrator_class(3)
- migrator.migrate("/valid", 1)
- assert_equal(1, ActiveRecord::Migrator.current_version)
+ migrator = migrator.new("/valid")
+ migrator.migrate(1)
+ assert_equal(1, migrator.current_version)
- migrator.forward("/valid", 2)
- assert_equal(3, ActiveRecord::Migrator.current_version)
+ migrator.forward(2)
+ assert_equal(3, migrator.current_version)
- migrator.forward("/valid")
- assert_equal(3, ActiveRecord::Migrator.current_version)
+ migrator.forward
+ assert_equal(3, migrator.current_version)
end
def test_only_loads_pending_migrations
@@ -440,25 +450,27 @@ class MigratorTest < ActiveRecord::TestCase
ActiveRecord::SchemaMigration.create!(version: "1")
calls, migrator = migrator_class(3)
- migrator.migrate("valid", nil)
+ migrator = migrator.new("valid")
+ migrator.migrate
assert_equal [[:up, 2], [:up, 3]], calls
end
def test_get_all_versions
_, migrator = migrator_class(3)
+ migrator = migrator.new("valid")
- migrator.migrate("valid")
- assert_equal([1, 2, 3], ActiveRecord::Migrator.get_all_versions)
+ migrator.migrate
+ assert_equal([1, 2, 3], migrator.get_all_versions)
- migrator.rollback("valid")
- assert_equal([1, 2], ActiveRecord::Migrator.get_all_versions)
+ migrator.rollback
+ assert_equal([1, 2], migrator.get_all_versions)
- migrator.rollback("valid")
- assert_equal([1], ActiveRecord::Migrator.get_all_versions)
+ migrator.rollback
+ assert_equal([1], migrator.get_all_versions)
- migrator.rollback("valid")
- assert_equal([], ActiveRecord::Migrator.get_all_versions)
+ migrator.rollback
+ assert_equal([], migrator.get_all_versions)
end
private
@@ -483,11 +495,11 @@ class MigratorTest < ActiveRecord::TestCase
def migrator_class(count)
calls, migrations = sensors(count)
- migrator = Class.new(ActiveRecord::Migrator).extend(Module.new {
- define_method(:migrations) { |paths|
+ migrator = Class.new(ActiveRecord::MigrationContext) {
+ define_method(:migrations) { |*|
migrations
}
- })
+ }
[calls, migrator]
end
end
diff --git a/activerecord/test/cases/tasks/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb
index c114842dec..21226352ff 100644
--- a/activerecord/test/cases/tasks/database_tasks_test.rb
+++ b/activerecord/test/cases/tasks/database_tasks_test.rb
@@ -28,10 +28,10 @@ module ActiveRecord
class DatabaseTasksUtilsTask < ActiveRecord::TestCase
def test_raises_an_error_when_called_with_protected_environment
- ActiveRecord::Migrator.stubs(:current_version).returns(1)
+ ActiveRecord::MigrationContext.any_instance.stubs(:current_version).returns(1)
protected_environments = ActiveRecord::Base.protected_environments
- current_env = ActiveRecord::Migrator.current_environment
+ current_env = ActiveRecord::Base.connection.migration_context.current_environment
assert_not_includes protected_environments, current_env
# Assert no error
ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
@@ -45,10 +45,10 @@ module ActiveRecord
end
def test_raises_an_error_when_called_with_protected_environment_which_name_is_a_symbol
- ActiveRecord::Migrator.stubs(:current_version).returns(1)
+ ActiveRecord::MigrationContext.any_instance.stubs(:current_version).returns(1)
protected_environments = ActiveRecord::Base.protected_environments
- current_env = ActiveRecord::Migrator.current_environment
+ current_env = ActiveRecord::Base.connection.migration_context.current_environment
assert_not_includes protected_environments, current_env
# Assert no error
ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
@@ -63,7 +63,7 @@ module ActiveRecord
def test_raises_an_error_if_no_migrations_have_been_made
ActiveRecord::InternalMetadata.stubs(:table_exists?).returns(false)
- ActiveRecord::Migrator.stubs(:current_version).returns(1)
+ ActiveRecord::MigrationContext.any_instance.stubs(:current_version).returns(1)
assert_raise(ActiveRecord::NoEnvironmentInSchemaError) do
ActiveRecord::Tasks::DatabaseTasks.check_protected_environments!
@@ -347,50 +347,92 @@ module ActiveRecord
end
end
- class DatabaseTasksMigrateTest < ActiveRecord::TestCase
- self.use_transactional_tests = false
+ if current_adapter?(:SQLite3Adapter) && !in_memory_db?
+ class DatabaseTasksMigrateTest < ActiveRecord::TestCase
+ self.use_transactional_tests = false
+
+ # Use a memory db here to avoid having to rollback at the end
+ setup do
+ migrations_path = MIGRATIONS_ROOT + "/valid"
+ file = ActiveRecord::Base.connection.raw_connection.filename
+ @conn = ActiveRecord::Base.establish_connection adapter: "sqlite3",
+ database: ":memory:", migrations_paths: migrations_path
+ source_db = SQLite3::Database.new file
+ dest_db = ActiveRecord::Base.connection.raw_connection
+ backup = SQLite3::Backup.new(dest_db, "main", source_db, "main")
+ backup.step(-1)
+ backup.finish
+ end
- def setup
- ActiveRecord::Tasks::DatabaseTasks.migrations_paths = "custom/path"
- end
+ teardown do
+ @conn.release_connection if @conn
+ ActiveRecord::Base.establish_connection :arunit
+ end
- def teardown
- ActiveRecord::Tasks::DatabaseTasks.migrations_paths = nil
- end
+ def test_migrate_set_and_unset_verbose_and_version_env_vars
+ verbose, version = ENV["VERBOSE"], ENV["VERSION"]
+ ENV["VERSION"] = "2"
+ ENV["VERBOSE"] = "false"
- def test_migrate_receives_correct_env_vars
- verbose, version = ENV["VERBOSE"], ENV["VERSION"]
+ # run down migration because it was already run on copied db
+ assert_empty capture_migration_output
- ENV["VERBOSE"] = "false"
- ENV["VERSION"] = "4"
- ActiveRecord::Migrator.expects(:migrate).with("custom/path", 4)
- ActiveRecord::Migration.expects(:verbose=).with(false)
- ActiveRecord::Migration.expects(:verbose=).with(ActiveRecord::Migration.verbose)
- ActiveRecord::Tasks::DatabaseTasks.migrate
+ ENV.delete("VERSION")
+ ENV.delete("VERBOSE")
- ENV.delete("VERBOSE")
- ENV.delete("VERSION")
- ActiveRecord::Migrator.expects(:migrate).with("custom/path", nil)
- ActiveRecord::Migration.expects(:verbose=).with(true)
- ActiveRecord::Migration.expects(:verbose=).with(ActiveRecord::Migration.verbose)
- ActiveRecord::Tasks::DatabaseTasks.migrate
+ # re-run up migration
+ assert_includes capture_migration_output, "migrating"
+ ensure
+ ENV["VERBOSE"], ENV["VERSION"] = verbose, version
+ end
- ENV["VERBOSE"] = ""
- ENV["VERSION"] = ""
- ActiveRecord::Migrator.expects(:migrate).with("custom/path", nil)
- ActiveRecord::Migration.expects(:verbose=).with(true)
- ActiveRecord::Migration.expects(:verbose=).with(ActiveRecord::Migration.verbose)
- ActiveRecord::Tasks::DatabaseTasks.migrate
+ def test_migrate_set_and_unset_empty_values_for_verbose_and_version_env_vars
+ verbose, version = ENV["VERBOSE"], ENV["VERSION"]
- ENV["VERBOSE"] = "yes"
- ENV["VERSION"] = "0"
- ActiveRecord::Migrator.expects(:migrate).with("custom/path", 0)
- ActiveRecord::Migration.expects(:verbose=).with(true)
- ActiveRecord::Migration.expects(:verbose=).with(ActiveRecord::Migration.verbose)
- ActiveRecord::Tasks::DatabaseTasks.migrate
- ensure
- ENV["VERBOSE"], ENV["VERSION"] = verbose, version
+ ENV["VERSION"] = "2"
+ ENV["VERBOSE"] = "false"
+
+ # run down migration because it was already run on copied db
+ assert_empty capture_migration_output
+
+ ENV["VERBOSE"] = ""
+ ENV["VERSION"] = ""
+
+ # re-run up migration
+ assert_includes capture_migration_output, "migrating"
+ ensure
+ ENV["VERBOSE"], ENV["VERSION"] = verbose, version
+ end
+
+ def test_migrate_set_and_unset_nonsense_values_for_verbose_and_version_env_vars
+ verbose, version = ENV["VERBOSE"], ENV["VERSION"]
+
+ # run down migration because it was already run on copied db
+ ENV["VERSION"] = "2"
+ ENV["VERBOSE"] = "false"
+
+ assert_empty capture_migration_output
+
+ ENV["VERBOSE"] = "yes"
+ ENV["VERSION"] = "2"
+
+ # run no migration because 2 was already run
+ assert_empty capture_migration_output
+ ensure
+ ENV["VERBOSE"], ENV["VERSION"] = verbose, version
+ end
+
+ private
+ def capture_migration_output
+ capture(:stdout) do
+ ActiveRecord::Tasks::DatabaseTasks.migrate
+ end
+ end
end
+ end
+
+ class DatabaseTasksMigrateErrorTest < ActiveRecord::TestCase
+ self.use_transactional_tests = false
def test_migrate_raise_error_on_invalid_version_format
version = ENV["VERSION"]
diff --git a/activestorage/test/database/setup.rb b/activestorage/test/database/setup.rb
index 705650a25d..daeeb5695b 100644
--- a/activestorage/test/database/setup.rb
+++ b/activestorage/test/database/setup.rb
@@ -3,5 +3,5 @@
require_relative "create_users_migration"
ActiveRecord::Base.establish_connection(adapter: "sqlite3", database: ":memory:")
-ActiveRecord::Migrator.migrate File.expand_path("../../db/migrate", __dir__)
+ActiveRecord::Base.connection.migration_context.migrate
ActiveStorageCreateUsers.migrate(:up)
diff --git a/railties/lib/rails/info.rb b/railties/lib/rails/info.rb
index d8f361f524..d5c9973c6b 100644
--- a/railties/lib/rails/info.rb
+++ b/railties/lib/rails/info.rb
@@ -99,7 +99,7 @@ module Rails
end
property "Database schema version" do
- ActiveRecord::Migrator.current_version rescue nil
+ ActiveRecord::Base.connection.migration_context.current_version rescue nil
end
end
end
diff --git a/railties/test/application/rake/migrations_test.rb b/railties/test/application/rake/migrations_test.rb
index 788f9160d6..1b45e0645c 100644
--- a/railties/test/application/rake/migrations_test.rb
+++ b/railties/test/application/rake/migrations_test.rb
@@ -37,6 +37,18 @@ module ApplicationTests
assert_match(/AMigration: reverted/, output)
end
+ test "version outputs current version" do
+ app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
+ class OneMigration < ActiveRecord::Migration::Current
+ end
+ MIGRATION
+
+ rails "db:migrate"
+
+ output = rails("db:version")
+ assert_match(/Current version: 1/, output)
+ end
+
test "migrate with specified VERSION in different formats" do
app_file "db/migrate/01_one_migration.rb", <<-MIGRATION
class OneMigration < ActiveRecord::Migration::Current
diff --git a/railties/test/railties/engine_test.rb b/railties/test/railties/engine_test.rb
index 339a56c34f..a59c63f343 100644
--- a/railties/test/railties/engine_test.rb
+++ b/railties/test/railties/engine_test.rb
@@ -34,7 +34,7 @@ module RailtiesTest
def migrations
migration_root = File.expand_path(ActiveRecord::Migrator.migrations_paths.first, app_path)
- ActiveRecord::Migrator.migrations(migration_root)
+ ActiveRecord::MigrationContext.new(migration_root).migrations
end
test "serving sprocket's assets" do