activerecord 3.1.12 → 3.2.0.rc1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG.md +6263 -103
- data/README.rdoc +2 -2
- data/examples/performance.rb +55 -31
- data/lib/active_record.rb +28 -2
- data/lib/active_record/aggregations.rb +2 -2
- data/lib/active_record/associations.rb +82 -69
- data/lib/active_record/associations/association.rb +2 -37
- data/lib/active_record/associations/association_scope.rb +3 -30
- data/lib/active_record/associations/builder/association.rb +6 -4
- data/lib/active_record/associations/builder/belongs_to.rb +3 -3
- data/lib/active_record/associations/builder/collection_association.rb +2 -2
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +5 -6
- data/lib/active_record/associations/builder/singular_association.rb +3 -16
- data/lib/active_record/associations/collection_association.rb +55 -28
- data/lib/active_record/associations/collection_proxy.rb +1 -35
- data/lib/active_record/associations/has_many_association.rb +5 -1
- data/lib/active_record/associations/has_many_through_association.rb +11 -8
- data/lib/active_record/associations/join_dependency.rb +1 -1
- data/lib/active_record/associations/preloader/association.rb +3 -1
- data/lib/active_record/attribute_assignment.rb +221 -0
- data/lib/active_record/attribute_methods.rb +212 -32
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
- data/lib/active_record/attribute_methods/dirty.rb +3 -3
- data/lib/active_record/attribute_methods/primary_key.rb +62 -25
- data/lib/active_record/attribute_methods/read.rb +69 -80
- data/lib/active_record/attribute_methods/serialization.rb +89 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +9 -14
- data/lib/active_record/attribute_methods/write.rb +27 -5
- data/lib/active_record/autosave_association.rb +23 -8
- data/lib/active_record/base.rb +223 -1712
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +98 -132
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +82 -29
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +13 -42
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/quoting.rb +7 -4
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +36 -25
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -13
- data/lib/active_record/connection_adapters/abstract_adapter.rb +78 -43
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +653 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +138 -578
- data/lib/active_record/connection_adapters/mysql_adapter.rb +86 -658
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +144 -94
- data/lib/active_record/connection_adapters/schema_cache.rb +50 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +43 -22
- data/lib/active_record/counter_cache.rb +1 -1
- data/lib/active_record/dynamic_matchers.rb +79 -0
- data/lib/active_record/errors.rb +11 -1
- data/lib/active_record/explain.rb +83 -0
- data/lib/active_record/explain_subscriber.rb +21 -0
- data/lib/active_record/fixtures.rb +31 -76
- data/lib/active_record/fixtures/file.rb +65 -0
- data/lib/active_record/identity_map.rb +1 -7
- data/lib/active_record/inheritance.rb +167 -0
- data/lib/active_record/integration.rb +49 -0
- data/lib/active_record/locking/optimistic.rb +19 -11
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +3 -3
- data/lib/active_record/migration.rb +38 -29
- data/lib/active_record/migration/command_recorder.rb +7 -7
- data/lib/active_record/model_schema.rb +362 -0
- data/lib/active_record/nested_attributes.rb +3 -2
- data/lib/active_record/persistence.rb +51 -1
- data/lib/active_record/querying.rb +58 -0
- data/lib/active_record/railtie.rb +24 -28
- data/lib/active_record/railties/controller_runtime.rb +3 -1
- data/lib/active_record/railties/databases.rake +133 -77
- data/lib/active_record/readonly_attributes.rb +26 -0
- data/lib/active_record/reflection.rb +7 -15
- data/lib/active_record/relation.rb +78 -35
- data/lib/active_record/relation/batches.rb +5 -2
- data/lib/active_record/relation/calculations.rb +27 -6
- data/lib/active_record/relation/delegation.rb +49 -0
- data/lib/active_record/relation/finder_methods.rb +5 -4
- data/lib/active_record/relation/predicate_builder.rb +13 -16
- data/lib/active_record/relation/query_methods.rb +59 -4
- data/lib/active_record/result.rb +1 -1
- data/lib/active_record/sanitization.rb +194 -0
- data/lib/active_record/schema_dumper.rb +5 -2
- data/lib/active_record/scoping.rb +152 -0
- data/lib/active_record/scoping/default.rb +140 -0
- data/lib/active_record/scoping/named.rb +202 -0
- data/lib/active_record/serialization.rb +1 -43
- data/lib/active_record/serializers/xml_serializer.rb +2 -44
- data/lib/active_record/session_store.rb +11 -11
- data/lib/active_record/store.rb +50 -0
- data/lib/active_record/test_case.rb +11 -7
- data/lib/active_record/timestamp.rb +16 -3
- data/lib/active_record/transactions.rb +5 -5
- data/lib/active_record/translation.rb +22 -0
- data/lib/active_record/validations.rb +1 -1
- data/lib/active_record/validations/associated.rb +5 -4
- data/lib/active_record/validations/uniqueness.rb +4 -4
- data/lib/active_record/version.rb +3 -3
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
- metadata +48 -38
- checksums.yaml +0 -7
- data/lib/active_record/named_scope.rb +0 -200
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'thread'
|
2
2
|
require 'monitor'
|
3
3
|
require 'set'
|
4
|
-
require 'active_support/core_ext/module/
|
4
|
+
require 'active_support/core_ext/module/deprecation'
|
5
5
|
|
6
6
|
module ActiveRecord
|
7
7
|
# Raised when a connection could not be obtained within the connection
|
@@ -57,10 +57,10 @@ module ActiveRecord
|
|
57
57
|
# * +wait_timeout+: number of seconds to block and wait for a connection
|
58
58
|
# before giving up and raising a timeout error (default 5 seconds).
|
59
59
|
class ConnectionPool
|
60
|
+
include MonitorMixin
|
61
|
+
|
60
62
|
attr_accessor :automatic_reconnect
|
61
63
|
attr_reader :spec, :connections
|
62
|
-
attr_reader :columns, :columns_hash, :primary_keys, :tables
|
63
|
-
attr_reader :column_defaults
|
64
64
|
|
65
65
|
# Creates a new ConnectionPool object. +spec+ is a ConnectionSpecification
|
66
66
|
# object which describes database connection information (e.g. adapter,
|
@@ -69,88 +69,21 @@ module ActiveRecord
|
|
69
69
|
#
|
70
70
|
# The default ConnectionPool maximum size is 5.
|
71
71
|
def initialize(spec)
|
72
|
+
super()
|
73
|
+
|
72
74
|
@spec = spec
|
73
75
|
|
74
76
|
# The cache of reserved connections mapped to threads
|
75
77
|
@reserved_connections = {}
|
76
78
|
|
77
|
-
|
78
|
-
@connection_mutex = Monitor.new
|
79
|
-
@queue = @connection_mutex.new_cond
|
79
|
+
@queue = new_cond
|
80
80
|
@timeout = spec.config[:wait_timeout] || 5
|
81
81
|
|
82
82
|
# default max pool size to 5
|
83
83
|
@size = (spec.config[:pool] && spec.config[:pool].to_i) || 5
|
84
84
|
|
85
85
|
@connections = []
|
86
|
-
@checked_out = []
|
87
86
|
@automatic_reconnect = true
|
88
|
-
@tables = {}
|
89
|
-
@visitor = nil
|
90
|
-
|
91
|
-
@columns = Hash.new do |h, table_name|
|
92
|
-
h[table_name] = with_connection do |conn|
|
93
|
-
|
94
|
-
# Fetch a list of columns
|
95
|
-
conn.columns(table_name, "#{table_name} Columns").tap do |columns|
|
96
|
-
|
97
|
-
# set primary key information
|
98
|
-
columns.each do |column|
|
99
|
-
column.primary = column.name == primary_keys[table_name]
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
|
105
|
-
@columns_hash = Hash.new do |h, table_name|
|
106
|
-
h[table_name] = Hash[columns[table_name].map { |col|
|
107
|
-
[col.name, col]
|
108
|
-
}]
|
109
|
-
end
|
110
|
-
|
111
|
-
@column_defaults = Hash.new do |h, table_name|
|
112
|
-
h[table_name] = Hash[columns[table_name].map { |col|
|
113
|
-
[col.name, col.default]
|
114
|
-
}]
|
115
|
-
end
|
116
|
-
|
117
|
-
@primary_keys = Hash.new do |h, table_name|
|
118
|
-
h[table_name] = with_connection do |conn|
|
119
|
-
table_exists?(table_name) ? conn.primary_key(table_name) : 'id'
|
120
|
-
end
|
121
|
-
end
|
122
|
-
end
|
123
|
-
|
124
|
-
# A cached lookup for table existence.
|
125
|
-
def table_exists?(name)
|
126
|
-
return true if @tables.key? name
|
127
|
-
|
128
|
-
with_connection do |conn|
|
129
|
-
conn.tables.each { |table| @tables[table] = true }
|
130
|
-
@tables[name] = true if !@tables.key?(name) && conn.table_exists?(name)
|
131
|
-
end
|
132
|
-
|
133
|
-
@tables.key? name
|
134
|
-
end
|
135
|
-
|
136
|
-
# Clears out internal caches:
|
137
|
-
#
|
138
|
-
# * columns
|
139
|
-
# * columns_hash
|
140
|
-
# * tables
|
141
|
-
def clear_cache!
|
142
|
-
@columns.clear
|
143
|
-
@columns_hash.clear
|
144
|
-
@column_defaults.clear
|
145
|
-
@tables.clear
|
146
|
-
end
|
147
|
-
|
148
|
-
# Clear out internal caches for table with +table_name+.
|
149
|
-
def clear_table_cache!(table_name)
|
150
|
-
@columns.delete table_name
|
151
|
-
@columns_hash.delete table_name
|
152
|
-
@column_defaults.delete table_name
|
153
|
-
@primary_keys.delete table_name
|
154
87
|
end
|
155
88
|
|
156
89
|
# Retrieve the connection associated with the current thread, or call
|
@@ -165,7 +98,7 @@ module ActiveRecord
|
|
165
98
|
# Check to see if there is an active connection in this connection
|
166
99
|
# pool.
|
167
100
|
def active_connection?
|
168
|
-
|
101
|
+
active_connections.any?
|
169
102
|
end
|
170
103
|
|
171
104
|
# Signal that the thread is finished with the current connection.
|
@@ -176,12 +109,12 @@ module ActiveRecord
|
|
176
109
|
checkin conn if conn
|
177
110
|
end
|
178
111
|
|
179
|
-
# If a connection already exists yield it to the block.
|
112
|
+
# If a connection already exists yield it to the block. If no connection
|
180
113
|
# exists checkout a connection, yield it to the block, and checkin the
|
181
114
|
# connection when finished.
|
182
115
|
def with_connection
|
183
116
|
connection_id = current_connection_id
|
184
|
-
fresh_connection = true unless
|
117
|
+
fresh_connection = true unless active_connection?
|
185
118
|
yield connection
|
186
119
|
ensure
|
187
120
|
release_connection(connection_id) if fresh_connection
|
@@ -189,43 +122,73 @@ module ActiveRecord
|
|
189
122
|
|
190
123
|
# Returns true if a connection has already been opened.
|
191
124
|
def connected?
|
192
|
-
|
125
|
+
synchronize { @connections.any? }
|
193
126
|
end
|
194
127
|
|
195
128
|
# Disconnects all connections in the pool, and clears the pool.
|
196
129
|
def disconnect!
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
130
|
+
synchronize do
|
131
|
+
@reserved_connections = {}
|
132
|
+
@connections.each do |conn|
|
133
|
+
checkin conn
|
134
|
+
conn.disconnect!
|
135
|
+
end
|
136
|
+
@connections = []
|
203
137
|
end
|
204
|
-
@connections = []
|
205
138
|
end
|
206
139
|
|
207
140
|
# Clears the cache which maps classes.
|
208
141
|
def clear_reloadable_connections!
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
142
|
+
synchronize do
|
143
|
+
@reserved_connections = {}
|
144
|
+
@connections.each do |conn|
|
145
|
+
checkin conn
|
146
|
+
conn.disconnect! if conn.requires_reloading?
|
147
|
+
end
|
148
|
+
@connections.delete_if do |conn|
|
149
|
+
conn.requires_reloading?
|
150
|
+
end
|
218
151
|
end
|
219
152
|
end
|
220
153
|
|
221
154
|
# Verify active connections and remove and disconnect connections
|
222
155
|
# associated with stale threads.
|
223
156
|
def verify_active_connections! #:nodoc:
|
224
|
-
|
225
|
-
|
226
|
-
connection
|
157
|
+
synchronize do
|
158
|
+
clear_stale_cached_connections!
|
159
|
+
@connections.each do |connection|
|
160
|
+
connection.verify!
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def columns
|
166
|
+
with_connection do |c|
|
167
|
+
c.schema_cache.columns
|
168
|
+
end
|
169
|
+
end
|
170
|
+
deprecate :columns
|
171
|
+
|
172
|
+
def columns_hash
|
173
|
+
with_connection do |c|
|
174
|
+
c.schema_cache.columns_hash
|
175
|
+
end
|
176
|
+
end
|
177
|
+
deprecate :columns_hash
|
178
|
+
|
179
|
+
def primary_keys
|
180
|
+
with_connection do |c|
|
181
|
+
c.schema_cache.primary_keys
|
182
|
+
end
|
183
|
+
end
|
184
|
+
deprecate :primary_keys
|
185
|
+
|
186
|
+
def clear_cache!
|
187
|
+
with_connection do |c|
|
188
|
+
c.schema_cache.clear!
|
227
189
|
end
|
228
190
|
end
|
191
|
+
deprecate :clear_cache!
|
229
192
|
|
230
193
|
# Return any checked-out connections back to the pool by threads that
|
231
194
|
# are no longer alive.
|
@@ -234,7 +197,13 @@ module ActiveRecord
|
|
234
197
|
t.alive?
|
235
198
|
}.map { |thread| thread.object_id }
|
236
199
|
keys.each do |key|
|
237
|
-
|
200
|
+
conn = @reserved_connections[key]
|
201
|
+
ActiveSupport::Deprecation.warn(<<-eowarn) if conn.in_use?
|
202
|
+
Database connections will not be closed automatically, please close your
|
203
|
+
database connection at the end of the thread by calling `close` on your
|
204
|
+
connection. For example: ActiveRecord::Base.connection.close
|
205
|
+
eowarn
|
206
|
+
checkin conn
|
238
207
|
@reserved_connections.delete(key)
|
239
208
|
end
|
240
209
|
end
|
@@ -257,23 +226,30 @@ module ActiveRecord
|
|
257
226
|
# within the timeout period.
|
258
227
|
def checkout
|
259
228
|
# Checkout an available connection
|
260
|
-
|
229
|
+
synchronize do
|
261
230
|
loop do
|
262
|
-
conn =
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
231
|
+
conn = @connections.find { |c| c.lease }
|
232
|
+
|
233
|
+
unless conn
|
234
|
+
if @connections.size < @size
|
235
|
+
conn = checkout_new_connection
|
236
|
+
conn.lease
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
if conn
|
241
|
+
checkout_and_verify conn
|
242
|
+
return conn
|
243
|
+
end
|
268
244
|
|
269
245
|
@queue.wait(@timeout)
|
270
246
|
|
271
|
-
if(
|
247
|
+
if(active_connections.size < @connections.size)
|
272
248
|
next
|
273
249
|
else
|
274
250
|
clear_stale_cached_connections!
|
275
|
-
if @size ==
|
276
|
-
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}.
|
251
|
+
if @size == active_connections.size
|
252
|
+
raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
|
277
253
|
end
|
278
254
|
end
|
279
255
|
|
@@ -287,30 +263,18 @@ module ActiveRecord
|
|
287
263
|
# +conn+: an AbstractAdapter object, which was obtained by earlier by
|
288
264
|
# calling +checkout+ on this pool.
|
289
265
|
def checkin(conn)
|
290
|
-
|
266
|
+
synchronize do
|
291
267
|
conn.run_callbacks :checkin do
|
292
|
-
|
268
|
+
conn.expire
|
293
269
|
@queue.signal
|
294
270
|
end
|
295
271
|
end
|
296
272
|
end
|
297
273
|
|
298
|
-
synchronize :clear_reloadable_connections!, :verify_active_connections!,
|
299
|
-
:connected?, :disconnect!, :with => :@connection_mutex
|
300
|
-
|
301
274
|
private
|
302
275
|
|
303
276
|
def new_connection
|
304
|
-
|
305
|
-
|
306
|
-
# TODO: This is a bit icky, and in the long term we may want to change the method
|
307
|
-
# signature for connections. Also, if we switch to have one visitor per
|
308
|
-
# connection (and therefore per thread), we can get rid of the thread-local
|
309
|
-
# variable in Arel::Visitors::ToSql.
|
310
|
-
@visitor ||= connection.class.visitor_for(self)
|
311
|
-
connection.visitor = @visitor
|
312
|
-
|
313
|
-
connection
|
277
|
+
ActiveRecord::Base.send(spec.adapter_method, spec.config)
|
314
278
|
end
|
315
279
|
|
316
280
|
def current_connection_id #:nodoc:
|
@@ -321,22 +285,21 @@ module ActiveRecord
|
|
321
285
|
raise ConnectionNotEstablished unless @automatic_reconnect
|
322
286
|
|
323
287
|
c = new_connection
|
288
|
+
c.pool = self
|
324
289
|
@connections << c
|
325
|
-
|
326
|
-
end
|
327
|
-
|
328
|
-
def checkout_existing_connection
|
329
|
-
c = (@connections - @checked_out).first
|
330
|
-
checkout_and_verify(c)
|
290
|
+
c
|
331
291
|
end
|
332
292
|
|
333
293
|
def checkout_and_verify(c)
|
334
294
|
c.run_callbacks :checkout do
|
335
295
|
c.verify!
|
336
|
-
@checked_out << c
|
337
296
|
end
|
338
297
|
c
|
339
298
|
end
|
299
|
+
|
300
|
+
def active_connections
|
301
|
+
@connections.find_all { |c| c.in_use? }
|
302
|
+
end
|
340
303
|
end
|
341
304
|
|
342
305
|
# ConnectionHandler is a collection of ConnectionPool objects. It is used
|
@@ -367,10 +330,12 @@ module ActiveRecord
|
|
367
330
|
|
368
331
|
def initialize(pools = {})
|
369
332
|
@connection_pools = pools
|
333
|
+
@class_to_pool = {}
|
370
334
|
end
|
371
335
|
|
372
336
|
def establish_connection(name, spec)
|
373
|
-
@connection_pools[
|
337
|
+
@connection_pools[spec] ||= ConnectionAdapters::ConnectionPool.new(spec)
|
338
|
+
@class_to_pool[name] = @connection_pools[spec]
|
374
339
|
end
|
375
340
|
|
376
341
|
# Returns true if there are any active connections among the connection
|
@@ -421,16 +386,17 @@ module ActiveRecord
|
|
421
386
|
# can be used as an argument for establish_connection, for easily
|
422
387
|
# re-establishing the connection.
|
423
388
|
def remove_connection(klass)
|
424
|
-
pool = @
|
389
|
+
pool = @class_to_pool.delete(klass.name)
|
425
390
|
return nil unless pool
|
426
391
|
|
392
|
+
@connection_pools.delete pool.spec
|
427
393
|
pool.automatic_reconnect = false
|
428
394
|
pool.disconnect!
|
429
395
|
pool.spec.config
|
430
396
|
end
|
431
397
|
|
432
398
|
def retrieve_connection_pool(klass)
|
433
|
-
pool = @
|
399
|
+
pool = @class_to_pool[klass.name]
|
434
400
|
return pool if pool
|
435
401
|
return nil if ActiveRecord::Base == klass
|
436
402
|
retrieve_connection_pool klass.superclass
|
@@ -5,6 +5,74 @@ module ActiveRecord
|
|
5
5
|
def initialize (config, adapter_method)
|
6
6
|
@config, @adapter_method = config, adapter_method
|
7
7
|
end
|
8
|
+
|
9
|
+
##
|
10
|
+
# Builds a ConnectionSpecification from user input
|
11
|
+
class Resolver # :nodoc:
|
12
|
+
attr_reader :config, :klass, :configurations
|
13
|
+
|
14
|
+
def initialize(config, configurations)
|
15
|
+
@config = config
|
16
|
+
@configurations = configurations
|
17
|
+
end
|
18
|
+
|
19
|
+
def spec
|
20
|
+
case config
|
21
|
+
when nil
|
22
|
+
raise AdapterNotSpecified unless defined?(Rails.env)
|
23
|
+
resolve_string_connection Rails.env
|
24
|
+
when Symbol, String
|
25
|
+
resolve_string_connection config.to_s
|
26
|
+
when Hash
|
27
|
+
resolve_hash_connection config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
def resolve_string_connection(spec) # :nodoc:
|
33
|
+
hash = configurations.fetch(spec) do |k|
|
34
|
+
connection_url_to_hash(k)
|
35
|
+
end
|
36
|
+
|
37
|
+
raise(AdapterNotSpecified, "#{spec} database is not configured") unless hash
|
38
|
+
|
39
|
+
resolve_hash_connection hash
|
40
|
+
end
|
41
|
+
|
42
|
+
def resolve_hash_connection(spec) # :nodoc:
|
43
|
+
spec = spec.symbolize_keys
|
44
|
+
|
45
|
+
raise(AdapterNotSpecified, "database configuration does not specify adapter") unless spec.key?(:adapter)
|
46
|
+
|
47
|
+
begin
|
48
|
+
require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
|
49
|
+
rescue LoadError => e
|
50
|
+
raise LoadError, "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e.message})", e.backtrace
|
51
|
+
end
|
52
|
+
|
53
|
+
adapter_method = "#{spec[:adapter]}_connection"
|
54
|
+
|
55
|
+
ConnectionSpecification.new(spec, adapter_method)
|
56
|
+
end
|
57
|
+
|
58
|
+
def connection_url_to_hash(url) # :nodoc:
|
59
|
+
config = URI.parse url
|
60
|
+
adapter = config.scheme
|
61
|
+
adapter = "postgresql" if adapter == "postgres"
|
62
|
+
spec = { :adapter => adapter,
|
63
|
+
:username => config.user,
|
64
|
+
:password => config.password,
|
65
|
+
:port => config.port,
|
66
|
+
:database => config.path.sub(%r{^/},""),
|
67
|
+
:host => config.host }
|
68
|
+
spec.reject!{ |_,value| !value }
|
69
|
+
if config.query
|
70
|
+
options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys
|
71
|
+
spec.merge!(options)
|
72
|
+
end
|
73
|
+
spec
|
74
|
+
end
|
75
|
+
end
|
8
76
|
end
|
9
77
|
|
10
78
|
##
|
@@ -46,39 +114,24 @@ module ActiveRecord
|
|
46
114
|
# "database" => "path/to/dbfile"
|
47
115
|
# )
|
48
116
|
#
|
117
|
+
# Or a URL:
|
118
|
+
#
|
119
|
+
# ActiveRecord::Base.establish_connection(
|
120
|
+
# "postgres://myuser:mypass@localhost/somedatabase"
|
121
|
+
# )
|
122
|
+
#
|
49
123
|
# The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError
|
50
124
|
# may be returned on an error.
|
51
|
-
def self.establish_connection(spec =
|
52
|
-
|
53
|
-
|
54
|
-
raise AdapterNotSpecified unless defined?(Rails.env)
|
55
|
-
establish_connection(Rails.env)
|
56
|
-
when ConnectionSpecification
|
57
|
-
self.connection_handler.establish_connection(name, spec)
|
58
|
-
when Symbol, String
|
59
|
-
if configuration = configurations[spec.to_s]
|
60
|
-
establish_connection(configuration)
|
61
|
-
else
|
62
|
-
raise AdapterNotSpecified, "#{spec} database is not configured"
|
63
|
-
end
|
64
|
-
else
|
65
|
-
spec = spec.symbolize_keys
|
66
|
-
unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
|
125
|
+
def self.establish_connection(spec = ENV["DATABASE_URL"])
|
126
|
+
resolver = ConnectionSpecification::Resolver.new spec, configurations
|
127
|
+
spec = resolver.spec
|
67
128
|
|
68
|
-
|
69
|
-
|
70
|
-
rescue LoadError => e
|
71
|
-
raise "Please install the #{spec[:adapter]} adapter: `gem install activerecord-#{spec[:adapter]}-adapter` (#{e})"
|
72
|
-
end
|
73
|
-
|
74
|
-
adapter_method = "#{spec[:adapter]}_connection"
|
75
|
-
unless respond_to?(adapter_method)
|
76
|
-
raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter"
|
77
|
-
end
|
78
|
-
|
79
|
-
remove_connection
|
80
|
-
establish_connection(ConnectionSpecification.new(spec, adapter_method))
|
129
|
+
unless respond_to?(spec.adapter_method)
|
130
|
+
raise AdapterNotFound, "database configuration specifies nonexistent #{spec.config[:adapter]} adapter"
|
81
131
|
end
|
132
|
+
|
133
|
+
remove_connection
|
134
|
+
connection_handler.establish_connection name, spec
|
82
135
|
end
|
83
136
|
|
84
137
|
class << self
|