mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
fdf3f0b930
While the three-tier config makes it easier to define databases for multiple database applications, it quickly became clear to offer full support for multiple databases we need to change the way the connections hash was handled. A three-tier config means that when Rails needed to choose a default configuration (in the case a user doesn't ask for a specific configuration) it wasn't clear to Rails which the default was. I [bandaid fixed this so the rake tasks could work](#32271) but that fix wasn't correct because it actually doubled up the configuration hashes. Instead of attemping to manipulate the hashes @tenderlove and I decided that it made more sense if we converted the hashes to objects so we can easily ask those object questions. In a three tier config like this: ``` development: primary: database: "my_primary_db" animals: database; "my_animals_db" ``` We end up with an object like this: ``` @configurations=[ #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",@spec_name="primary", @config={"adapter"=>"sqlite3", "database"=>"db/development.sqlite3"}>, #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="development",@spec_name="animals", @config={"adapter"=>"sqlite3", "database"=>"db/development.sqlite3"}> ]> ``` The configurations setter takes the database configuration set by your application and turns them into an `ActiveRecord::DatabaseConfigurations` object that has one getter - `@configurations` which is an array of all the database objects. The configurations getter returns this object by default since it acts like a hash in most of the cases we need. For example if you need to access the default `development` database we can simply request it as we did before: ``` ActiveRecord::Base.configurations["development"] ``` This will return primary development database configuration hash: ``` { "database" => "my_primary_db" } ``` Internally all of Active Record has been converted to use the new objects. I've built this to be backwards compatible but allow for accessing the hash if needed for a deprecation period. To get the original hash instead of the object you can either add `to_h` on the configurations call or pass `legacy: true` to `configurations. ``` ActiveRecord::Base.configurations.to_h => { "development => { "database" => "my_primary_db" } } ActiveRecord::Base.configurations(legacy: true) => { "development => { "database" => "my_primary_db" } } ``` The new configurations object allows us to iterate over the Active Record configurations without losing the known environment or specification name for that configuration. You can also select all the configs for an env or env and spec. With this we can always ask any object what environment it belongs to: ``` db_configs = ActiveRecord::Base.configurations.configurations_for("development") => #<ActiveRecord::DatabaseConfigurations:0x00007fd1acbdf800 @configurations=[ #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10 @env_name="development",@spec_name="primary", @config={"adapter"=>"sqlite3", "database"=>"db/development.sqlite3"}>, #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbdea90 @env_name="development",@spec_name="animals", @config={"adapter"=>"sqlite3", "database"=>"db/development.sqlite3"}> ]> db_config.env_name => "development" db_config.spec_name => "primary" db_config.config => { "adapter"=>"sqlite3", "database"=>"db/development.sqlite3" } ``` The configurations object is more flexible than the configurations hash and will allow us to build on top of the connection management in order to add support for primary/replica connections, sharding, and constructing queries for associations that live in multiple databases.
43 lines
1.4 KiB
Ruby
43 lines
1.4 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
require "cases/helper"
|
|
|
|
module ActiveRecord
|
|
class LegacyConfigurationsTest < ActiveRecord::TestCase
|
|
def test_can_turn_configurations_into_a_hash
|
|
assert ActiveRecord::Base.configurations.to_h.is_a?(Hash), "expected to be a hash but was not."
|
|
assert_equal ["arunit", "arunit2", "arunit_without_prepared_statements"].sort, ActiveRecord::Base.configurations.to_h.keys.sort
|
|
end
|
|
|
|
def test_each_is_deprecated
|
|
assert_deprecated do
|
|
ActiveRecord::Base.configurations.each do |db_config|
|
|
assert_equal "primary", db_config.spec_name
|
|
end
|
|
end
|
|
end
|
|
|
|
def test_first_is_deprecated
|
|
assert_deprecated do
|
|
db_config = ActiveRecord::Base.configurations.first
|
|
assert_equal "arunit", db_config.env_name
|
|
assert_equal "primary", db_config.spec_name
|
|
end
|
|
end
|
|
|
|
def test_fetch_is_deprecated
|
|
assert_deprecated do
|
|
db_config = ActiveRecord::Base.configurations.fetch("arunit").first
|
|
assert_equal "arunit", db_config.env_name
|
|
assert_equal "primary", db_config.spec_name
|
|
end
|
|
end
|
|
|
|
def test_values_are_deprecated
|
|
config_hashes = ActiveRecord::Base.configurations.configurations.map(&:config)
|
|
assert_deprecated do
|
|
assert_equal config_hashes, ActiveRecord::Base.configurations.values
|
|
end
|
|
end
|
|
end
|
|
end
|