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.
上级 1c24f015
* 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.
......
......@@ -65,6 +65,10 @@ def migrations_paths
def for_current_env?
env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
end
def schema_cache_path
raise NotImplementedError
end
end
end
end
......@@ -87,6 +87,13 @@ def idle_timeout
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
......@@ -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
......
......@@ -409,14 +409,14 @@ def dump_filename(namespace, format = ActiveRecord::Base.schema_format)
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 @@ def dump_schema_cache(conn, filename)
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)
......
......@@ -208,12 +208,78 @@ class DatabaseTasksCreateTest < ActiveRecord::TestCase
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
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册