active_record_shards 3.0.0.beta1 → 3.0.0.beta2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,515 +0,0 @@
1
- require_relative 'helper'
2
-
3
- describe "connection switching" do
4
- i_suck_and_my_tests_are_order_dependent!
5
-
6
- describe "shard switching" do
7
- it "only switch connection on sharded models" do
8
- assert_using_database('ars_test', Ticket)
9
- assert_using_database('ars_test', Account)
10
-
11
- ActiveRecord::Base.on_shard(0) do
12
- assert_using_database('ars_test_shard0', Ticket)
13
- assert_using_database('ars_test', Account)
14
- end
15
- end
16
-
17
- it "switch to shard and back" do
18
- assert_using_database('ars_test')
19
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_slave') }
20
-
21
- ActiveRecord::Base.on_shard(0) do
22
- assert_using_database('ars_test_shard0')
23
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_shard0_slave') }
24
-
25
- ActiveRecord::Base.on_shard(nil) do
26
- assert_using_database('ars_test')
27
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_slave') }
28
- end
29
-
30
- assert_using_database('ars_test_shard0')
31
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_shard0_slave') }
32
- end
33
-
34
- assert_using_database('ars_test')
35
- ActiveRecord::Base.on_slave { assert_using_database('ars_test_slave') }
36
- end
37
-
38
- describe "on_first_shard" do
39
- it "use the first shard" do
40
- ActiveRecord::Base.on_first_shard {
41
- assert_using_database('ars_test_shard0')
42
- }
43
- end
44
- end
45
-
46
- describe "on_all_shards" do
47
- before do
48
- @shard_0_master = ActiveRecord::Base.on_shard(0) {ActiveRecord::Base.connection}
49
- @shard_1_master = ActiveRecord::Base.on_shard(1) {ActiveRecord::Base.connection}
50
- refute_equal(@shard_0_master.select_value("SELECT DATABASE()"), @shard_1_master.select_value("SELECT DATABASE()"))
51
- end
52
-
53
- it "execute the block on all shard masters" do
54
- result = ActiveRecord::Base.on_all_shards do |shard|
55
- [ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
56
- end
57
- database_names = result.map(&:first)
58
- database_shards = result.map(&:last)
59
-
60
- assert_equal(2, database_names.size)
61
- assert_includes(database_names, @shard_0_master.select_value("SELECT DATABASE()"))
62
- assert_includes(database_names, @shard_1_master.select_value("SELECT DATABASE()"))
63
-
64
- assert_equal(2, database_shards.size)
65
- assert_includes(database_shards, "0")
66
- assert_includes(database_shards, "1")
67
- end
68
-
69
- it "execute the block unsharded" do
70
- ActiveRecord::Base.expects(:supports_sharding?).returns false
71
- result = ActiveRecord::Base.on_all_shards do |shard|
72
- [ActiveRecord::Base.connection.select_value("SELECT DATABASE()"), shard]
73
- end
74
- assert_equal [["ars_test", nil]], result
75
- end
76
- end
77
- end
78
-
79
- describe "default shard selection" do
80
- describe "of nil" do
81
- before do
82
- ActiveRecord::Base.default_shard = nil
83
- end
84
-
85
- it "use unsharded db for sharded models" do
86
- assert_using_database('ars_test', Ticket)
87
- assert_using_database('ars_test', Account)
88
- end
89
- end
90
-
91
- describe "value" do
92
- before do
93
- ActiveRecord::Base.default_shard = 0
94
- end
95
-
96
- after do
97
- ActiveRecord::Base.default_shard = nil
98
- end
99
-
100
- it "use default shard db for sharded models" do
101
- assert_using_database('ars_test_shard0', Ticket)
102
- assert_using_database('ars_test', Account)
103
- end
104
-
105
- it "still be able to switch to shard nil" do
106
- ActiveRecord::Base.on_shard(nil) do
107
- assert_using_database('ars_test', Ticket)
108
- assert_using_database('ars_test', Account)
109
- end
110
- end
111
- end
112
- end
113
-
114
- describe "ActiveRecord::Base.columns" do
115
- before do
116
- ActiveRecord::Base.default_shard = nil
117
- end
118
-
119
- describe "for unsharded models" do
120
- it "use the non-sharded connection" do
121
- assert_using_database('ars_test', Account)
122
- Account.connection.execute("alter table accounts add column foo int")
123
-
124
- assert Account.column_names.include?('foo')
125
- end
126
-
127
- after do
128
- ActiveRecord::Base.connection.execute("alter table accounts drop column foo")
129
- Account.reset_column_information
130
- end
131
- end
132
-
133
- describe "for sharded models" do
134
- before do
135
- ActiveRecord::Base.on_first_shard do
136
- ActiveRecord::Base.connection.execute("alter table tickets add column foo int")
137
- end
138
- end
139
-
140
- after do
141
- ActiveRecord::Base.on_first_shard do
142
- ActiveRecord::Base.connection.execute("alter table tickets drop column foo")
143
- Ticket.reset_column_information
144
- end
145
- end
146
-
147
- it "get colmns from the first shard" do
148
- assert Ticket.column_names.include?('foo')
149
- end
150
-
151
- it "have correct from_shard" do
152
- ActiveRecord::Base.on_all_shards do |shard|
153
- assert_equal shard, Ticket.new.from_shard
154
- end
155
- end
156
- end
157
- end
158
-
159
- describe "ActiveRecord::Base.table_exists?" do
160
- before do
161
- ActiveRecord::Base.default_shard = nil
162
- end
163
-
164
- describe "for unsharded models" do
165
- it "use the unsharded connection" do
166
- class UnshardedModel < ActiveRecord::Base
167
- not_sharded
168
- end
169
- UnshardedModel.connection.execute("create table unsharded_models (id int)")
170
- assert(UnshardedModel.table_exists?)
171
-
172
- ActiveRecord::Base.on_all_shards do
173
- assert !ActiveRecord::Base.connection.table_exists?("unsharded_models")
174
- end
175
- end
176
- end
177
-
178
- describe "for sharded models" do
179
- it "try the first shard" do
180
- class ShardedModel < ActiveRecord::Base
181
- end
182
-
183
- ActiveRecord::Base.on_first_shard do
184
- ShardedModel.connection.execute("create table sharded_models (id int)")
185
- end
186
-
187
- assert ShardedModel.table_exists?
188
- end
189
- end
190
- end
191
-
192
- describe "in an unsharded environment" do
193
- before do
194
- silence_warnings { ::RAILS_ENV = 'test2' }
195
- ActiveRecord::Base.establish_connection(::RAILS_ENV)
196
- assert_using_database('ars_test2', Ticket)
197
- end
198
-
199
- after do
200
- silence_warnings { ::RAILS_ENV = 'test' }
201
- ActiveRecord::Base.establish_connection(::RAILS_ENV)
202
- assert_using_database('ars_test', Ticket)
203
- end
204
-
205
- if ActiveRecord::VERSION::MAJOR >= 3
206
- it "be able to find by column" do
207
- Account.where(:name => "peter").to_sql # does not blow up
208
- end
209
-
210
- it "have correct engine" do
211
- assert_equal Account, Account.arel_engine
212
- end
213
- end
214
-
215
- describe "shard switching" do
216
- it "just stay on the main db" do
217
- assert_using_database('ars_test2', Ticket)
218
- assert_using_database('ars_test2', Account)
219
-
220
- ActiveRecord::Base.on_shard(0) do
221
- assert_using_database('ars_test2', Ticket)
222
- assert_using_database('ars_test2', Account)
223
- end
224
- end
225
- end
226
-
227
- describe "on_all_shards" do
228
- before do
229
- @database_names = []
230
- ActiveRecord::Base.on_all_shards do
231
- @database_names << ActiveRecord::Base.connection.select_value("SELECT DATABASE()")
232
- end
233
- end
234
-
235
- it "execute the block on all shard masters" do
236
- assert_equal([ActiveRecord::Base.connection.select_value("SELECT DATABASE()")], @database_names)
237
- end
238
- end
239
- end
240
-
241
- describe "slave driving" do
242
- describe "without slave configuration" do
243
-
244
- before do
245
- ActiveRecord::Base.configurations.delete('test_slave')
246
- if ActiveRecord::VERSION::MAJOR == 4
247
- ActiveRecord::Base.connection_handler.connection_pool_list.clear
248
- else
249
- ActiveRecord::Base.connection_handler.connection_pools.clear
250
- end
251
- ActiveRecord::Base.establish_connection('test')
252
- end
253
-
254
- it "default to the master database" do
255
- Account.create!
256
-
257
- ActiveRecord::Base.on_slave { assert_using_master_db }
258
- Account.on_slave { assert_using_master_db }
259
- Ticket.on_slave { assert_using_master_db }
260
- end
261
-
262
- it "successfully execute queries" do
263
- Account.create!
264
- assert_using_master_db
265
-
266
- assert_equal Account.count, ActiveRecord::Base.on_slave { Account.count }
267
- assert_equal Account.count, Account.on_slave { Account.count }
268
- end
269
-
270
- end
271
-
272
- describe "with slave configuration" do
273
-
274
- it "successfully execute queries" do
275
- assert_using_master_db
276
- Account.create!
277
-
278
- assert_equal(1, Account.count)
279
- assert_equal(0, ActiveRecord::Base.on_slave { Account.count })
280
- end
281
-
282
- it "support global on_slave blocks" do
283
- assert_using_master_db
284
- assert_using_master_db
285
-
286
- ActiveRecord::Base.on_slave do
287
- assert_using_slave_db
288
- assert_using_slave_db
289
- end
290
-
291
- assert_using_master_db
292
- assert_using_master_db
293
- end
294
-
295
- it "support conditional methods" do
296
- assert_using_master_db
297
-
298
- Account.on_slave_if(true) do
299
- assert_using_slave_db
300
- end
301
-
302
- assert_using_master_db
303
-
304
- Account.on_slave_if(false) do
305
- assert_using_master_db
306
- end
307
-
308
- Account.on_slave_unless(true) do
309
- assert_using_master_db
310
- end
311
-
312
- Account.on_slave_unless(false) do
313
- assert_using_slave_db
314
- end
315
- end
316
-
317
- describe "a model loaded with the slave" do
318
- before do
319
- Account.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'master_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
320
- assert(Account.find(1000))
321
- assert_equal('master_name', Account.find(1000).name)
322
-
323
- Account.on_slave.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'slave_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
324
-
325
- @model = Account.on_slave.find(1000)
326
- assert(@model)
327
- assert_equal('slave_name', @model.name)
328
- end
329
-
330
- it "read from master on reload" do
331
- @model.reload
332
- assert_equal('master_name', @model.name)
333
- end
334
-
335
- it "be marked as read only" do
336
- assert(@model.readonly?)
337
- end
338
-
339
- it "be marked as comming from the slave" do
340
- assert(@model.from_slave?)
341
- end
342
- end
343
-
344
- describe "a inherited model without cached columns hash" do
345
- # before columns -> with_scope -> type-condition -> columns == loop
346
- it "not loop when on slave by default" do
347
- Person.on_slave_by_default = true
348
- assert User.on_slave_by_default?
349
- assert User.finder_needs_type_condition?
350
-
351
- User.instance_variable_set(:@columns_hash, nil)
352
- User.columns_hash
353
- end
354
- end
355
-
356
- describe "a model loaded with the master" do
357
- before do
358
- Account.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'master_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
359
- @model = Account.first
360
- assert(@model)
361
- assert_equal('master_name', @model.name)
362
- end
363
-
364
- # TODO mocha raises stack level too deep on ActiveRecord 3.2+
365
- if ActiveRecord::VERSION::STRING < "3.2.0"
366
- it "not unnecessary call with_scope" do
367
- Account.expects(:with_scope).never
368
- Account.on_master.first
369
- end
370
- end
371
-
372
- it "not unset readonly" do
373
- @model = Account.on_master.scoped(:readonly => true).first
374
- assert(@model.readonly?)
375
- end
376
-
377
- it "not be marked as read only" do
378
- assert(!@model.readonly?)
379
- end
380
-
381
- it "not be marked as comming from the slave" do
382
- assert(!@model.from_slave?)
383
- end
384
- end
385
-
386
- # TODO: make all this stuff rails 3 compatible.
387
- describe "with finds routed to the slave by default" do
388
- before do
389
- Account.on_slave_by_default = true
390
- Account.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'master_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
391
- Account.on_slave.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1000, 'slave_name', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
392
- Account.on_slave.connection.execute("INSERT INTO accounts (id, name, created_at, updated_at) VALUES(1001, 'slave_name2', '2009-12-04 20:18:48', '2009-12-04 20:18:48')")
393
- end
394
-
395
- it "find() by default on the slave" do
396
- account = Account.find(1000)
397
- assert_equal 'slave_name', account.name
398
- end
399
-
400
- it "count() by default on the slave" do
401
- count = Account.all.size
402
- assert_equal 2, count
403
- end
404
-
405
- it "reload() on the master" do
406
- account = Account.find(1000)
407
- assert_equal 'master_name', account.reload.name
408
- end
409
-
410
- it "do exists? on the slave" do
411
- if Account.respond_to?(:exists?)
412
- assert Account.exists?(1001)
413
- end
414
- end
415
-
416
- it "does exists? on the slave with a named scope" do
417
- AccountThing.on_slave_by_default = true
418
- Account.on_slave.connection.execute("INSERT INTO account_things (id, account_id) VALUES(123125, 1000)")
419
- assert AccountThing.enabled.exists?(123125)
420
- Account.on_slave.connection.execute("DELETE FROM account_things")
421
- AccountThing.on_slave_by_default = false
422
- end
423
-
424
- it "count associations on the slave" do
425
- AccountThing.on_slave_by_default = true
426
- Account.on_slave.connection.execute("INSERT INTO account_things (id, account_id) VALUES(123123, 1000)")
427
- Account.on_slave.connection.execute("INSERT INTO account_things (id, account_id) VALUES(123124, 1000)")
428
- assert_equal 2, Account.find(1000).account_things.size
429
- AccountThing.on_slave_by_default = false
430
- end
431
-
432
- it "Allow override using on_master" do
433
- model = Account.on_master.find(1000)
434
- assert_equal "master_name", model.name
435
- end
436
-
437
- it "not override on_master with on_slave" do
438
- model = Account.on_master { Account.on_slave.find(1000) }
439
- assert_equal "master_name", model.name
440
- end
441
-
442
- it "override on_slave with on_master" do
443
- model = Account.on_slave { Account.on_master.find(1000) }
444
- assert_equal "master_name", model.name
445
- end
446
-
447
- it "propogate the default_slave setting to inherited classes" do
448
- assert AccountInherited.on_slave_by_default?
449
- end
450
-
451
- after do
452
- Account.on_slave_by_default = false
453
- end
454
- end
455
- end
456
-
457
- describe "slave proxy" do
458
- it "successfully execute queries" do
459
- assert_using_master_db
460
- Account.create!
461
-
462
- refute_equal Account.count, Account.on_slave.count
463
- end
464
-
465
- it "work on association collections" do
466
- begin
467
- assert_using_master_db
468
- account = Account.create!
469
-
470
- account.tickets.create! :title => 'master ticket'
471
-
472
- Ticket.on_slave {
473
- account.tickets.create! :title => 'slave ticket'
474
- }
475
-
476
- assert_equal "master ticket", account.tickets.first.title
477
- assert_equal "slave ticket", account.tickets.on_slave.first.title
478
- rescue Exception
479
- retried ||= 0
480
- retried += 1
481
- puts "Failed in #{__LINE__}##{retried}"
482
- retry if retried < 3
483
- end
484
- end
485
- end
486
- end
487
-
488
- describe "alternative connections" do
489
- it "not interfere with other connections" do
490
- assert_using_database('ars_test', Account)
491
- assert_using_database('ars_test', Ticket)
492
- assert_using_database('ars_test_alternative', Email)
493
-
494
- ActiveRecord::Base.on_shard(0) do
495
- assert_using_database('ars_test', Account)
496
- assert_using_database('ars_test_shard0', Ticket)
497
- assert_using_database('ars_test_alternative', Email)
498
- end
499
-
500
- assert_using_database('ars_test', Account)
501
- assert_using_database('ars_test', Ticket)
502
- assert_using_database('ars_test_alternative', Email)
503
- end
504
- end
505
-
506
- it "raises an exception if a connection is not found" do
507
- ActiveRecord::Base.on_shard(0) do
508
- ActiveRecord::Base.connection_handler.remove_connection(Ticket)
509
- assert_raises(ActiveRecord::ConnectionNotEstablished) do
510
- ActiveRecord::Base.connection_handler.retrieve_connection_pool(Ticket)
511
- assert_using_database('ars_test_shard0', Ticket)
512
- end
513
- end
514
- end
515
- end