diff options
Diffstat (limited to 'activerecord/lib/active_record/database_configurations.rb')
-rw-r--r-- | activerecord/lib/active_record/database_configurations.rb | 91 |
1 files changed, 60 insertions, 31 deletions
diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb index 44b5cfc738..268be34b21 100644 --- a/activerecord/lib/active_record/database_configurations.rb +++ b/activerecord/lib/active_record/database_configurations.rb @@ -9,6 +9,8 @@ module ActiveRecord # objects (either a HashConfig or UrlConfig) that are constructed from the # application's database configuration hash or URL string. class DatabaseConfigurations + class InvalidConfigurationError < StandardError; end + attr_reader :configurations delegate :any?, to: :configurations @@ -91,6 +93,19 @@ module ActiveRecord end alias :blank? :empty? + def each + throw_getter_deprecation(:each) + configurations.each { |config| + yield [config.env_name, config.config] + } + end + + def first + throw_getter_deprecation(:first) + config = configurations.first + [config.env_name, config.config] + end + private def env_with_configs(env = nil) if env @@ -104,34 +119,48 @@ module ActiveRecord return configs.configurations if configs.is_a?(DatabaseConfigurations) return configs if configs.is_a?(Array) - build_db_config = configs.each_pair.flat_map do |env_name, config| - walk_configs(env_name.to_s, "primary", config) - end.flatten.compact + db_configs = configs.flat_map do |env_name, config| + 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 + + current_env = ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s - if url = ENV["DATABASE_URL"] - build_url_config(url, build_db_config) - else - build_db_config + 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) + config.map do |spec_name, sub_config| + build_db_config_from_raw_config(env_name, spec_name.to_s, sub_config) end end - def walk_configs(env_name, spec_name, config) + def build_db_config_from_raw_config(env_name, spec_name, config) case config when String build_db_config_from_string(env_name, spec_name, config) when Hash build_db_config_from_hash(env_name, spec_name, config.stringify_keys) + else + raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash." end end def build_db_config_from_string(env_name, spec_name, config) url = config uri = URI.parse(url) - if uri.try(:scheme) + if uri.scheme ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url) + else + raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash." end - rescue URI::InvalidURIError - ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, spec_name, config) end def build_db_config_from_hash(env_name, spec_name, config) @@ -141,36 +170,36 @@ module ActiveRecord config_without_url.delete "url" ActiveRecord::DatabaseConfigurations::UrlConfig.new(env_name, spec_name, url, config_without_url) - elsif config["database"] || (config.size == 1 && config.values.all? { |v| v.is_a? String }) - ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, spec_name, config) else - config.each_pair.map do |sub_spec_name, sub_config| - walk_configs(env_name, sub_spec_name, sub_config) - end + ActiveRecord::DatabaseConfigurations::HashConfig.new(env_name, spec_name, config) end end - def build_url_config(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 original_config = configs.find(&:for_current_env?) - if original_config.url_config? - configs - else - configs.map do |config| - 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 = environment_value_for(spec_name) + return unless url + + ActiveRecord::DatabaseConfigurations::UrlConfig.new(env, spec_name, url, config) + end + + def environment_value_for(spec_name) + spec_env_key = "#{spec_name.upcase}_DATABASE_URL" + url = ENV[spec_env_key] + url ||= ENV["DATABASE_URL"] if spec_name == "primary" + url + end + def method_missing(method, *args, &blk) case method - when :each, :first - throw_getter_deprecation(method) - configurations.send(method, *args, &blk) when :fetch throw_getter_deprecation(method) configs_for(env_name: args.first) |