From 5e260574a43d5c2fef8b170138baa9f7e10bfb24 Mon Sep 17 00:00:00 2001 From: John Crepezzi Date: Thu, 25 Jul 2019 20:08:10 -0400 Subject: Only merge DATABASE_URL settings into the current env This commit fixes a regression where when the `DATABASE_URL` environment variable was set and the current Rails environment had a valid configuration defined in the database config, settings from the environment variable would affect _all_ environments (not just the current one). --- .../lib/active_record/database_configurations.rb | 38 ++++++++++++---------- .../merge_and_resolve_default_url_config_test.rb | 16 +++++++++ 2 files changed, 36 insertions(+), 18 deletions(-) (limited to 'activerecord') diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb index e122628b05..8baa0f5af6 100644 --- a/activerecord/lib/active_record/database_configurations.rb +++ b/activerecord/lib/active_record/database_configurations.rb @@ -105,18 +105,20 @@ module ActiveRecord return configs if configs.is_a?(Array) db_configs = configs.flat_map do |env_name, config| - if config.is_a?(Hash) && config.all? { |k, v| v.is_a?(Hash) } + if config.is_a?(Hash) && config.all? { |_, v| v.is_a?(Hash) } walk_configs(env_name.to_s, config) else build_db_config_from_raw_config(env_name.to_s, "primary", config) end - end.compact + end - if url = ENV["DATABASE_URL"] - merge_url_with_configs(url, db_configs) - else - db_configs + current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s + + unless db_configs.find(&:for_current_env?) + db_configs << environment_url_config(current_env, "primary", {}) end + + merge_db_environment_variables(current_env, db_configs.compact) end def walk_configs(env_name, config) @@ -156,22 +158,22 @@ module ActiveRecord end end - def merge_url_with_configs(url, configs) - env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s + def merge_db_environment_variables(current_env, configs) + configs.map do |config| + next config if config.url_config? || config.env_name != current_env - if configs.find(&:for_current_env?) - configs.map do |config| - if config.url_config? - config - else - ActiveRecord::DatabaseConfigurations::UrlConfig.new(config.env_name, config.spec_name, url, config.config) - end - end - else - configs + [ActiveRecord::DatabaseConfigurations::UrlConfig.new(env, "primary", url)] + url_config = environment_url_config(current_env, config.spec_name, config.config) + url_config || config end end + def environment_url_config(env, spec_name, config) + url = ENV["DATABASE_URL"] + return unless url + + ActiveRecord::DatabaseConfigurations::UrlConfig.new(env, spec_name, url, config) + end + def method_missing(method, *args, &blk) case method when :each, :first diff --git a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb index 15a045ed23..95e57f42e3 100644 --- a/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb +++ b/activerecord/test/cases/connection_adapters/merge_and_resolve_default_url_config_test.rb @@ -347,6 +347,22 @@ module ActiveRecord assert_equal expected, actual end end + + def test_does_not_change_other_environments + ENV["DATABASE_URL"] = "postgres://localhost/foo" + config = { "production" => { "adapter" => "not_postgres", "database" => "not_foo", "host" => "localhost" }, "default_env" => {} } + + actual = resolve_spec(:production, config) + assert_equal config["production"].merge("name" => "production"), actual + + actual = resolve_spec(:default_env, config) + assert_equal({ + "host" => "localhost", + "database" => "foo", + "adapter" => "postgresql", + "name" => "default_env" + }, actual) + end end end end -- cgit v1.2.3