From a77dd104ea9557d26d311d17a8b53c8ab7d7f8a8 Mon Sep 17 00:00:00 2001 From: Weston Ganger Date: Thu, 15 Jul 2021 11:49:29 -0700 Subject: [PATCH] Implement db config option `database_tasks: false` --- activerecord/CHANGELOG.md | 21 ++++++++++ .../active_record/database_configurations.rb | 2 +- .../database_configurations/hash_config.rb | 4 ++ .../lib/active_record/tasks/database_tasks.rb | 2 + .../hash_config_test.rb | 13 +++++++ .../active_record_multiple_databases.md | 18 +++++++++ .../test/application/rake/multi_dbs_test.rb | 39 +++++++++++++++++++ 7 files changed, 98 insertions(+), 1 deletion(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 451f51cbd1..22a5a9f51a 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,24 @@ +* Add database config option `database_tasks` + + If you would like to connect to an external database without any database + mangement tasks such as schema management, migrations, seeds, etc. you can set + the per database config option `database_tasks: false` + + ```yaml + # config/database.yml + + production: + primary: + database: my_database + adapter: mysql2 + animals: + database: my_animals_database + adapter: mysql2 + database_tasks: false + ``` + + *Weston Ganger* + * Fix `ActiveRecord::InternalMetadata` to not be broken by `config.active_record.record_timestamps = false` Since the model always create the timestamp columns, it has to set them, otherwise it breaks diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb index 13b871495f..a223925307 100644 --- a/activerecord/lib/active_record/database_configurations.rb +++ b/activerecord/lib/active_record/database_configurations.rb @@ -48,7 +48,7 @@ module ActiveRecord unless include_replicas configs = configs.select do |db_config| - !db_config.replica? + db_config.database_tasks? end end diff --git a/activerecord/lib/active_record/database_configurations/hash_config.rb b/activerecord/lib/active_record/database_configurations/hash_config.rb index 43b2b687e0..11736984fd 100644 --- a/activerecord/lib/active_record/database_configurations/hash_config.rb +++ b/activerecord/lib/active_record/database_configurations/hash_config.rb @@ -113,6 +113,10 @@ module ActiveRecord def schema_dump configuration_hash.fetch(:schema_dump, true) end + + def database_tasks? # :nodoc: + !replica? && !!configuration_hash.fetch(:database_tasks, true) + end end end end diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 529f3270ef..bbdffa61f9 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -178,6 +178,8 @@ module ActiveRecord return if database_configs.count == 1 database_configs.each do |db_config| + next unless db_config.database_tasks? + yield db_config.name end end diff --git a/activerecord/test/cases/database_configurations/hash_config_test.rb b/activerecord/test/cases/database_configurations/hash_config_test.rb index 2dcaea6dc1..6a7efa3781 100644 --- a/activerecord/test/cases/database_configurations/hash_config_test.rb +++ b/activerecord/test/cases/database_configurations/hash_config_test.rb @@ -122,6 +122,19 @@ module ActiveRecord config = HashConfig.new("default_env", "primary", { schema_dump: false }) assert_equal false, config.schema_dump end + + def test_database_tasks_defaults_to_true + config = HashConfig.new("default_env", "primary", {}) + assert_equal true, config.database_tasks? + end + + def test_database_tasks_overrides_with_value + config = HashConfig.new("default_env", "primary", database_tasks: false) + assert_equal false, config.database_tasks? + + config = HashConfig.new("default_env", "primary", database_tasks: "str") + assert_equal true, config.database_tasks? + end end end end diff --git a/guides/source/active_record_multiple_databases.md b/guides/source/active_record_multiple_databases.md index 2ceff3d7e2..88faf3cf37 100644 --- a/guides/source/active_record_multiple_databases.md +++ b/guides/source/active_record_multiple_databases.md @@ -202,6 +202,24 @@ Note that there is no command for creating the database users, and you'll need t to support the readonly users for your replicas. If you want to create just the animals database you can run `bin/rails db:create:animals`. +## Connecting to Databases without Managing Schema and Migrations + +If you would like to connect to an external database without any database +mangement tasks such as schema management, migrations, seeds, etc. you can set +the per database config option `database_tasks: false`. By default it is +set to true. + +```yaml +production: + primary: + database: my_database + adapter: mysql2 + animals: + database: my_animals_database + adapter: mysql2 + database_tasks: false +``` + ## Generators and Migrations Migrations for multiple databases should live in their own folders prefixed with the diff --git a/railties/test/application/rake/multi_dbs_test.rb b/railties/test/application/rake/multi_dbs_test.rb index c20f6e439a..2da1f775f6 100644 --- a/railties/test/application/rake/multi_dbs_test.rb +++ b/railties/test/application/rake/multi_dbs_test.rb @@ -1065,6 +1065,45 @@ module ApplicationTests db_migrate_and_schema_dump_and_load end + + test "when database_tasks is false, then do not run the database tasks on that db" do + app_file "config/database.yml", <<-YAML + development: + primary: + database: db/default.sqlite3 + adapter: sqlite3 + animals: + database: db/development_animals.sqlite3 + adapter: sqlite3 + database_tasks: false + schema_dump: true ### database_tasks should override all sub-settings + YAML + + Dir.chdir(app_path) do + animals_db_exists = lambda{ rails("runner", "puts !!(AnimalsBase.connection rescue false)").strip } + + generate_models_for_animals + + assert_equal "true", animals_db_exists.call + + assert_not File.exist?("db/animals_schema.yml") + + begin + assert_raise RuntimeError do + rails "db:migrate:animals" ### Task not defined + end + rescue RuntimeError => e + assert_includes e.message, "See the list of available tasks" + end + + rails "db:schema:dump" + assert_not File.exist?("db/animals_schema.yml") + + rails "db:drop" + assert_equal "true", animals_db_exists.call + end + end + end end end