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.

Files changed (99) hide show
  1. data/CHANGELOG.md +6263 -103
  2. data/README.rdoc +2 -2
  3. data/examples/performance.rb +55 -31
  4. data/lib/active_record.rb +28 -2
  5. data/lib/active_record/aggregations.rb +2 -2
  6. data/lib/active_record/associations.rb +82 -69
  7. data/lib/active_record/associations/association.rb +2 -37
  8. data/lib/active_record/associations/association_scope.rb +3 -30
  9. data/lib/active_record/associations/builder/association.rb +6 -4
  10. data/lib/active_record/associations/builder/belongs_to.rb +3 -3
  11. data/lib/active_record/associations/builder/collection_association.rb +2 -2
  12. data/lib/active_record/associations/builder/has_many.rb +4 -4
  13. data/lib/active_record/associations/builder/has_one.rb +5 -6
  14. data/lib/active_record/associations/builder/singular_association.rb +3 -16
  15. data/lib/active_record/associations/collection_association.rb +55 -28
  16. data/lib/active_record/associations/collection_proxy.rb +1 -35
  17. data/lib/active_record/associations/has_many_association.rb +5 -1
  18. data/lib/active_record/associations/has_many_through_association.rb +11 -8
  19. data/lib/active_record/associations/join_dependency.rb +1 -1
  20. data/lib/active_record/associations/preloader/association.rb +3 -1
  21. data/lib/active_record/attribute_assignment.rb +221 -0
  22. data/lib/active_record/attribute_methods.rb +212 -32
  23. data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +32 -0
  24. data/lib/active_record/attribute_methods/dirty.rb +3 -3
  25. data/lib/active_record/attribute_methods/primary_key.rb +62 -25
  26. data/lib/active_record/attribute_methods/read.rb +69 -80
  27. data/lib/active_record/attribute_methods/serialization.rb +89 -0
  28. data/lib/active_record/attribute_methods/time_zone_conversion.rb +9 -14
  29. data/lib/active_record/attribute_methods/write.rb +27 -5
  30. data/lib/active_record/autosave_association.rb +23 -8
  31. data/lib/active_record/base.rb +223 -1712
  32. data/lib/active_record/connection_adapters/abstract/connection_pool.rb +98 -132
  33. data/lib/active_record/connection_adapters/abstract/connection_specification.rb +82 -29
  34. data/lib/active_record/connection_adapters/abstract/database_statements.rb +13 -42
  35. data/lib/active_record/connection_adapters/abstract/query_cache.rb +1 -1
  36. data/lib/active_record/connection_adapters/abstract/quoting.rb +7 -4
  37. data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +36 -25
  38. data/lib/active_record/connection_adapters/abstract/schema_statements.rb +41 -13
  39. data/lib/active_record/connection_adapters/abstract_adapter.rb +78 -43
  40. data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +653 -0
  41. data/lib/active_record/connection_adapters/mysql2_adapter.rb +138 -578
  42. data/lib/active_record/connection_adapters/mysql_adapter.rb +86 -658
  43. data/lib/active_record/connection_adapters/postgresql_adapter.rb +144 -94
  44. data/lib/active_record/connection_adapters/schema_cache.rb +50 -0
  45. data/lib/active_record/connection_adapters/sqlite3_adapter.rb +2 -6
  46. data/lib/active_record/connection_adapters/sqlite_adapter.rb +43 -22
  47. data/lib/active_record/counter_cache.rb +1 -1
  48. data/lib/active_record/dynamic_matchers.rb +79 -0
  49. data/lib/active_record/errors.rb +11 -1
  50. data/lib/active_record/explain.rb +83 -0
  51. data/lib/active_record/explain_subscriber.rb +21 -0
  52. data/lib/active_record/fixtures.rb +31 -76
  53. data/lib/active_record/fixtures/file.rb +65 -0
  54. data/lib/active_record/identity_map.rb +1 -7
  55. data/lib/active_record/inheritance.rb +167 -0
  56. data/lib/active_record/integration.rb +49 -0
  57. data/lib/active_record/locking/optimistic.rb +19 -11
  58. data/lib/active_record/locking/pessimistic.rb +1 -1
  59. data/lib/active_record/log_subscriber.rb +3 -3
  60. data/lib/active_record/migration.rb +38 -29
  61. data/lib/active_record/migration/command_recorder.rb +7 -7
  62. data/lib/active_record/model_schema.rb +362 -0
  63. data/lib/active_record/nested_attributes.rb +3 -2
  64. data/lib/active_record/persistence.rb +51 -1
  65. data/lib/active_record/querying.rb +58 -0
  66. data/lib/active_record/railtie.rb +24 -28
  67. data/lib/active_record/railties/controller_runtime.rb +3 -1
  68. data/lib/active_record/railties/databases.rake +133 -77
  69. data/lib/active_record/readonly_attributes.rb +26 -0
  70. data/lib/active_record/reflection.rb +7 -15
  71. data/lib/active_record/relation.rb +78 -35
  72. data/lib/active_record/relation/batches.rb +5 -2
  73. data/lib/active_record/relation/calculations.rb +27 -6
  74. data/lib/active_record/relation/delegation.rb +49 -0
  75. data/lib/active_record/relation/finder_methods.rb +5 -4
  76. data/lib/active_record/relation/predicate_builder.rb +13 -16
  77. data/lib/active_record/relation/query_methods.rb +59 -4
  78. data/lib/active_record/result.rb +1 -1
  79. data/lib/active_record/sanitization.rb +194 -0
  80. data/lib/active_record/schema_dumper.rb +5 -2
  81. data/lib/active_record/scoping.rb +152 -0
  82. data/lib/active_record/scoping/default.rb +140 -0
  83. data/lib/active_record/scoping/named.rb +202 -0
  84. data/lib/active_record/serialization.rb +1 -43
  85. data/lib/active_record/serializers/xml_serializer.rb +2 -44
  86. data/lib/active_record/session_store.rb +11 -11
  87. data/lib/active_record/store.rb +50 -0
  88. data/lib/active_record/test_case.rb +11 -7
  89. data/lib/active_record/timestamp.rb +16 -3
  90. data/lib/active_record/transactions.rb +5 -5
  91. data/lib/active_record/translation.rb +22 -0
  92. data/lib/active_record/validations.rb +1 -1
  93. data/lib/active_record/validations/associated.rb +5 -4
  94. data/lib/active_record/validations/uniqueness.rb +4 -4
  95. data/lib/active_record/version.rb +3 -3
  96. data/lib/rails/generators/active_record/session_migration/templates/migration.rb +1 -5
  97. metadata +48 -38
  98. checksums.yaml +0 -7
  99. 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/synchronization'
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
- # The mutex used to synchronize pool access
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
- @reserved_connections.key? current_connection_id
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. If no connection
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 @reserved_connections[connection_id]
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
- !@connections.empty?
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
- @reserved_connections.each do |name,conn|
198
- checkin conn
199
- end
200
- @reserved_connections = {}
201
- @connections.each do |conn|
202
- conn.disconnect!
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
- @reserved_connections.each do |name, conn|
210
- checkin conn
211
- end
212
- @reserved_connections = {}
213
- @connections.each do |conn|
214
- conn.disconnect! if conn.requires_reloading?
215
- end
216
- @connections.delete_if do |conn|
217
- conn.requires_reloading?
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
- clear_stale_cached_connections!
225
- @connections.each do |connection|
226
- connection.verify!
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
- checkin @reserved_connections[key]
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
- @connection_mutex.synchronize do
229
+ synchronize do
261
230
  loop do
262
- conn = if @checked_out.size < @connections.size
263
- checkout_existing_connection
264
- elsif @connections.size < @size
265
- checkout_new_connection
266
- end
267
- return conn if conn
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(@checked_out.size < @connections.size)
247
+ if(active_connections.size < @connections.size)
272
248
  next
273
249
  else
274
250
  clear_stale_cached_connections!
275
- if @size == @checked_out.size
276
- raise ConnectionTimeoutError, "could not obtain a database connection#{" within #{@timeout} seconds" if @timeout}. The max pool size is currently #{@size}; consider increasing it."
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
- @connection_mutex.synchronize do
266
+ synchronize do
291
267
  conn.run_callbacks :checkin do
292
- @checked_out.delete conn
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
- connection = ActiveRecord::Base.send(spec.adapter_method, spec.config)
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
- checkout_and_verify(c)
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[name] = ConnectionAdapters::ConnectionPool.new(spec)
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 = @connection_pools.delete(klass.name)
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 = @connection_pools[klass.name]
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 = nil)
52
- case spec
53
- when nil
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
- begin
69
- require "active_record/connection_adapters/#{spec[:adapter]}_adapter"
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