diff options
-rw-r--r-- | activerecord/lib/active_record.rb | 1 | ||||
-rw-r--r-- | activerecord/lib/active_record/base.rb | 1 | ||||
-rw-r--r-- | activerecord/lib/active_record/core.rb | 39 | ||||
-rw-r--r-- | activerecord/lib/active_record/database_configurations.rb | 63 | ||||
-rw-r--r-- | activerecord/lib/active_record/railties/databases.rake | 32 | ||||
-rw-r--r-- | activerecord/lib/active_record/tasks/database_tasks.rb | 9 | ||||
-rw-r--r-- | railties/lib/rails/application/configuration.rb | 12 |
7 files changed, 101 insertions, 56 deletions
diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index d43378c64f..d198466dbf 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -40,6 +40,7 @@ module ActiveRecord autoload :Core autoload :ConnectionHandling autoload :CounterCache + autoload :DatabaseConfigurations autoload :DynamicMatchers autoload :Enum autoload :InternalMetadata diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index cc99401390..7ab9160265 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -290,6 +290,7 @@ module ActiveRecord #:nodoc: extend CollectionCacheKey include Core + include DatabaseConfigurations include Persistence include ReadonlyAttributes include ModelSchema diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index b6b4c76569..e1a0b2ecf8 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -60,45 +60,6 @@ module ActiveRecord @@configurations end - DatabaseConfig = Struct.new(:env_name, :spec_name, :config) # :nodoc - - # Given an env, spec and config creates DatabaseConfig structs with - # each attribute set. - def self.walk_configs(env_name, spec_name, config) # :nodoc: - if config["database"] || env_name == "default" - DatabaseConfig.new(env_name, spec_name, config) - else - config.each_pair.map do |spec_name, sub_config| - walk_configs(env_name, spec_name, sub_config) - end - end - end - - # Walks all the configs passed in and returns an array - # of DatabaseConfig structs for each configuration. - def self.db_configs(configs = configurations) # :nodoc: - configs.each_pair.flat_map do |env_name, config| - walk_configs(env_name, "primary", config) - end - end - - # Collects the configs for the environment passed in. - # - # If a block is given returns the specification name and configuration - # otherwise returns an array of DatabaseConfig structs for the environment. - def self.configs_for(environment, configs = configurations, &blk) # :nodoc: - env_with_configs = db_configs(configs).select do |db_config| - db_config.env_name == environment - end - - if block_given? - env_with_configs.each do |env_with_config| - yield env_with_config.spec_name, env_with_config.config - end - else - env_with_configs - end - end ## # :singleton-method: # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling diff --git a/activerecord/lib/active_record/database_configurations.rb b/activerecord/lib/active_record/database_configurations.rb new file mode 100644 index 0000000000..86624a41c9 --- /dev/null +++ b/activerecord/lib/active_record/database_configurations.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module ActiveRecord + module DatabaseConfigurations # :nodoc: + class DatabaseConfig + attr_reader :env_name, :spec_name, :config + + def initialize(env_name, spec_name, config) + @env_name = env_name + @spec_name = spec_name + @config = config + end + end + + # Selects the config for the specified environment and specification name + # + # For example if passed :development, and :animals it will select the database + # under the :development and :animals configuration level + def self.config_for_env_and_spec(environment, specification_name, configs = ActiveRecord::Base.configurations) # :nodoc: + configs_for(environment, configs).find do |db_config| + db_config.spec_name == specification_name + end + end + + # Collects the configs for the environment passed in. + # + # If a block is given returns the specification name and configuration + # otherwise returns an array of DatabaseConfig structs for the environment. + def self.configs_for(env, configs = ActiveRecord::Base.configurations, &blk) # :nodoc: + env_with_configs = db_configs(configs).select do |db_config| + db_config.env_name == env + end + + if block_given? + env_with_configs.each do |env_with_config| + yield env_with_config.spec_name, env_with_config.config + end + else + env_with_configs + end + end + + # Given an env, spec and config creates DatabaseConfig structs with + # each attribute set. + def self.walk_configs(env_name, spec_name, config) # :nodoc: + if config["database"] || env_name == "default" + DatabaseConfig.new(env_name, spec_name, config) + else + config.each_pair.map do |spec_name, sub_config| + walk_configs(env_name, spec_name, sub_config) + end + end + end + + # Walks all the configs passed in and returns an array + # of DatabaseConfig structs for each configuration. + def self.db_configs(configs = ActiveRecord::Base.configurations) # :nodoc: + configs.each_pair.flat_map do |env_name, config| + walk_configs(env_name, "primary", config) + end + end + end +end diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index cd0c4616b8..76dbcafffb 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -23,11 +23,11 @@ db_namespace = namespace :db do ActiveRecord::Tasks::DatabaseTasks.create_all end - databases = Rails.application.config.database_configuration - ActiveRecord::Base.configs_for(Rails.env, databases) do |spec_name, config| + ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| desc "Create #{spec_name} database for current environment" - task spec_name do - ActiveRecord::Tasks::DatabaseTasks.create(config) + task spec_name => :load_config do + db_config = ActiveRecord::DatabaseConfigurations.config_for_env_and_spec(Rails.env, spec_name) + ActiveRecord::Tasks::DatabaseTasks.create(db_config.config) end end end @@ -42,11 +42,11 @@ db_namespace = namespace :db do ActiveRecord::Tasks::DatabaseTasks.drop_all end - databases = Rails.application.config.database_configuration - ActiveRecord::Base.configs_for(Rails.env, databases) do |spec_name, config| + ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| desc "Drop #{spec_name} database for current environment" - task spec_name => :check_protected_environments do - ActiveRecord::Tasks::DatabaseTasks.drop(config) + task spec_name => [:load_config, :check_protected_environments] do + db_config = ActiveRecord::DatabaseConfigurations.config_for_env_and_spec(Rails.env, spec_name) + ActiveRecord::Tasks::DatabaseTasks.drop(db_config.config) end end end @@ -73,11 +73,11 @@ db_namespace = namespace :db do desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)." task migrate: :load_config do - ActiveRecord::Base.configs_for(Rails.env) do |spec_name, config| + ActiveRecord::DatabaseConfigurations.configs_for(Rails.env) do |spec_name, config| ActiveRecord::Base.establish_connection(config) ActiveRecord::Tasks::DatabaseTasks.migrate - db_namespace["_dump"].invoke end + db_namespace["_dump"].invoke end # IMPORTANT: This task won't dump the schema if ActiveRecord::Base.dump_schema_after_migration is set to false @@ -96,11 +96,11 @@ db_namespace = namespace :db do end namespace :migrate do - databases = Rails.application.config.database_configuration - ActiveRecord::Base.configs_for(Rails.env, databases) do |spec_name, config| + ActiveRecord::Tasks::DatabaseTasks.for_each do |spec_name| desc "Migrate #{spec_name} database for current environment" - task spec_name do - ActiveRecord::Base.establish_connection(config) + task spec_name => :load_config do + db_config = ActiveRecord::DatabaseConfigurations.config_for_env_and_spec(Rails.env, spec_name) + ActiveRecord::Base.establish_connection(db_config.config) ActiveRecord::Tasks::DatabaseTasks.migrate end end @@ -275,7 +275,7 @@ db_namespace = namespace :db do task dump: :load_config do require "active_record/schema_dumper" - ActiveRecord::Base.configs_for(Rails.env) do |spec_name, config| + ActiveRecord::DatabaseConfigurations.configs_for(Rails.env) do |spec_name, config| filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(spec_name, :ruby) File.open(filename, "w:utf-8") do |file| ActiveRecord::Base.establish_connection(config) @@ -314,7 +314,7 @@ db_namespace = namespace :db do namespace :structure do desc "Dumps the database structure to db/structure.sql. Specify another file with SCHEMA=db/my_structure.sql" task dump: :load_config do - ActiveRecord::Base.configs_for(Rails.env) do |spec_name, config| + ActiveRecord::DatabaseConfigurations.configs_for(Rails.env) do |spec_name, config| ActiveRecord::Base.establish_connection(config) filename = ActiveRecord::Tasks::DatabaseTasks.dump_filename(spec_name, :sql) current_config = ActiveRecord::Tasks::DatabaseTasks.current_config diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index e2c292ee56..5787660148 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -134,6 +134,13 @@ module ActiveRecord end end + def for_each + databases = Rails.application.config.load_database_yaml + ActiveRecord::DatabaseConfigurations.configs_for(Rails.env, databases) do |spec_name, _| + yield spec_name + end + end + def create_current(environment = env) each_current_configuration(environment) { |configuration| create configuration @@ -327,7 +334,7 @@ module ActiveRecord environments << "test" if environment == "development" environments.each do |env| - ActiveRecord::Base.configs_for(env) do |spec_name, configuration| + ActiveRecord::DatabaseConfigurations.configs_for(env) do |spec_name, configuration| yield configuration, spec_name, env end end diff --git a/railties/lib/rails/application/configuration.rb b/railties/lib/rails/application/configuration.rb index 912faed3e4..f80da4b005 100644 --- a/railties/lib/rails/application/configuration.rb +++ b/railties/lib/rails/application/configuration.rb @@ -166,6 +166,18 @@ module Rails end end + # Loads the database YAML without evaluating ERB. People seem to + # write ERB that makes the database configuration depend on + # Rails configuration. But we want Rails configuration (specifically + # `rake` and `rails` tasks) to be generated based on information in + # the database yaml, so we need a method that loads the database + # yaml *without* the context of the Rails application. + def load_database_yaml # :nodoc: + path = paths["config/database"].existent.first + return {} unless path + YAML.load_file(path.to_s) + end + # Loads and returns the entire raw configuration of database from # values stored in <tt>config/database.yml</tt>. def database_configuration |