Skip to content

Commit cdd4170

Browse files
authored
Merge pull request rails#46399 from eileencodes/fix-pending-migrations-error-message
Fix pending migrations error message
2 parents 8069d7f + e9d835f commit cdd4170

File tree

2 files changed

+41
-28
lines changed

2 files changed

+41
-28
lines changed

activerecord/lib/active_record/migration.rb

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -143,18 +143,20 @@ class PendingMigrationError < MigrationError # :nodoc:
143143
end
144144
end
145145

146-
def initialize(message = nil)
147-
super(message || detailed_migration_message)
146+
def initialize(message = nil, pending_migrations: nil)
147+
if pending_migrations.nil?
148+
pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
149+
end
150+
151+
super(message || detailed_migration_message(pending_migrations))
148152
end
149153

150154
private
151-
def detailed_migration_message
155+
def detailed_migration_message(pending_migrations)
152156
message = "Migrations are pending. To resolve this issue, run:\n\n bin/rails db:migrate"
153157
message += " RAILS_ENV=#{::Rails.env}" if defined?(Rails.env) && !(Rails.env.development? || Rails.env.test?)
154158
message += "\n\n"
155159

156-
pending_migrations = ActiveRecord::Base.connection.migration_context.open.pending_migrations
157-
158160
message += "You have #{pending_migrations.size} pending #{pending_migrations.size > 1 ? 'migrations:' : 'migration:'}\n\n"
159161

160162
pending_migrations.each do |pending_migration|
@@ -634,7 +636,9 @@ def nearest_delegate # :nodoc:
634636

635637
# Raises <tt>ActiveRecord::PendingMigrationError</tt> error if any migrations are pending.
636638
def check_pending!(connection = Base.connection)
637-
raise ActiveRecord::PendingMigrationError if connection.migration_context.needs_migration?
639+
if pending_migrations = connection.migration_context.pending_migrations
640+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: pending_migrations)
641+
end
638642
end
639643

640644
def load_schema_if_pending!
@@ -678,17 +682,28 @@ def disable_ddl_transaction!
678682
end
679683

680684
def check_pending_migrations # :nodoc:
681-
prev_db_config = Base.connection_db_config
682-
683-
db_configs_in_current_env.each do |db_config|
684-
Base.establish_connection(db_config)
685-
check_pending!
685+
if pending_migrations.any?
686+
raise ActiveRecord::PendingMigrationError.new(pending_migrations: pending_migrations)
686687
end
687-
ensure
688-
Base.establish_connection(prev_db_config)
689688
end
690689

691690
private
691+
def pending_migrations
692+
prev_db_config = Base.connection_db_config
693+
pending_migrations = []
694+
695+
db_configs_in_current_env.each do |db_config|
696+
conn = Base.establish_connection(db_config).connection
697+
if pending = conn.migration_context.open.pending_migrations
698+
pending_migrations << pending
699+
end
700+
end
701+
702+
pending_migrations.flatten
703+
ensure
704+
Base.establish_connection(prev_db_config)
705+
end
706+
692707
def db_configs_in_current_env
693708
current_environment = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
694709
ActiveRecord::Base.configurations.configs_for(env_name: current_environment)

activerecord/test/cases/migration/pending_migrations_test.rb

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class #{name.classify} < ActiveRecord::Migration::Current
4141

4242
def test_errors_if_pending
4343
create_migration "01", "create_foo"
44-
assert_pending_migrations
44+
assert_pending_migrations("01_create_foo.rb")
4545
end
4646

4747
def test_checks_if_supported
@@ -62,26 +62,21 @@ def test_understands_migrations_created_out_of_order
6262

6363
# It understands the new migration created at 01
6464
create_migration "01", "create_foo"
65-
assert_pending_migrations
65+
assert_pending_migrations("01_create_foo.rb")
6666
end
6767

6868
def test_with_multiple_database
69-
create_migration "01", "create_bar", database: :secondary
70-
assert_pending_migrations
69+
create_migration "01", "create_bar", database: :primary
70+
create_migration "02", "create_foo", database: :secondary
71+
assert_pending_migrations("01_create_bar.rb", "02_create_foo.rb")
7172

7273
ActiveRecord::Base.establish_connection(:secondary)
7374
quietly { run_migrations }
7475

7576
ActiveRecord::Base.establish_connection(:primary)
77+
quietly { run_migrations }
7678

7779
assert_no_pending_migrations
78-
79-
# Now check exclusion if database_tasks is set to false for the db_config
80-
create_migration "02", "create_foo", database: :secondary
81-
assert_pending_migrations
82-
83-
ActiveRecord::Base.configurations = base_config(secondary: { database_tasks: false })
84-
assert_no_pending_migrations
8580
end
8681

8782
def test_with_stdlib_logger
@@ -92,20 +87,23 @@ def test_with_stdlib_logger
9287
end
9388

9489
private
95-
def assert_pending_migrations
96-
# Do twice to test that the error continues to be raised.
90+
def assert_pending_migrations(*expected_migrations)
9791
2.times do
98-
assert_raises ActiveRecord::PendingMigrationError do
92+
error = assert_raises ActiveRecord::PendingMigrationError do
9993
CheckPending.new(proc { flunk }).call({})
10094
end
95+
96+
assert_includes error.message, "Migrations are pending."
97+
expected_migrations.each do |migration|
98+
assert_includes error.message, migration
99+
end
101100
end
102101
end
103102

104103
def assert_no_pending_migrations
105104
app = Minitest::Mock.new
106105
check_pending = CheckPending.new(app)
107106

108-
# Do twice to also test the cached result.
109107
2.times do
110108
app.expect :call, nil, [{}]
111109
check_pending.call({})

0 commit comments

Comments
 (0)