mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Guarantee the connection resolver handles string values
This commit also cleans up the rake tasks that were checking for DATABASE_URL in different places. In fact, it would be nice to deprecate DATABASE_URL usage in the long term, considering the direction we are moving of allowing those in .yml files.
This commit is contained in:
parent
d22a359a18
commit
c390e60811
6 changed files with 58 additions and 53 deletions
|
@ -16,34 +16,43 @@ module ActiveRecord
|
||||||
##
|
##
|
||||||
# Builds a ConnectionSpecification from user input
|
# Builds a ConnectionSpecification from user input
|
||||||
class Resolver # :nodoc:
|
class Resolver # :nodoc:
|
||||||
attr_reader :config, :klass, :configurations
|
attr_reader :configurations
|
||||||
|
|
||||||
def initialize(config, configurations)
|
def initialize(configurations)
|
||||||
@config = config
|
|
||||||
@configurations = configurations
|
@configurations = configurations
|
||||||
end
|
end
|
||||||
|
|
||||||
def spec
|
def resolve(config)
|
||||||
case config
|
if config
|
||||||
when nil
|
resolve_connection config
|
||||||
raise AdapterNotSpecified unless defined?(Rails.env)
|
elsif defined?(Rails.env)
|
||||||
resolve_string_connection Rails.env
|
resolve_env_connection Rails.env
|
||||||
when Symbol, String
|
else
|
||||||
resolve_string_connection config.to_s
|
raise AdapterNotSpecified
|
||||||
when Hash
|
|
||||||
resolve_hash_connection config
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
def resolve_string_connection(spec) # :nodoc:
|
|
||||||
hash = configurations.fetch(spec) do |k|
|
def resolve_connection(spec) #:nodoc:
|
||||||
connection_url_to_hash(k)
|
case spec
|
||||||
|
when Symbol, String
|
||||||
|
resolve_env_connection spec.to_s
|
||||||
|
when Hash
|
||||||
|
resolve_hash_connection spec
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
|
def resolve_env_connection(spec) # :nodoc:
|
||||||
|
# Rails has historically accepted a string to mean either
|
||||||
resolve_hash_connection hash
|
# an environment key or a url spec. So we support both for
|
||||||
|
# now but it would be nice to limit the environment key only
|
||||||
|
# for symbols.
|
||||||
|
spec = configurations.fetch(spec.to_s) do
|
||||||
|
resolve_string_connection(spec) if spec.is_a?(String)
|
||||||
|
end
|
||||||
|
raise(AdapterNotSpecified, "#{spec} database is not configured") unless spec
|
||||||
|
resolve_connection spec
|
||||||
end
|
end
|
||||||
|
|
||||||
def resolve_hash_connection(spec) # :nodoc:
|
def resolve_hash_connection(spec) # :nodoc:
|
||||||
|
@ -65,8 +74,8 @@ module ActiveRecord
|
||||||
ConnectionSpecification.new(spec, adapter_method)
|
ConnectionSpecification.new(spec, adapter_method)
|
||||||
end
|
end
|
||||||
|
|
||||||
def connection_url_to_hash(url) # :nodoc:
|
def resolve_string_connection(spec) # :nodoc:
|
||||||
config = URI.parse url
|
config = URI.parse spec
|
||||||
adapter = config.scheme
|
adapter = config.scheme
|
||||||
adapter = "postgresql" if adapter == "postgres"
|
adapter = "postgresql" if adapter == "postgres"
|
||||||
|
|
||||||
|
|
|
@ -35,8 +35,8 @@ module ActiveRecord
|
||||||
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
||||||
# 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 spec, configurations
|
resolver = ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
|
||||||
spec = resolver.spec
|
spec = resolver.resolve(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"
|
||||||
|
|
|
@ -43,11 +43,24 @@ module ActiveRecord
|
||||||
namespace :db do
|
namespace :db do
|
||||||
task :load_config do
|
task :load_config do
|
||||||
ActiveRecord::Tasks::DatabaseTasks.db_dir = Rails.application.config.paths["db"].first
|
ActiveRecord::Tasks::DatabaseTasks.db_dir = Rails.application.config.paths["db"].first
|
||||||
ActiveRecord::Tasks::DatabaseTasks.database_configuration = Rails.application.config.database_configuration
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.migrations_paths = Rails.application.paths['db/migrate'].to_a
|
ActiveRecord::Tasks::DatabaseTasks.migrations_paths = Rails.application.paths['db/migrate'].to_a
|
||||||
ActiveRecord::Tasks::DatabaseTasks.fixtures_path = File.join Rails.root, 'test', 'fixtures'
|
ActiveRecord::Tasks::DatabaseTasks.fixtures_path = File.join Rails.root, 'test', 'fixtures'
|
||||||
ActiveRecord::Tasks::DatabaseTasks.root = Rails.root
|
ActiveRecord::Tasks::DatabaseTasks.root = Rails.root
|
||||||
|
|
||||||
|
configuration = if ENV["DATABASE_URL"]
|
||||||
|
{ Rails.env => ENV["DATABASE_URL"] }
|
||||||
|
else
|
||||||
|
Rails.application.config.database_configuration || {}
|
||||||
|
end
|
||||||
|
|
||||||
|
resolver = ActiveRecord::ConnectionAdapters::ConnectionSpecification::Resolver.new(configuration)
|
||||||
|
|
||||||
|
configuration.each do |key, value|
|
||||||
|
configuration[key] = resolver.resolve(value) if value
|
||||||
|
end
|
||||||
|
|
||||||
|
ActiveRecord::Tasks::DatabaseTasks.database_configuration = configuration
|
||||||
|
|
||||||
if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
|
if defined?(ENGINE_PATH) && engine = Rails::Engine.find(ENGINE_PATH)
|
||||||
if engine.paths['db/migrate'].existent
|
if engine.paths['db/migrate'].existent
|
||||||
ActiveRecord::Tasks::DatabaseTasks.migrations_paths += engine.paths['db/migrate'].to_a
|
ActiveRecord::Tasks::DatabaseTasks.migrations_paths += engine.paths['db/migrate'].to_a
|
||||||
|
|
|
@ -14,12 +14,8 @@ db_namespace = namespace :db do
|
||||||
|
|
||||||
desc 'Create the database from DATABASE_URL or config/database.yml for the current Rails.env (use db:create:all to create all databases in the config)'
|
desc 'Create the database from DATABASE_URL or config/database.yml for the current Rails.env (use db:create:all to create all databases in the config)'
|
||||||
task :create => [:load_config] do
|
task :create => [:load_config] do
|
||||||
if ENV['DATABASE_URL']
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create_database_url
|
|
||||||
else
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.create_current
|
ActiveRecord::Tasks::DatabaseTasks.create_current
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
namespace :drop do
|
namespace :drop do
|
||||||
task :all => :load_config do
|
task :all => :load_config do
|
||||||
|
@ -29,12 +25,8 @@ db_namespace = namespace :db do
|
||||||
|
|
||||||
desc 'Drops the database using DATABASE_URL or the current Rails.env (use db:drop:all to drop all databases)'
|
desc 'Drops the database using DATABASE_URL or the current Rails.env (use db:drop:all to drop all databases)'
|
||||||
task :drop => [:load_config] do
|
task :drop => [:load_config] do
|
||||||
if ENV['DATABASE_URL']
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.drop_database_url
|
|
||||||
else
|
|
||||||
ActiveRecord::Tasks::DatabaseTasks.drop_current
|
ActiveRecord::Tasks::DatabaseTasks.drop_current
|
||||||
end
|
end
|
||||||
end
|
|
||||||
|
|
||||||
desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
|
desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)."
|
||||||
task :migrate => [:environment, :load_config] do
|
task :migrate => [:environment, :load_config] do
|
||||||
|
|
|
@ -56,11 +56,7 @@ module ActiveRecord
|
||||||
if options.has_key?(:config)
|
if options.has_key?(:config)
|
||||||
@current_config = options[:config]
|
@current_config = options[:config]
|
||||||
else
|
else
|
||||||
@current_config ||= if ENV['DATABASE_URL']
|
@current_config ||= ActiveRecord::Base.configurations[options[:env]]
|
||||||
database_url_config
|
|
||||||
else
|
|
||||||
ActiveRecord::Base.configurations[options[:env]]
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -85,10 +81,6 @@ module ActiveRecord
|
||||||
ActiveRecord::Base.establish_connection environment
|
ActiveRecord::Base.establish_connection environment
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_database_url
|
|
||||||
create database_url_config
|
|
||||||
end
|
|
||||||
|
|
||||||
def drop(*arguments)
|
def drop(*arguments)
|
||||||
configuration = arguments.first
|
configuration = arguments.first
|
||||||
class_for_adapter(configuration['adapter']).new(*arguments).drop
|
class_for_adapter(configuration['adapter']).new(*arguments).drop
|
||||||
|
@ -107,10 +99,6 @@ module ActiveRecord
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
||||||
def drop_database_url
|
|
||||||
drop database_url_config
|
|
||||||
end
|
|
||||||
|
|
||||||
def charset_current(environment = env)
|
def charset_current(environment = env)
|
||||||
charset ActiveRecord::Base.configurations[environment]
|
charset ActiveRecord::Base.configurations[environment]
|
||||||
end
|
end
|
||||||
|
@ -165,11 +153,6 @@ module ActiveRecord
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def database_url_config
|
|
||||||
@database_url_config ||=
|
|
||||||
ConnectionAdapters::ConnectionSpecification::Resolver.new(ENV["DATABASE_URL"], {}).spec.config.stringify_keys
|
|
||||||
end
|
|
||||||
|
|
||||||
def class_for_adapter(adapter)
|
def class_for_adapter(adapter)
|
||||||
key = @tasks.keys.detect { |pattern| adapter[pattern] }
|
key = @tasks.keys.detect { |pattern| adapter[pattern] }
|
||||||
unless key
|
unless key
|
||||||
|
|
|
@ -4,8 +4,8 @@ module ActiveRecord
|
||||||
module ConnectionAdapters
|
module ConnectionAdapters
|
||||||
class ConnectionSpecification
|
class ConnectionSpecification
|
||||||
class ResolverTest < ActiveRecord::TestCase
|
class ResolverTest < ActiveRecord::TestCase
|
||||||
def resolve(spec)
|
def resolve(spec, config={})
|
||||||
Resolver.new(spec, {}).spec.config
|
Resolver.new(config).resolve(spec).config
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_url_invalid_adapter
|
def test_url_invalid_adapter
|
||||||
|
@ -17,6 +17,14 @@ module ActiveRecord
|
||||||
# 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
|
||||||
# checks that the adapter file can be required in.
|
# checks that the adapter file can be required in.
|
||||||
|
|
||||||
|
def test_url_from_environment
|
||||||
|
spec = resolve :production, 'production' => 'abstract://foo?encoding=utf8'
|
||||||
|
assert_equal({
|
||||||
|
adapter: "abstract",
|
||||||
|
host: "foo",
|
||||||
|
encoding: "utf8" }, spec)
|
||||||
|
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({
|
||||||
|
|
Loading…
Reference in a new issue