connection_handling.rb 4.8 KB
Newer Older
1 2
module ActiveRecord
  module ConnectionHandling
3 4 5
    RAILS_ENV   = -> { Rails.env if defined?(Rails) }
    DEFAULT_ENV = -> { RAILS_ENV.call || "default_env" }

6 7 8 9 10
    # Establishes the connection to the database. Accepts a hash as input where
    # the <tt>:adapter</tt> key must be specified with the name of a database adapter (in lower-case)
    # example for regular databases (MySQL, Postgresql, etc):
    #
    #   ActiveRecord::Base.establish_connection(
A
AvnerCohen 已提交
11 12 13 14 15
    #     adapter:  "mysql",
    #     host:     "localhost",
    #     username: "myuser",
    #     password: "mypass",
    #     database: "somedatabase"
16 17 18 19 20
    #   )
    #
    # Example for SQLite database:
    #
    #   ActiveRecord::Base.establish_connection(
21 22
    #     adapter:  "sqlite",
    #     database: "path/to/dbfile"
23 24 25 26 27
    #   )
    #
    # Also accepts keys as strings (for parsing from YAML for example):
    #
    #   ActiveRecord::Base.establish_connection(
28 29
    #     "adapter"  => "sqlite",
    #     "database" => "path/to/dbfile"
30 31 32 33 34 35 36 37
    #   )
    #
    # Or a URL:
    #
    #   ActiveRecord::Base.establish_connection(
    #     "postgres://myuser:mypass@localhost/somedatabase"
    #   )
    #
38 39 40 41 42 43 44
    # In case <tt>ActiveRecord::Base.configurations</tt> is set (Rails
    # automatically loads the contents of config/database.yml into it),
    # a symbol can also be given as argument, representing a key in the
    # configuration hash:
    #
    #   ActiveRecord::Base.establish_connection(:production)
    #
45 46
    # The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
    # may be returned on an error.
47 48 49 50
    def establish_connection(spec = nil)
      spec     ||= DEFAULT_ENV.call.to_sym
      resolver =   ConnectionAdapters::ConnectionSpecification::Resolver.new configurations
      spec     =   resolver.spec(spec)
51 52 53 54 55 56

      unless respond_to?(spec.adapter_method)
        raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
      end

      remove_connection
57
      connection_handler.establish_connection self, spec
58 59
    end

60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
    class MergeAndResolveDefaultUrlConfig # :nodoc:
      def initialize(raw_configurations, url = ENV['DATABASE_URL'])
        @raw_config = raw_configurations.dup
        @url        = url
      end

      # Returns fully resolved connection hashes.
      # Merges connection information from `ENV['DATABASE_URL']` if available.
      def resolve
        ConnectionAdapters::ConnectionSpecification::Resolver.new(config).resolve_all
      end

      private
        def config
          if @url
            raw_merged_into_default
          else
            @raw_config
          end
        end

        def raw_merged_into_default
          default = default_url_hash

          @raw_config.each do |env, values|
            default[env] = values || {}
            default[env].merge!("url" => @url) { |h, v1, v2| v1 || v2 } if default[env].is_a?(Hash)
          end
          default
        end

        # When the raw configuration is not present and ENV['DATABASE_URL']
        # is available we return a hash with the connection information in
        # the connection URL. This hash responds to any string key with
        # resolved connection information.
        def default_url_hash
96 97 98 99 100
          Hash.new do |hash, key|
            hash[key] = if key.is_a? String
               ActiveRecord::ConnectionAdapters::ConnectionSpecification::ConnectionUrlResolver.new(@url).to_hash
            else
              nil
101 102 103 104 105
            end
          end
        end
    end

106 107 108 109 110 111 112 113
    # Returns the connection currently associated with the class. This can
    # also be used to "borrow" the connection to do database work unrelated
    # to any of the specific Active Records.
    def connection
      retrieve_connection
    end

    def connection_id
114
      ActiveRecord::RuntimeRegistry.connection_id
115 116 117
    end

    def connection_id=(connection_id)
118
      ActiveRecord::RuntimeRegistry.connection_id = connection_id
119 120 121 122 123
    end

    # Returns the configuration of the associated connection as a hash:
    #
    #  ActiveRecord::Base.connection_config
A
AvnerCohen 已提交
124
    #  # => {pool: 5, timeout: 5000, database: "db/development.sqlite3", adapter: "sqlite3"}
125 126 127 128 129 130 131 132 133 134 135 136 137 138
    #
    # Please use only for reading.
    def connection_config
      connection_pool.spec.config
    end

    def connection_pool
      connection_handler.retrieve_connection_pool(self) or raise ConnectionNotEstablished
    end

    def retrieve_connection
      connection_handler.retrieve_connection(self)
    end

139
    # Returns +true+ if Active Record is connected.
140 141 142 143 144 145 146 147
    def connected?
      connection_handler.connected?(self)
    end

    def remove_connection(klass = self)
      connection_handler.remove_connection(klass)
    end

J
Jon Leighton 已提交
148 149 150 151
    def clear_cache! # :nodoc:
      connection.schema_cache.clear!
    end

152
    delegate :clear_active_connections!, :clear_reloadable_connections!,
153
      :clear_all_connections!, :to => :connection_handler
154 155
  end
end