mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Only build a ConnectionSpecification if required
This commit is contained in:
parent
d8336cab32
commit
d2ed433b0a
6 changed files with 60 additions and 60 deletions
6
Gemfile
6
Gemfile
|
@ -36,9 +36,9 @@ group :test do
|
||||||
gem 'ruby-prof', '~> 0.11.2'
|
gem 'ruby-prof', '~> 0.11.2'
|
||||||
end
|
end
|
||||||
|
|
||||||
platforms :mri_19, :mri_20 do
|
# platforms :mri_19, :mri_20 do
|
||||||
gem 'debugger'
|
# gem 'debugger'
|
||||||
end
|
# end
|
||||||
|
|
||||||
gem 'benchmark-ips'
|
gem 'benchmark-ips'
|
||||||
end
|
end
|
||||||
|
|
|
@ -32,6 +32,24 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def spec(config)
|
||||||
|
spec = resolve(config).symbolize_keys
|
||||||
|
|
||||||
|
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
|
||||||
|
|
||||||
|
path_to_adapter = "active_record/connection_adapters/#{spec[:adapter]}_adapter"
|
||||||
|
begin
|
||||||
|
require path_to_adapter
|
||||||
|
rescue Gem::LoadError => e
|
||||||
|
raise Gem::LoadError, "Specified '#{spec[:adapter]}' for database adapter, but the gem is not loaded. Add `gem '#{e.name}'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord)."
|
||||||
|
rescue LoadError => e
|
||||||
|
raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql', 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile.", e.backtrace
|
||||||
|
end
|
||||||
|
|
||||||
|
adapter_method = "#{spec[:adapter]}_connection"
|
||||||
|
ConnectionSpecification.new(spec, adapter_method)
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def resolve_connection(spec) #:nodoc:
|
def resolve_connection(spec) #:nodoc:
|
||||||
|
@ -52,26 +70,11 @@ module ActiveRecord
|
||||||
resolve_string_connection(spec) if spec.is_a?(String)
|
resolve_string_connection(spec) if spec.is_a?(String)
|
||||||
end
|
end
|
||||||
raise(AdapterNotSpecified, "#{spec} database is not configured") unless config
|
raise(AdapterNotSpecified, "#{spec} database is not configured") unless config
|
||||||
resolve_connection config
|
resolve_connection(config)
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_hash_connection(spec) # :nodoc:
|
def resolve_hash_connection(spec) # :nodoc:
|
||||||
spec = spec.symbolize_keys
|
spec
|
||||||
|
|
||||||
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
|
|
||||||
|
|
||||||
path_to_adapter = "active_record/connection_adapters/#{spec[:adapter]}_adapter"
|
|
||||||
begin
|
|
||||||
require path_to_adapter
|
|
||||||
rescue Gem::LoadError => e
|
|
||||||
raise Gem::LoadError, "Specified '#{spec[:adapter]}' for database adapter, but the gem is not loaded. Add `gem '#{e.name}'` to your Gemfile (and ensure its version is at the minimum required by ActiveRecord)."
|
|
||||||
rescue LoadError => e
|
|
||||||
raise LoadError, "Could not load '#{path_to_adapter}'. Make sure that the adapter in config/database.yml is valid. If you use an adapter other than 'mysql', 'mysql2', 'postgresql' or 'sqlite3' add the necessary adapter gem to the Gemfile.", e.backtrace
|
|
||||||
end
|
|
||||||
|
|
||||||
adapter_method = "#{spec[:adapter]}_connection"
|
|
||||||
|
|
||||||
ConnectionSpecification.new(spec, adapter_method)
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_string_connection(spec) # :nodoc:
|
def resolve_string_connection(spec) # :nodoc:
|
||||||
|
@ -89,12 +92,12 @@ module ActiveRecord
|
||||||
config.path.sub(%r{^/},"")
|
config.path.sub(%r{^/},"")
|
||||||
end
|
end
|
||||||
|
|
||||||
spec = { :adapter => adapter,
|
spec = { "adapter" => adapter,
|
||||||
:username => config.user,
|
"username" => config.user,
|
||||||
:password => config.password,
|
"password" => config.password,
|
||||||
:port => config.port,
|
"port" => config.port,
|
||||||
:database => database,
|
"database" => database,
|
||||||
:host => config.host }
|
"host" => config.host }
|
||||||
|
|
||||||
spec.reject!{ |_,value| value.blank? }
|
spec.reject!{ |_,value| value.blank? }
|
||||||
|
|
||||||
|
@ -103,8 +106,7 @@ module ActiveRecord
|
||||||
spec.map { |key,value| spec[key] = uri_parser.unescape(value) if value.is_a?(String) }
|
spec.map { |key,value| spec[key] = uri_parser.unescape(value) if value.is_a?(String) }
|
||||||
|
|
||||||
if config.query
|
if config.query
|
||||||
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
|
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }]
|
||||||
|
|
||||||
spec.merge!(options)
|
spec.merge!(options)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -36,7 +36,7 @@ module ActiveRecord
|
||||||
# may be returned on an error.
|
# may be returned on an error.
|
||||||
def establish_connection(spec = ENV["DATABASE_URL"])
|
def establish_connection(spec = ENV["DATABASE_URL"])
|
||||||
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
|
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
|
||||||
spec = resolver.resolve(spec)
|
spec = resolver.spec(spec)
|
||||||
|
|
||||||
unless respond_to?(spec.adapter_method)
|
unless respond_to?(spec.adapter_method)
|
||||||
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
||||||
|
|
|
@ -56,7 +56,7 @@ module ActiveRecord
|
||||||
resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(configuration)
|
resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(configuration)
|
||||||
|
|
||||||
configuration.each do |key, value|
|
configuration.each do |key, value|
|
||||||
configuration[key] = resolver.resolve(value).config.stringify_keys if value
|
configuration[key] = resolver.resolve(value) if value
|
||||||
end
|
end
|
||||||
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.database_configuration = configuration
|
ActiveRecord::Tasks::DatabaseTasks.database_configuration = configuration
|
||||||
|
|
|
@ -5,13 +5,19 @@ module ActiveRecord
|
||||||
class ConnectionSpecification
|
class ConnectionSpecification
|
||||||
class ResolverTest < ActiveRecord::TestCase
|
class ResolverTest < ActiveRecord::TestCase
|
||||||
def resolve(spec, config={})
|
def resolve(spec, config={})
|
||||||
Resolver.new(config).resolve(spec).config
|
Resolver.new(config).resolve(spec)
|
||||||
|
end
|
||||||
|
|
||||||
|
def spec(spec, config={})
|
||||||
|
Resolver.new(config).spec(spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_invalid_adapter
|
def test_url_invalid_adapter
|
||||||
assert_raises(LoadError) do
|
error = assert_raises(LoadError) do
|
||||||
resolve 'ridiculous://foo?encoding=utf8'
|
spec 'ridiculous://foo?encoding=utf8'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
assert_match "Could not load 'active_record/connection_adapters/ridiculous_adapter'", error.message
|
||||||
end
|
end
|
||||||
|
|
||||||
# The abstract adapter is used simply to bypass the bit of code that
|
# The abstract adapter is used simply to bypass the bit of code that
|
||||||
|
@ -20,60 +26,52 @@ module ActiveRecord
|
||||||
def test_url_from_environment
|
def test_url_from_environment
|
||||||
spec = resolve :production, 'production' => 'abstract://foo?encoding=utf8'
|
spec = resolve :production, 'production' => 'abstract://foo?encoding=utf8'
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
"adapter" => "abstract",
|
||||||
host: "foo",
|
"host" => "foo",
|
||||||
encoding: "utf8" }, spec)
|
"encoding" => "utf8" }, spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_host_no_db
|
def test_url_host_no_db
|
||||||
spec = resolve 'abstract://foo?encoding=utf8'
|
spec = resolve 'abstract://foo?encoding=utf8'
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
"adapter" => "abstract",
|
||||||
host: "foo",
|
"host" => "foo",
|
||||||
encoding: "utf8" }, spec)
|
"encoding" => "utf8" }, spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_host_db
|
def test_url_host_db
|
||||||
spec = resolve 'abstract://foo/bar?encoding=utf8'
|
spec = resolve 'abstract://foo/bar?encoding=utf8'
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
"adapter" => "abstract",
|
||||||
database: "bar",
|
"database" => "bar",
|
||||||
host: "foo",
|
"host" => "foo",
|
||||||
encoding: "utf8" }, spec)
|
"encoding" => "utf8" }, spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_port
|
def test_url_port
|
||||||
spec = resolve 'abstract://foo:123?encoding=utf8'
|
spec = resolve 'abstract://foo:123?encoding=utf8'
|
||||||
assert_equal({
|
assert_equal({
|
||||||
adapter: "abstract",
|
"adapter" => "abstract",
|
||||||
port: 123,
|
"port" => 123,
|
||||||
host: "foo",
|
"host" => "foo",
|
||||||
encoding: "utf8" }, spec)
|
"encoding" => "utf8" }, spec)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_encoded_password
|
def test_encoded_password
|
||||||
password = 'am@z1ng_p@ssw0rd#!'
|
password = 'am@z1ng_p@ssw0rd#!'
|
||||||
encoded_password = URI.encode_www_form_component(password)
|
encoded_password = URI.encode_www_form_component(password)
|
||||||
spec = resolve "abstract://foo:#{encoded_password}@localhost/bar"
|
spec = resolve "abstract://foo:#{encoded_password}@localhost/bar"
|
||||||
assert_equal password, spec[:password]
|
assert_equal password, spec["password"]
|
||||||
end
|
|
||||||
|
|
||||||
def test_descriptive_error_message_when_adapter_is_missing
|
|
||||||
error = assert_raise(LoadError) do
|
|
||||||
resolve(adapter: 'non-existing')
|
|
||||||
end
|
|
||||||
|
|
||||||
assert_match "Could not load 'active_record/connection_adapters/non-existing_adapter'", error.message
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_host_db_for_sqlite3
|
def test_url_host_db_for_sqlite3
|
||||||
spec = resolve 'sqlite3://foo:bar@dburl:9000/foo_test'
|
spec = resolve 'sqlite3://foo:bar@dburl:9000/foo_test'
|
||||||
assert_equal('/foo_test', spec[:database])
|
assert_equal('/foo_test', spec["database"])
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_host_memory_db_for_sqlite3
|
def test_url_host_memory_db_for_sqlite3
|
||||||
spec = resolve 'sqlite3://foo:bar@dburl:9000/:memory:'
|
spec = resolve 'sqlite3://foo:bar@dburl:9000/:memory:'
|
||||||
assert_equal(':memory:', spec[:database])
|
assert_equal(':memory:', spec["database"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -84,7 +84,7 @@ module Rails
|
||||||
require APP_PATH
|
require APP_PATH
|
||||||
ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(
|
ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(
|
||||||
Rails.application.config.database_configuration || {}
|
Rails.application.config.database_configuration || {}
|
||||||
).resolve(ENV["DATABASE_URL"]).config.stringify_keys
|
).resolve(ENV["DATABASE_URL"])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue