1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Allow schema cache path to be defined in the config file

This updates the database tasks for dumping the Active Record schema cache as
well as clearing the schema cache file, allowing the path to be defined in the
database configuration YAML file.

As before, the value can also be defined in an ENV variable, though this would
not work for a multi-db application. If the value is specified neither in the
DB config, nor in the ENV, then the path will continue to be derived from the
DB config spec_name.

Note that in order to make this change cleaner I also moved a bit of logic
out of a rake task and into the DatabaseTasks class, for symmetry.

We have two rake tasks for the schema cache:

    $ rake db:schema:cache:dump
    $ rake db:schema:cache:clear

The cache:dump task was implemented in DatabaseTasks, but the
cache:clear one was not.

I also added some tests for the behavior that I was changing, since some of
the code paths weren't tested.
This commit is contained in:
Katrina Owen 2020-01-21 11:34:20 -07:00
parent 1c24f01596
commit 2c2ff8228e
No known key found for this signature in database
GPG key ID: A2C5A7CA5A4A075C
6 changed files with 112 additions and 9 deletions

View file

@ -1,3 +1,17 @@
* Allow schema cache path to be defined in the database configuration file.
For example:
```
development:
adapter: postgresql
database: blog_development
pool: 5
schema_cache_path: tmp/schema/main.yml
```
*Katrina Owen*
* Deprecate `#remove_connection` in favor of `#remove_connection_pool` when called on the handler.
`#remove_connection` is deprecated in order to support returning a `DatabaseConfig` object instead of a `Hash`. Use `#remove_connection_pool`, `#remove_connection` will be removed in 6.2.

View file

@ -65,6 +65,10 @@ module ActiveRecord
def for_current_env?
env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
end
def schema_cache_path
raise NotImplementedError
end
end
end
end

View file

@ -87,6 +87,13 @@ module ActiveRecord
def adapter
configuration_hash[:adapter]
end
# The path to the schema cache dump file for a database.
# If omitted, the filename will be read from ENV or a
# default will be derived.
def schema_cache_path
configuration_hash[:schema_cache_path]
end
end
end
end

View file

@ -407,7 +407,10 @@ db_namespace = namespace :db do
task dump: :load_config do
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
ActiveRecord::Base.establish_connection(db_config)
filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
db_config.spec_name,
schema_cache_path: db_config.schema_cache_path,
)
ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(
ActiveRecord::Base.connection,
filename,
@ -418,8 +421,13 @@ db_namespace = namespace :db do
desc "Clears a db/schema_cache.yml file."
task clear: :load_config do
ActiveRecord::Base.configurations.configs_for(env_name: ActiveRecord::Tasks::DatabaseTasks.env).each do |db_config|
filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(db_config.spec_name)
rm_f filename, verbose: false
filename = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename(
db_config.spec_name,
schema_cache_path: db_config.schema_cache_path,
)
ActiveRecord::Tasks::DatabaseTasks.clear_schema_cache(
filename,
)
end
end
end

View file

@ -409,14 +409,14 @@ module ActiveRecord
ENV["SCHEMA"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
end
def cache_dump_filename(namespace)
def cache_dump_filename(namespace, schema_cache_path: nil)
filename = if namespace == "primary"
"schema_cache.yml"
else
"#{namespace}_schema_cache.yml"
end
ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
schema_cache_path || ENV["SCHEMA_CACHE"] || File.join(ActiveRecord::Tasks::DatabaseTasks.db_dir, filename)
end
def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
@ -454,6 +454,10 @@ module ActiveRecord
open(filename, "wb") { |f| f.write(YAML.dump(conn.schema_cache)) }
end
def clear_schema_cache(filename)
FileUtils.rm_f filename, verbose: false
end
private
def resolve_configuration(configuration)
Base.configurations.resolve(configuration)

View file

@ -208,12 +208,78 @@ module ActiveRecord
class DatabaseTasksDumpSchemaCacheTest < ActiveRecord::TestCase
def test_dump_schema_cache
path = "/tmp/my_schema_cache.yml"
ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, path)
assert File.file?(path)
Dir.mktmpdir do |dir|
ActiveRecord::Tasks::DatabaseTasks.stub(:db_dir, dir) do
path = File.join(dir, "schema_cache.yml")
assert_not File.file?(path)
ActiveRecord::Tasks::DatabaseTasks.dump_schema_cache(ActiveRecord::Base.connection, path)
assert File.file?(path)
end
end
ensure
ActiveRecord::Base.clear_cache!
FileUtils.rm_rf(path)
end
def test_clear_schema_cache
Dir.mktmpdir do |dir|
ActiveRecord::Tasks::DatabaseTasks.stub(:db_dir, dir) do
path = File.join(dir, "schema_cache.yml")
File.open(path, "wb") do |f|
f.puts "This is a cache."
end
assert File.file?(path)
ActiveRecord::Tasks::DatabaseTasks.clear_schema_cache(path)
assert_not File.file?(path)
end
end
end
def test_cache_dump_default_filename
old_path = ENV["SCHEMA_CACHE"]
ENV.delete("SCHEMA_CACHE")
ActiveRecord::Tasks::DatabaseTasks.stub(:db_dir, "db") do
path = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename("primary")
assert_equal "db/schema_cache.yml", path
end
ensure
ENV["SCHEMA_CACHE"] = old_path
end
def test_cache_dump_alternate_filename
old_path = ENV["SCHEMA_CACHE"]
ENV.delete("SCHEMA_CACHE")
ActiveRecord::Tasks::DatabaseTasks.stub(:db_dir, "db") do
path = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename("alternate")
assert_equal "db/alternate_schema_cache.yml", path
end
ensure
ENV["SCHEMA_CACHE"] = old_path
end
def test_cache_dump_filename_with_env_override
old_path = ENV["SCHEMA_CACHE"]
ENV["SCHEMA_CACHE"] = "tmp/something.yml"
ActiveRecord::Tasks::DatabaseTasks.stub(:db_dir, "db") do
path = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename("primary")
assert_equal "tmp/something.yml", path
end
ensure
ENV["SCHEMA_CACHE"] = old_path
end
def test_cache_dump_filename_with_path_from_db_config
old_path = ENV["SCHEMA_CACHE"]
ENV.delete("SCHEMA_CACHE")
ActiveRecord::Tasks::DatabaseTasks.stub(:db_dir, "db") do
path = ActiveRecord::Tasks::DatabaseTasks.cache_dump_filename("primary", schema_cache_path: "tmp/something.yml")
assert_equal "tmp/something.yml", path
end
ensure
ENV["SCHEMA_CACHE"] = old_path
end
end