Skip to content

Commit

Permalink
Merge pull request #36870 from jhawthorn/schema_sha
Browse files Browse the repository at this point in the history
Sync test DB from schema using its SHA1
  • Loading branch information
jhawthorn committed Aug 6, 2019
2 parents d1c2ba6 + ba093a5 commit 6bc8835
Show file tree
Hide file tree
Showing 3 changed files with 25 additions and 13 deletions.
14 changes: 9 additions & 5 deletions activerecord/lib/active_record/migration.rb
Expand Up @@ -587,18 +587,22 @@ def check_pending!(connection = Base.connection)
end

def load_schema_if_pending!
if Base.connection.migration_context.needs_migration? || !Base.connection.migration_context.any_migrations?
current_config = Base.connection_config
all_configs = ActiveRecord::Base.configurations.configs_for(env_name: Rails.env)

unless all_configs.all? { |config| Tasks::DatabaseTasks.schema_up_to_date?(config.config) }
# Roundtrip to Rake to allow plugins to hook into database initialization.
root = defined?(ENGINE_ROOT) ? ENGINE_ROOT : Rails.root
FileUtils.cd(root) do
current_config = Base.connection_config
Base.clear_all_connections!
system("bin/rails db:test:prepare")
# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
Base.establish_connection(current_config)
end
check_pending!
end

# Establish a new connection, the old database may be gone (db:test:prepare uses purge)
Base.establish_connection(current_config)

check_pending!
end

def maintain_test_schema! #:nodoc:
Expand Down
15 changes: 15 additions & 0 deletions activerecord/lib/active_record/tasks/database_tasks.rb
Expand Up @@ -332,10 +332,21 @@ def load_schema(configuration, format = ActiveRecord::Base.schema_format, file =
end
ActiveRecord::InternalMetadata.create_table
ActiveRecord::InternalMetadata[:environment] = environment
ActiveRecord::InternalMetadata[:schema_sha1] = schema_sha1(file)
ensure
Migration.verbose = verbose_was
end

def schema_up_to_date?(configuration, format = ActiveRecord::Base.schema_format, file = nil, environment = env, spec_name = "primary")
file ||= dump_filename(spec_name, format)

return true unless File.exist?(file)

ActiveRecord::Base.establish_connection(configuration)
return false unless ActiveRecord::InternalMetadata.table_exists?
ActiveRecord::InternalMetadata[:schema_sha1] == schema_sha1(file)
end

def dump_schema(configuration, format = ActiveRecord::Base.schema_format, spec_name = "primary") # :nodoc:
require "active_record/schema_dumper"
filename = dump_filename(spec_name, format)
Expand Down Expand Up @@ -467,6 +478,10 @@ def each_local_configuration
def local_database?(configuration)
configuration["host"].blank? || LOCAL_HOSTS.include?(configuration["host"])
end

def schema_sha1(file)
Digest::SHA1.hexdigest(File.read(file))
end
end
end
end
9 changes: 1 addition & 8 deletions railties/test/application/test_test.rb
Expand Up @@ -232,10 +232,7 @@ class UserTest < ActiveSupport::TestCase
assert_successful_test_run("models/user_test.rb")
end

# TODO: would be nice if we could detect the schema change automatically.
# For now, the user has to synchronize the schema manually.
# This test case serves as a reminder for this use case.
test "manually synchronize test schema after rollback" do
test "automatically synchronizes test schema after rollback" do
output = rails("generate", "model", "user", "name:string")
version = output.match(/(\d+)_create_users\.rb/)[1]

Expand Down Expand Up @@ -268,10 +265,6 @@ class UserTest < ActiveSupport::TestCase
end
RUBY

assert_successful_test_run "models/user_test.rb"

rails "db:test:prepare"

assert_unsuccessful_run "models/user_test.rb", <<-ASSERTION
Expected: ["id", "name"]
Actual: ["id", "name", "age"]
Expand Down

0 comments on commit 6bc8835

Please sign in to comment.