Support hash config for `structure_dump_flags` and `structure_load_flags` flags

Now that Active Record supports multiple databases configuration
    we need a way to pass specific flags for dump/load databases since
    the options are not the same for different adapters.
    We can use in the original way:
    ```ruby
    ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table']
    #or
    ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
    ```
    And also use it passing a hash, with one or more keys, where the key
    is the adapter
    ```ruby
    ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
      mysql2: ['--no-defaults', '--skip-add-drop-table'],
      postgres: '--no-tablespaces'
    }
    ```
This commit is contained in:
Gustavo Gonzalez 2021-01-21 21:32:55 -05:00
parent aec71e84d8
commit 62aec5146b
4 changed files with 137 additions and 2 deletions

View File

@ -1,3 +1,27 @@
* Support hash config for `structure_dump_flags` and `structure_load_flags` flags
Now that Active Record supports multiple databases configuration
we need a way to pass specific flags for dump/load databases since
the options are not the same for different adapters.
We can use in the original way:
```ruby
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = ['--no-defaults', '--skip-add-drop-table']
#or
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = '--no-defaults --skip-add-drop-table'
```
And also use it passing a hash, with one or more keys, where the key
is the adapter
```ruby
ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
mysql2: ['--no-defaults', '--skip-add-drop-table'],
postgres: '--no-tablespaces'
}
```
*Gustavo Gonzalez*
* Connection specification now passes the "url" key as a configuration for the
adapter if the "url" protocol is "jdbc", "http", or "https". Previously only
urls with the "jdbc" prefix were passed to the Active Record Adapter, others

View File

@ -39,11 +39,18 @@ module ActiveRecord
##
# :singleton-method:
# Extra flags passed to database CLI tool (mysqldump/pg_dump) when calling db:schema:dump
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
# Example:
# ActiveRecord::Tasks::DatabaseTasks.structure_dump_flags = {
# mysql2: ['--no-defaults', '--skip-add-drop-table'],
# postgres: '--no-tablespaces'
# }
mattr_accessor :structure_dump_flags, instance_accessor: false
##
# :singleton-method:
# Extra flags passed to database CLI tool when calling db:schema:load
# It can be used as a string/array (the typical case) or a hash (when you use multiple adapters)
mattr_accessor :structure_load_flags, instance_accessor: false
extend self
@ -338,13 +345,15 @@ module ActiveRecord
def structure_dump(configuration, *arguments)
db_config = resolve_configuration(configuration)
filename = arguments.delete_at(0)
database_adapter_for(db_config, *arguments).structure_dump(filename, structure_dump_flags)
flags = structure_dump_flags_for(db_config.adapter)
database_adapter_for(db_config, *arguments).structure_dump(filename, flags)
end
def structure_load(configuration, *arguments)
db_config = resolve_configuration(configuration)
filename = arguments.delete_at(0)
database_adapter_for(db_config, *arguments).structure_load(filename, structure_load_flags)
flags = structure_load_flags_for(db_config.adapter)
database_adapter_for(db_config, *arguments).structure_load(filename, flags)
end
def load_schema(db_config, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
@ -566,6 +575,22 @@ module ActiveRecord
def schema_sha1(file)
Digest::SHA1.hexdigest(File.read(file))
end
def structure_dump_flags_for(adapter)
if structure_dump_flags.is_a?(Hash)
structure_dump_flags[adapter.to_sym]
else
structure_dump_flags
end
end
def structure_load_flags_for(adapter)
if structure_load_flags.is_a?(Hash)
structure_load_flags[adapter.to_sym]
else
structure_load_flags
end
end
end
end
end

View File

@ -318,6 +318,28 @@ if current_adapter?(:Mysql2Adapter)
end
end
def test_structure_dump_with_hash_extra_flags_for_a_different_driver
filename = "awesome-file.sql"
expected_command = ["mysqldump", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
end
end
end
def test_structure_dump_with_hash_extra_flags_for_the_correct_driver
filename = "awesome-file.sql"
expected_command = ["mysqldump", "--noop", "--result-file", filename, "--no-data", "--routines", "--skip-comments", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, filename)
end
end
end
def test_structure_dump_with_ignore_tables
filename = "awesome-file.sql"
ActiveRecord::SchemaDumper.stub(:ignore_tables, ["foo", "bar"]) do
@ -404,6 +426,28 @@ if current_adapter?(:Mysql2Adapter)
end
end
def test_structure_load_with_hash_extra_flags_for_a_different_driver
filename = "awesome-file.sql"
expected_command = ["mysql", "--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}, "--database", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
def test_structure_load_with_hash_extra_flags_for_the_correct_driver
filename = "awesome-file.sql"
expected_command = ["mysql", "--noop", "--execute", %{SET FOREIGN_KEY_CHECKS = 0; SOURCE #{filename}; SET FOREIGN_KEY_CHECKS = 1}, "--database", "test-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
private
def with_structure_load_flags(flags)
old = ActiveRecord::Tasks::DatabaseTasks.structure_load_flags

View File

@ -387,6 +387,26 @@ if current_adapter?(:PostgreSQLAdapter)
end
end
def test_structure_dump_with_hash_extra_flags_for_a_different_driver
expected_command = ["pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "my-app-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
end
end
end
def test_structure_dump_with_hash_extra_flags_for_the_correct_driver
expected_command = ["pg_dump", "--schema-only", "--no-privileges", "--no-owner", "--file", @filename, "--noop", "my-app-db"]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_dump_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_dump(@configuration, @filename)
end
end
end
def test_structure_dump_with_ignore_tables
assert_called(
ActiveRecord::SchemaDumper,
@ -509,6 +529,28 @@ if current_adapter?(:PostgreSQLAdapter)
end
end
def test_structure_load_with_hash_extra_flags_for_a_different_driver
filename = "awesome-file.sql"
expected_command = ["psql", "--set", "ON_ERROR_STOP=1", "--quiet", "--no-psqlrc", "--file", filename, @configuration["database"]]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ mysql2: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
def test_structure_load_with_hash_extra_flags_for_the_correct_driver
filename = "awesome-file.sql"
expected_command = ["psql", "--set", "ON_ERROR_STOP=1", "--quiet", "--no-psqlrc", "--file", filename, "--noop", @configuration["database"]]
assert_called_with(Kernel, :system, expected_command, returns: true) do
with_structure_load_flags({ postgresql: ["--noop"] }) do
ActiveRecord::Tasks::DatabaseTasks.structure_load(@configuration, filename)
end
end
end
def test_structure_load_accepts_path_with_spaces
filename = "awesome file.sql"
assert_called_with(