ar-octopus 0.8.1 → 0.10.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +6 -14
  2. data/.gitignore +1 -0
  3. data/.rspec +1 -1
  4. data/.rubocop.yml +46 -0
  5. data/.rubocop_todo.yml +56 -0
  6. data/.travis.yml +7 -12
  7. data/Appraisals +11 -4
  8. data/Gemfile +1 -1
  9. data/README.mkdn +138 -63
  10. data/Rakefile +23 -16
  11. data/ar-octopus.gemspec +23 -20
  12. data/gemfiles/rails42.gemfile +7 -0
  13. data/gemfiles/{rails32.gemfile → rails5.gemfile} +2 -2
  14. data/gemfiles/{rails4.gemfile → rails51.gemfile} +2 -2
  15. data/gemfiles/rails52.gemfile +7 -0
  16. data/lib/ar-octopus.rb +1 -1
  17. data/lib/octopus/{rails3/abstract_adapter.rb → abstract_adapter.rb} +4 -15
  18. data/lib/octopus/association.rb +8 -99
  19. data/lib/octopus/association_shard_tracking.rb +74 -0
  20. data/lib/octopus/collection_association.rb +17 -0
  21. data/lib/octopus/collection_proxy.rb +16 -0
  22. data/lib/octopus/exception.rb +4 -0
  23. data/lib/octopus/finder_methods.rb +8 -0
  24. data/lib/octopus/load_balancing/round_robin.rb +20 -0
  25. data/lib/octopus/load_balancing.rb +4 -0
  26. data/lib/octopus/{rails3/log_subscriber.rb → log_subscriber.rb} +6 -2
  27. data/lib/octopus/migration.rb +187 -110
  28. data/lib/octopus/model.rb +151 -131
  29. data/lib/octopus/persistence.rb +45 -0
  30. data/lib/octopus/proxy.rb +297 -232
  31. data/lib/octopus/proxy_config.rb +251 -0
  32. data/lib/octopus/query_cache_for_shards.rb +24 -0
  33. data/lib/octopus/railtie.rb +1 -3
  34. data/lib/octopus/relation_proxy.rb +70 -0
  35. data/lib/octopus/result_patch.rb +19 -0
  36. data/lib/octopus/scope_proxy.rb +54 -36
  37. data/lib/octopus/shard_tracking/attribute.rb +22 -0
  38. data/lib/octopus/shard_tracking/dynamic.rb +11 -0
  39. data/lib/octopus/shard_tracking.rb +46 -0
  40. data/lib/octopus/singular_association.rb +9 -0
  41. data/lib/octopus/slave_group.rb +13 -0
  42. data/lib/octopus/version.rb +1 -1
  43. data/lib/octopus.rb +125 -33
  44. data/lib/tasks/octopus.rake +2 -2
  45. data/sample_app/Gemfile +3 -3
  46. data/sample_app/autotest/discover.rb +2 -2
  47. data/sample_app/config/application.rb +1 -1
  48. data/sample_app/config/boot.rb +1 -1
  49. data/sample_app/config/environments/test.rb +1 -1
  50. data/sample_app/config/initializers/session_store.rb +1 -1
  51. data/sample_app/config/initializers/wrap_parameters.rb +1 -1
  52. data/sample_app/config/routes.rb +1 -1
  53. data/sample_app/db/migrate/20100720210335_create_sample_users.rb +2 -2
  54. data/sample_app/db/schema.rb +10 -10
  55. data/sample_app/db/seeds.rb +3 -3
  56. data/sample_app/features/step_definitions/seeds_steps.rb +4 -4
  57. data/sample_app/features/step_definitions/web_steps.rb +3 -4
  58. data/sample_app/features/support/env.rb +3 -4
  59. data/sample_app/features/support/paths.rb +4 -4
  60. data/sample_app/lib/tasks/cucumber.rake +43 -44
  61. data/sample_app/spec/spec_helper.rb +3 -3
  62. data/spec/config/shards.yml +78 -0
  63. data/spec/migrations/10_create_users_using_replication.rb +4 -4
  64. data/spec/migrations/11_add_field_in_all_slaves.rb +4 -4
  65. data/spec/migrations/12_create_users_using_block.rb +8 -8
  66. data/spec/migrations/13_create_users_using_block_and_using.rb +5 -5
  67. data/spec/migrations/14_create_users_on_shards_of_a_group_with_versions.rb +3 -3
  68. data/spec/migrations/15_create_user_on_shards_of_default_group_with_versions.rb +3 -3
  69. data/spec/migrations/1_create_users_on_master.rb +4 -4
  70. data/spec/migrations/2_create_users_on_canada.rb +4 -4
  71. data/spec/migrations/3_create_users_on_both_shards.rb +4 -4
  72. data/spec/migrations/4_create_users_on_shards_of_a_group.rb +4 -4
  73. data/spec/migrations/5_create_users_on_multiples_groups.rb +3 -3
  74. data/spec/migrations/6_raise_exception_with_invalid_shard_name.rb +4 -4
  75. data/spec/migrations/7_raise_exception_with_invalid_multiple_shard_names.rb +4 -4
  76. data/spec/migrations/8_raise_exception_with_invalid_group_name.rb +4 -4
  77. data/spec/migrations/9_raise_exception_with_multiple_invalid_group_names.rb +5 -5
  78. data/spec/octopus/association_shard_tracking_spec.rb +1036 -0
  79. data/spec/octopus/collection_proxy_spec.rb +16 -0
  80. data/spec/octopus/load_balancing/round_robin_spec.rb +15 -0
  81. data/spec/octopus/log_subscriber_spec.rb +5 -5
  82. data/spec/octopus/migration_spec.rb +83 -49
  83. data/spec/octopus/model_spec.rb +544 -292
  84. data/spec/octopus/octopus_spec.rb +64 -31
  85. data/spec/octopus/proxy_spec.rb +145 -141
  86. data/spec/octopus/query_cache_for_shards_spec.rb +40 -0
  87. data/spec/octopus/relation_proxy_spec.rb +132 -0
  88. data/spec/octopus/replicated_slave_grouped_spec.rb +91 -0
  89. data/spec/octopus/replication_spec.rb +140 -65
  90. data/spec/octopus/scope_proxy_spec.rb +90 -10
  91. data/spec/octopus/sharded_replicated_slave_grouped_spec.rb +55 -0
  92. data/spec/octopus/sharded_spec.rb +10 -10
  93. data/spec/spec_helper.rb +8 -6
  94. data/spec/support/active_record/connection_adapters/modify_config_adapter.rb +1 -3
  95. data/spec/support/database_connection.rb +2 -2
  96. data/spec/support/database_models.rb +18 -17
  97. data/spec/support/octopus_helper.rb +32 -25
  98. data/spec/support/query_count.rb +1 -3
  99. data/spec/support/shared_contexts.rb +3 -3
  100. data/spec/tasks/octopus.rake_spec.rb +10 -10
  101. metadata +112 -70
  102. data/.ruby-version +0 -1
  103. data/init.rb +0 -1
  104. data/lib/octopus/association_collection.rb +0 -49
  105. data/lib/octopus/has_and_belongs_to_many_association.rb +0 -17
  106. data/lib/octopus/rails3/persistence.rb +0 -39
  107. data/lib/octopus/rails3/singular_association.rb +0 -34
  108. data/rails/init.rb +0 -1
  109. data/spec/octopus/association_spec.rb +0 -712
@@ -1,23 +1,33 @@
1
- require "spec_helper"
1
+ require 'spec_helper'
2
2
 
3
3
  describe Octopus::Model do
4
- describe "#using method" do
5
- it "should return self after calling the #using method" do
6
- User.using(:canada).should be_a(Octopus::ScopeProxy)
4
+ describe '#using method' do
5
+ it 'raise when Model#using receives a block' do
6
+ expect { User.using(:master) { true } }.to raise_error(Octopus::Exception, /User\.using is not allowed to receive a block/)
7
7
  end
8
8
 
9
- it "should allow to send a block to the master shard" do
9
+ it 'should allow to send a block to the master shard' do
10
10
  Octopus.using(:master) do
11
- User.create!(:name => "Block test")
11
+ User.create!(:name => 'Block test')
12
12
  end
13
13
 
14
- User.using(:master).find_by_name("Block test").should_not be_nil
14
+ expect(User.using(:master).find_by_name('Block test')).not_to be_nil
15
15
  end
16
16
 
17
17
  it 'should allow to pass a string as the shard name to a AR subclass' do
18
18
  User.using('canada').create!(:name => 'Rafael Pilha')
19
19
 
20
- User.using('canada').find_by_name('Rafael Pilha').should_not be_nil
20
+ expect(User.using('canada').find_by_name('Rafael Pilha')).not_to be_nil
21
+ end
22
+
23
+ it 'should allow comparison of a string shard name with symbol shard name' do
24
+ u = User.using('canada').create!(:name => 'Rafael Pilha')
25
+ expect(u).to eq(User.using(:canada).find_by_name('Rafael Pilha'))
26
+ end
27
+
28
+ it 'should allow comparison of a symbol shard name with string shard name' do
29
+ u = User.using(:canada).create!(:name => 'Rafael Pilha')
30
+ expect(u).to eq(User.using('canada').find_by_name('Rafael Pilha'))
21
31
  end
22
32
 
23
33
  it 'should allow to pass a string as the shard name to a block' do
@@ -25,192 +35,237 @@ describe Octopus::Model do
25
35
  User.create!(:name => 'Rafael Pilha')
26
36
  end
27
37
 
28
- User.using('canada').find_by_name('Rafael Pilha').should_not be_nil
38
+ expect(User.using('canada').find_by_name('Rafael Pilha')).not_to be_nil
29
39
  end
30
40
 
31
- it "should allow selecting the shards on scope" do
41
+ it 'should allow selecting the shards on scope' do
32
42
  User.using(:canada).create!(:name => 'oi')
33
- User.using(:canada).count.should == 1
34
- User.count.should == 0
43
+ expect(User.using(:canada).count).to eq(1)
44
+ expect(User.count).to eq(0)
35
45
  end
36
46
 
37
- it "should allow selecting the shard using #new" do
47
+ it 'should allow selecting the shard using #new' do
38
48
  u = User.using(:canada).new
39
- u.name = "Thiago"
49
+ u.name = 'Thiago'
40
50
  u.save
41
51
 
42
- User.using(:canada).count.should == 1
43
- User.using(:brazil).count.should == 0
52
+ expect(User.using(:canada).count).to eq(1)
53
+ expect(User.using(:brazil).count).to eq(0)
44
54
 
45
55
  u1 = User.new
46
- u1.name = "Joaquim"
56
+ u1.name = 'Joaquim'
47
57
  u2 = User.using(:canada).new
48
- u2.name = "Manuel"
49
- u1.save()
50
- u2.save()
58
+ u2.name = 'Manuel'
59
+ u1.save
60
+ u2.save
51
61
 
52
- User.using(:canada).all.should == [u, u2]
53
- User.all.should == [u1]
62
+ expect(User.using(:canada).all).to eq([u, u2])
63
+ expect(User.all).to eq([u1])
54
64
  end
55
65
 
56
- describe "multiple calls to the same scope" do
57
- it "works with nil response" do
66
+ it "should allow the #select method to fetch the correct data when using a block" do
67
+ canadian_user = User.using(:canada).create!(:name => 'Rafael Pilha')
68
+
69
+ Octopus.using('canada') do
70
+ @all_canadian_user_ids = User.select('id').to_a
71
+ end
72
+
73
+ expect(@all_canadian_user_ids).to eq([canadian_user])
74
+ end
75
+
76
+ it "should allow objects to be fetch using different blocks - GH #306" do
77
+ canadian_user = User.using(:canada).create!(:name => 'Rafael Pilha')
78
+
79
+ Octopus.using(:canada) { @users = User.where('id is not null') }
80
+ Octopus.using(:canada) { @user = @users.first }
81
+
82
+ Octopus.using(:canada) { @user2 = User.where('id is not null').first }
83
+
84
+ expect(@user).to eq(canadian_user)
85
+ expect(@user2).to eq(canadian_user)
86
+ end
87
+
88
+ describe 'multiple calls to the same scope' do
89
+ it 'works with nil response' do
58
90
  scope = User.using(:canada)
59
- scope.count.should == 0
60
- scope.first.should be_nil
91
+ expect(scope.count).to eq(0)
92
+ expect(scope.first).to be_nil
61
93
  end
62
94
 
63
- it "works with non-nil response" do
95
+ it 'works with non-nil response' do
64
96
  user = User.using(:canada).create!(:name => 'oi')
65
97
  scope = User.using(:canada)
66
- scope.count.should == 1
67
- scope.first.should == user
98
+ expect(scope.count).to eq(1)
99
+ expect(scope.first).to eq(user)
68
100
  end
69
101
  end
70
102
 
71
- it "should select the correct shard" do
103
+ it 'should select the correct shard' do
72
104
  User.using(:canada)
73
105
  User.create!(:name => 'oi')
74
- User.count.should == 1
106
+ expect(User.count).to eq(1)
75
107
  end
76
108
 
77
- it "should ensure that the connection will be cleaned" do
78
- ActiveRecord::Base.connection.current_shard.should == :master
79
- begin
109
+ it 'should ensure that the connection will be cleaned' do
110
+ expect(ActiveRecord::Base.connection.current_shard).to eq(:master)
111
+ expect do
80
112
  Octopus.using(:canada) do
81
- raise "Some Exception"
113
+ fail 'Some Exception'
82
114
  end
83
- rescue
84
- end
115
+ end.to raise_error(RuntimeError)
116
+
117
+ expect(ActiveRecord::Base.connection.current_shard).to eq(:master)
118
+ end
119
+
120
+ it 'should ensure that the connection will be cleaned with custom master' do
121
+ OctopusHelper.using_environment :octopus do
122
+ Octopus.config[:master_shard] = :brazil
123
+ expect(ActiveRecord::Base.connection.current_shard).to eq(:brazil)
124
+ expect do
125
+ Octopus.using(:canada) do
126
+ fail 'Some Exception'
127
+ end
128
+ end.to raise_error(RuntimeError)
85
129
 
86
- ActiveRecord::Base.connection.current_shard.should == :master
130
+ expect(ActiveRecord::Base.connection.current_shard).to eq(:brazil)
131
+ Octopus.config[:master_shard] = nil
132
+ end
87
133
  end
88
134
 
89
- it "should allow creating more than one user" do
135
+ it 'should allow creating more than one user' do
90
136
  User.using(:canada).create([{ :name => 'America User 1' }, { :name => 'America User 2' }])
91
- User.create!(:name => "Thiago")
92
- User.using(:canada).find_by_name("America User 1").should_not be_nil
93
- User.using(:canada).find_by_name("America User 2").should_not be_nil
94
- User.using(:master).find_by_name("Thiago").should_not be_nil
137
+ User.create!(:name => 'Thiago')
138
+ expect(User.using(:canada).find_by_name('America User 1')).not_to be_nil
139
+ expect(User.using(:canada).find_by_name('America User 2')).not_to be_nil
140
+ expect(User.using(:master).find_by_name('Thiago')).not_to be_nil
95
141
  end
96
142
 
97
- it "should work when you have a SQLite3 shard" do
98
- u = User.using(:sqlite_shard).create!(:name => "Sqlite3")
99
- User.using(:sqlite_shard).find_by_name("Sqlite3").should == u
143
+ it 'should work when you have a SQLite3 shard' do
144
+ u = User.using(:sqlite_shard).create!(:name => 'Sqlite3')
145
+ expect(User.using(:sqlite_shard).where(name: 'Sqlite3').first).to eq(u)
100
146
  end
101
147
 
102
- it "should clean #current_shard from proxy when using execute" do
103
- User.using(:canada).connection().execute("select * from users limit 1;")
104
- User.connection.current_shard.should == :master
148
+ it 'should clean #current_shard from proxy when using execute' do
149
+ User.using(:canada).connection.execute('select * from users limit 1;')
150
+ expect(User.connection.current_shard).to eq(:master)
105
151
  end
106
152
 
107
- it "should allow scoping dynamically" do
153
+ it 'should clean #current_shard from proxy when using execute' do
154
+ OctopusHelper.using_environment :octopus do
155
+ Octopus.config[:master_shard] = :brazil
156
+ User.using(:canada).connection.execute('select * from users limit 1;')
157
+ expect(User.connection.current_shard).to eq(:brazil)
158
+ Octopus.config[:master_shard] = nil
159
+ end
160
+ end
161
+
162
+ it 'should allow scoping dynamically' do
108
163
  User.using(:canada).using(:master).using(:canada).create!(:name => 'oi')
109
- User.using(:canada).using(:master).count.should == 0
110
- User.using(:master).using(:canada).count.should == 1
164
+ expect(User.using(:canada).using(:master).count).to eq(0)
165
+ expect(User.using(:master).using(:canada).count).to eq(1)
111
166
  end
112
167
 
113
- it "should allow find inside blocks" do
114
- @user = User.using(:brazil).create!(:name => "Thiago")
168
+ it 'should allow find inside blocks' do
169
+ @user = User.using(:brazil).create!(:name => 'Thiago')
115
170
 
116
171
  Octopus.using(:brazil) do
117
- User.first.should == @user
172
+ expect(User.first).to eq(@user)
118
173
  end
119
174
 
120
- User.using(:brazil).find_by_name("Thiago").should == @user
175
+ expect(User.using(:brazil).find_by_name('Thiago')).to eq(@user)
121
176
  end
122
177
 
123
- it "should clean the current_shard after executing the current query" do
124
- User.using(:canada).create!(:name => "oi")
125
- User.count.should == 0
178
+ it 'should clean the current_shard after executing the current query' do
179
+ User.using(:canada).create!(:name => 'oi')
180
+ expect(User.count).to eq(0)
126
181
  end
127
182
 
128
- it "should support both groups and alone shards" do
129
- u = User.using(:alone_shard).create!(:name => "Alone")
130
- User.using(:alone_shard).count.should == 1
131
- User.using(:canada).count.should == 0
132
- User.using(:brazil).count.should == 0
133
- User.count.should == 0
183
+ it 'should support both groups and alone shards' do
184
+ _u = User.using(:alone_shard).create!(:name => 'Alone')
185
+ expect(User.using(:alone_shard).count).to eq(1)
186
+ expect(User.using(:canada).count).to eq(0)
187
+ expect(User.using(:brazil).count).to eq(0)
188
+ expect(User.count).to eq(0)
134
189
  end
135
190
 
136
- it "should work with named scopes" do
137
- u = User.using(:brazil).create!(:name => "Thiago")
191
+ it 'should work with named scopes' do
192
+ u = User.using(:brazil).create!(:name => 'Thiago')
138
193
 
139
- User.thiago.using(:brazil).first.should eq(u)
140
- User.using(:brazil).thiago.first.should eq(u)
194
+ expect(User.thiago.using(:brazil).first).to eq(u)
195
+ expect(User.using(:brazil).thiago.first).to eq(u)
141
196
 
142
197
  Octopus.using(:brazil) do
143
- User.thiago.first.should eq(u)
198
+ expect(User.thiago.first).to eq(u)
144
199
  end
145
200
  end
146
201
 
147
- describe "#current_shard attribute" do
148
- it "should store the attribute when you create or find an object" do
149
- u = User.using(:alone_shard).create!(:name => "Alone")
150
- u.current_shard.should == :alone_shard
202
+ describe '#current_shard attribute' do
203
+ it 'should store the attribute when you create or find an object' do
204
+ u = User.using(:alone_shard).create!(:name => 'Alone')
205
+ expect(u.current_shard).to eq(:alone_shard)
151
206
  User.using(:canada).create!(:name => 'oi')
152
- u = User.using(:canada).find_by_name("oi")
153
- u.current_shard.should == :canada
207
+ u = User.using(:canada).find_by_name('oi')
208
+ expect(u.current_shard).to eq(:canada)
154
209
  end
155
210
 
156
- it "should store the attribute when you find multiple instances" do
157
- 5.times { User.using(:alone_shard).create!(:name => "Alone") }
211
+ it 'should store the attribute when you find multiple instances' do
212
+ 5.times { User.using(:alone_shard).create!(:name => 'Alone') }
158
213
 
159
214
  User.using(:alone_shard).all.each do |u|
160
- u.current_shard.should == :alone_shard
215
+ expect(u.current_shard).to eq(:alone_shard)
161
216
  end
162
217
  end
163
218
 
164
- it "should works when you find, and after that, alter that object" do
165
- alone_user = User.using(:alone_shard).create!(:name => "Alone")
166
- master_user = User.using(:master).create!(:name => "Master")
167
- alone_user.name = "teste"
219
+ it 'should works when you find, and after that, alter that object' do
220
+ alone_user = User.using(:alone_shard).create!(:name => 'Alone')
221
+ _mstr_user = User.using(:master).create!(:name => 'Master')
222
+ alone_user.name = 'teste'
168
223
  alone_user.save
169
- User.using(:master).find(:first).name.should == "Master"
170
- User.using(:alone_shard).find(:first).name.should == "teste"
224
+ expect(User.using(:master).first.name).to eq('Master')
225
+ expect(User.using(:alone_shard).first.name).to eq('teste')
171
226
  end
172
227
 
173
- it "should work for the reload method" do
174
- User.using(:alone_shard).create!(:name => "Alone")
175
- u = User.using(:alone_shard).find_by_name("Alone")
228
+ it 'should work for the reload method' do
229
+ User.using(:alone_shard).create!(:name => 'Alone')
230
+ u = User.using(:alone_shard).find_by_name('Alone')
176
231
  u.reload
177
- u.name.should == "Alone"
232
+ expect(u.name).to eq('Alone')
178
233
  end
179
234
 
180
- it "should work passing some arguments to reload method" do
181
- User.using(:alone_shard).create!(:name => "Alone")
182
- u = User.using(:alone_shard).find_by_name("Alone")
235
+ it 'should work passing some arguments to reload method' do
236
+ User.using(:alone_shard).create!(:name => 'Alone')
237
+ u = User.using(:alone_shard).find_by_name('Alone')
183
238
  u.reload(:lock => true)
184
- u.name.should == "Alone"
239
+ expect(u.name).to eq('Alone')
185
240
  end
186
241
  end
187
242
 
188
- describe "passing a block" do
189
- it "should allow queries be executed inside the block, ponting to a specific shard" do
243
+ describe 'passing a block' do
244
+ it 'should allow queries be executed inside the block, ponting to a specific shard' do
190
245
  Octopus.using(:canada) do
191
- User.create(:name => "oi")
246
+ User.create(:name => 'oi')
192
247
  end
193
248
 
194
- User.using(:canada).count.should == 1
195
- User.using(:master).count.should == 0
196
- User.count.should == 0
249
+ expect(User.using(:canada).count).to eq(1)
250
+ expect(User.using(:master).count).to eq(0)
251
+ expect(User.count).to eq(0)
197
252
  end
198
253
 
199
- it "should allow execute queries inside a model" do
254
+ it 'should allow execute queries inside a model' do
200
255
  u = User.new
201
- u.awesome_queries()
202
- User.using(:canada).count.should == 1
203
- User.count.should == 0
256
+ u.awesome_queries
257
+ expect(User.using(:canada).count).to eq(1)
258
+ expect(User.count).to eq(0)
204
259
  end
205
260
  end
206
261
 
207
- describe "raising errors" do
262
+ describe 'raising errors' do
208
263
  it "should raise a error when you specify a shard that doesn't exist" do
209
- lambda { User.using(:crazy_shard).create!(:name => 'Thiago') }.should raise_error("Nonexistent Shard Name: crazy_shard")
264
+ expect { User.using(:crazy_shard).create!(:name => 'Thiago') }.to raise_error('Nonexistent Shard Name: crazy_shard')
210
265
  end
211
266
  end
212
267
 
213
- describe "equality" do
268
+ describe 'equality' do
214
269
  let(:canada1) do
215
270
  u = User.new
216
271
  u.id = 1
@@ -232,353 +287,550 @@ describe Octopus::Model do
232
287
  u
233
288
  end
234
289
 
235
- it "should work with persisted objects" do
236
- u = User.using(:brazil).create(:name => "Mike")
237
- User.using(:brazil).find_by_name("Mike").should == u
290
+ it 'should work with persisted objects' do
291
+ u = User.using(:brazil).create(:name => 'Mike')
292
+ expect(User.using(:brazil).find_by_name('Mike')).to eq(u)
238
293
  end
239
294
 
240
- it "should check current_shard when determining equality" do
241
- canada1.should_not == brazil1
242
- canada1.should == canada1_dup
295
+ it 'should check current_shard when determining equality' do
296
+ expect(canada1).not_to eq(brazil1)
297
+ expect(canada1).to eq(canada1_dup)
243
298
  end
244
299
 
245
- it "delegates equality check on scopes" do
246
- u = User.using(:brazil).create!(:name => "Mike")
247
- User.using(:brazil).where(:name => "Mike").should == [u]
300
+ it 'delegates equality check on scopes' do
301
+ u = User.using(:brazil).create!(:name => 'Mike')
302
+ expect(User.using(:brazil).where(:name => 'Mike')).to eq([u])
248
303
  end
249
304
  end
250
305
  end
251
306
 
252
- describe "using a postgresql shard" do
253
- it "should update the Arel Engine" do
254
- if ActiveRecord::VERSION::STRING > '2.4.0'
255
- User.using(:postgresql_shard).arel_engine.connection.adapter_name.should == "PostgreSQL"
256
- User.using(:alone_shard).arel_engine.connection.adapter_name.should == "Mysql2"
307
+ describe 'using a postgresql shard' do
308
+ it 'should update the Arel Engine' do
309
+ if Octopus.atleast_rails52?
310
+ expect(User.using(:postgresql_shard).connection.adapter_name).to eq('PostgreSQL')
311
+ expect(User.using(:alone_shard).connection.adapter_name).to eq('Mysql2')
312
+ else
313
+ expect(User.using(:postgresql_shard).arel_engine.connection.adapter_name).to eq('PostgreSQL')
314
+ expect(User.using(:alone_shard).arel_engine.connection.adapter_name).to eq('Mysql2')
257
315
  end
258
316
  end
259
317
 
260
- it "should works with writes and reads" do
261
- u = User.using(:postgresql_shard).create!(:name => "PostgreSQL User")
262
- User.using(:postgresql_shard).find(:all).should == [u]
263
- User.using(:alone_shard).find(:all).should == []
264
- User.connection_handler.connection_pools["ActiveRecord::Base"] = User.connection.instance_variable_get(:@shards)[:master]
318
+ it 'should works with writes and reads' do
319
+ u = User.using(:postgresql_shard).create!(:name => 'PostgreSQL User')
320
+ expect(User.using(:postgresql_shard).all).to eq([u])
321
+ expect(User.using(:alone_shard).all).to eq([])
265
322
  end
266
323
  end
267
324
 
268
- describe "AR basic methods" do
269
- it "establish_connection" do
270
- CustomConnection.connection.current_database.should == "octopus_shard_2"
325
+ describe 'AR basic methods' do
326
+ it 'establish_connection' do
327
+ expect(CustomConnection.connection.current_database).to eq('octopus_shard_2')
271
328
  end
272
329
 
273
- it "should not mess with custom connection table names" do
274
- Advert.connection.current_database.should == "octopus_shard_1"
275
- Advert.create!(:name => "Teste")
330
+ it 'reuses parent model connection' do
331
+ klass = Class.new(CustomConnection)
332
+
333
+ expect(klass.connection).to be klass.connection
276
334
  end
277
335
 
278
- it "increment" do
279
- u = User.using(:brazil).create!(:name => "Teste", :number => 10)
336
+ it 'should not mess with custom connection table names' do
337
+ expect(Advert.connection.current_database).to eq('octopus_shard_1')
338
+ Advert.create!(:name => 'Teste')
339
+ end
340
+
341
+ it 'increment' do
342
+ _ = User.using(:brazil).create!(:name => 'Teste', :number => 10)
280
343
  u = User.using(:brazil).find_by_number(10)
281
344
  u.increment(:number)
282
- u.save()
283
- u = User.using(:brazil).find_by_number(11).should_not be_nil
345
+ u.save
346
+ expect(User.using(:brazil).find_by_number(11)).not_to be_nil
284
347
  end
285
348
 
286
- it "increment!" do
287
- u = User.using(:brazil).create!(:name => "Teste", :number => 10)
349
+ it 'increment!' do
350
+ _ = User.using(:brazil).create!(:name => 'Teste', :number => 10)
288
351
  u = User.using(:brazil).find_by_number(10)
289
352
  u.increment!(:number)
290
- u = User.using(:brazil).find_by_number(11).should_not be_nil
353
+ expect(User.using(:brazil).find_by_number(11)).not_to be_nil
291
354
  end
292
355
 
293
- it "decrement" do
294
- u = User.using(:brazil).create!(:name => "Teste", :number => 10)
356
+ it 'decrement' do
357
+ _ = User.using(:brazil).create!(:name => 'Teste', :number => 10)
295
358
  u = User.using(:brazil).find_by_number(10)
296
359
  u.decrement(:number)
297
- u.save()
298
- u = User.using(:brazil).find_by_number(9).should_not be_nil
360
+ u.save
361
+ expect(User.using(:brazil).find_by_number(9)).not_to be_nil
299
362
  end
300
363
 
301
- it "decrement!" do
302
- u = User.using(:brazil).create!(:name => "Teste", :number => 10)
364
+ it 'decrement!' do
365
+ _ = User.using(:brazil).create!(:name => 'Teste', :number => 10)
303
366
  u = User.using(:brazil).find_by_number(10)
304
367
  u.decrement!(:number)
305
- u = User.using(:brazil).find_by_number(9).should_not be_nil
368
+ expect(User.using(:brazil).find_by_number(9)).not_to be_nil
306
369
  end
307
370
 
308
- it "toggle" do
309
- u = User.using(:brazil).create!(:name => "Teste", :admin => false)
371
+ it 'toggle' do
372
+ _ = User.using(:brazil).create!(:name => 'Teste', :admin => false)
310
373
  u = User.using(:brazil).find_by_name('Teste')
311
374
  u.toggle(:admin)
312
- u.save()
313
- u = User.using(:brazil).find_by_name('Teste').admin.should be_true
375
+ u.save
376
+ expect(User.using(:brazil).find_by_name('Teste').admin).to be true
314
377
  end
315
378
 
316
- it "toggle!" do
317
- u = User.using(:brazil).create!(:name => "Teste", :admin => false)
379
+ it 'toggle!' do
380
+ _ = User.using(:brazil).create!(:name => 'Teste', :admin => false)
318
381
  u = User.using(:brazil).find_by_name('Teste')
319
382
  u.toggle!(:admin)
320
- u = User.using(:brazil).find_by_name('Teste').admin.should be_true
383
+ expect(User.using(:brazil).find_by_name('Teste').admin).to be true
321
384
  end
322
385
 
323
- it "count" do
324
- u = User.using(:brazil).create!(:name => "User1")
325
- u2 = User.using(:brazil).create!(:name => "User2")
326
- u3 = User.using(:brazil).create!(:name => "User3")
327
- User.using(:brazil).find(:all, :conditions => {:name => "User2"}).count.should == 1
386
+ it 'count' do
387
+ _u = User.using(:brazil).create!(:name => 'User1')
388
+ _v = User.using(:brazil).create!(:name => 'User2')
389
+ _w = User.using(:brazil).create!(:name => 'User3')
390
+ expect(User.using(:brazil).where(:name => 'User2').all.count).to eq(1)
328
391
  end
329
392
 
330
- it "maximum" do
331
- u1 = User.using(:brazil).create!(:name => "Teste", :number => 11)
332
- u2 = User.using(:master).create!(:name => "Teste", :number => 12)
393
+ it 'maximum' do
394
+ _u = User.using(:brazil).create!(:name => 'Teste', :number => 11)
395
+ _v = User.using(:master).create!(:name => 'Teste', :number => 12)
396
+
397
+ expect(User.using(:brazil).maximum(:number)).to eq(11)
398
+ expect(User.using(:master).maximum(:number)).to eq(12)
399
+ end
400
+
401
+ it 'sum' do
402
+ u = User.using(:brazil).create!(:name => 'Teste', :number => 11)
403
+ v = User.using(:master).create!(:name => 'Teste', :number => 12)
404
+
405
+ expect(User.using(:master).sum(:number)).to eq(12)
406
+ expect(User.using(:brazil).sum(:number)).to eq(11)
333
407
 
334
- User.using(:brazil).maximum(:number).should == 11
335
- User.using(:master).maximum(:number).should == 12
408
+ expect(User.where(id: v.id).sum(:number)).to eq(12)
409
+ expect(User.using(:brazil).where(id: u.id).sum(:number)).to eq(11)
410
+ expect(User.using(:master).where(id: v.id).sum(:number)).to eq(12)
336
411
  end
337
412
 
338
- describe "any?" do
339
- before { User.using(:brazil).create!(:name => "User1") }
413
+ describe 'any?' do
414
+ before { User.using(:brazil).create!(:name => 'User1') }
340
415
 
341
- it "works when true" do
342
- scope = User.using(:brazil).where(:name => "User1")
343
- scope.any?.should be_true
416
+ it 'works when true' do
417
+ scope = User.using(:brazil).where(:name => 'User1')
418
+ expect(scope.any?).to be true
344
419
  end
345
420
 
346
- it "works when false" do
347
- scope = User.using(:brazil).where(:name => "User2")
348
- scope.any?.should be_false
421
+ it 'works when false' do
422
+ scope = User.using(:brazil).where(:name => 'User2')
423
+ expect(scope.any?).to be false
349
424
  end
350
425
  end
351
426
 
352
- it "exists?" do
353
- @user = User.using(:brazil).create!(:name => "User1")
427
+ it 'exists?' do
428
+ @user = User.using(:brazil).create!(:name => 'User1')
354
429
 
355
- User.using(:brazil).where(:name => "User1").exists?.should be_true
356
- User.using(:brazil).where(:name => "User2").exists?.should be_false
430
+ expect(User.using(:brazil).where(:name => 'User1').exists?).to be true
431
+ expect(User.using(:brazil).where(:name => 'User2').exists?).to be false
357
432
  end
358
433
 
359
- describe "touch" do
360
- it "updates updated_at by default" do
361
- @user = User.using(:brazil).create!(:name => "User1")
362
- User.using(:brazil).update_all({:updated_at => Time.now - 3.months}, {:id => @user.id})
434
+ describe 'touch' do
435
+ it 'updates updated_at by default' do
436
+ @user = User.using(:brazil).create!(:name => 'User1')
437
+ User.using(:brazil).where(:id => @user.id).update_all(:updated_at => Time.now - 3.months)
363
438
  @user.touch
364
- @user.reload.updated_at.to_date.should eq(Date.today)
439
+ expect(@user.reload.updated_at.in_time_zone('GMT').to_date).to eq(Time.now.in_time_zone('GMT').to_date)
365
440
  end
366
441
 
367
- it "updates passed in attribute name" do
368
- @user = User.using(:brazil).create!(:name => "User1")
369
- User.using(:brazil).update_all({:created_at => Time.now - 3.months}, {:id => @user.id})
442
+ it 'updates passed in attribute name' do
443
+ @user = User.using(:brazil).create!(:name => 'User1')
444
+ User.using(:brazil).where(:id => @user.id).update_all(:created_at => Time.now - 3.months)
370
445
  @user.touch(:created_at)
371
- @user.reload.created_at.to_date.should eq(Date.today)
446
+ expect(@user.reload.created_at.in_time_zone('GMT').to_date).to eq(Time.now.in_time_zone('GMT').to_date)
372
447
  end
373
448
  end
374
449
 
375
- describe "#pluck" do
376
- before { User.using(:brazil).create!(:name => "User1") }
450
+ describe '#pluck' do
451
+ before { User.using(:brazil).create!(:name => 'User1') }
377
452
 
378
- it "should works from scope proxy" do
453
+ it 'should works from scope proxy' do
379
454
  names = User.using(:brazil).pluck(:name)
380
- names.should eq(["User1"])
381
- User.using(:master).pluck(:name).should eq([])
455
+ expect(names).to eq(['User1'])
456
+ expect(User.using(:master).pluck(:name)).to eq([])
382
457
  end
383
458
  end
384
459
 
385
- it "update_column" do
386
- @user = User.using(:brazil).create!(:name => "User1")
460
+ it 'update_column' do
461
+ @user = User.using(:brazil).create!(:name => 'User1')
387
462
  @user2 = User.using(:brazil).find(@user.id)
388
- @user2.update_column(:name, "Joaquim Shard Brazil")
389
- User.using(:brazil).find_by_name("Joaquim Shard Brazil").should_not be_nil
463
+ @user2.update_column(:name, 'Joaquim Shard Brazil')
464
+ expect(User.using(:brazil).find_by_name('Joaquim Shard Brazil')).not_to be_nil
390
465
  end
391
466
 
392
- it "update_attributes" do
393
- @user = User.using(:brazil).create!(:name => "User1")
467
+ it 'update_attributes' do
468
+ @user = User.using(:brazil).create!(:name => 'User1')
394
469
  @user2 = User.using(:brazil).find(@user.id)
395
- @user2.update_attributes(:name => "Joaquim")
396
- User.using(:brazil).find_by_name("Joaquim").should_not be_nil
470
+ @user2.update_attributes(:name => 'Joaquim')
471
+ expect(User.using(:brazil).find_by_name('Joaquim')).not_to be_nil
397
472
  end
398
473
 
399
- it "using update_attributes inside a block" do
474
+ it 'using update_attributes inside a block' do
400
475
  Octopus.using(:brazil) do
401
- @user = User.create!(:name => "User1")
476
+ @user = User.create!(:name => 'User1')
402
477
  @user2 = User.find(@user.id)
403
- @user2.update_attributes(:name => "Joaquim")
478
+ @user2.update_attributes(:name => 'Joaquim')
404
479
  end
405
480
 
406
- User.find_by_name("Joaquim").should be_nil
407
- User.using(:brazil).find_by_name("Joaquim").should_not be_nil
481
+ expect(User.find_by_name('Joaquim')).to be_nil
482
+ expect(User.using(:brazil).find_by_name('Joaquim')).not_to be_nil
408
483
  end
409
484
 
410
- it "update_attribute" do
411
- @user = User.using(:brazil).create!(:name => "User1")
485
+ it 'update_attribute' do
486
+ @user = User.using(:brazil).create!(:name => 'User1')
412
487
  @user2 = User.using(:brazil).find(@user.id)
413
- @user2.update_attribute(:name, "Joaquim")
414
- User.using(:brazil).find_by_name("Joaquim").should_not be_nil
488
+ @user2.update_attribute(:name, 'Joaquim')
489
+ expect(User.using(:brazil).find_by_name('Joaquim')).not_to be_nil
415
490
  end
416
491
 
417
- it "as_json" do
418
- ActiveRecord::Base.include_root_in_json = false
492
+ it 'as_json' do
493
+ ActiveRecord::Base.include_root_in_json = false
419
494
 
420
495
  Octopus.using(:brazil) do
421
- User.create!(:name => "User1")
496
+ User.create!(:name => 'User1')
422
497
  end
423
498
 
424
- user = User.using(:brazil).where(:name => "User1").first
425
- user.as_json(:except => [:created_at, :updated_at, :id]).should eq({"admin"=>nil, "name"=>"User1", "number"=>nil})
499
+ user = User.using(:brazil).where(:name => 'User1').first
500
+ expect(user.as_json(:except => [:created_at, :updated_at, :id])).to eq('admin' => nil, 'name' => 'User1', 'number' => nil)
426
501
  end
427
502
 
428
- it "transaction" do
429
- u = User.create!(:name => "Thiago")
503
+ describe 'transaction' do
504
+ context 'without assigning a database' do
505
+ it 'works as expected' do
506
+ _u = User.create!(:name => 'Thiago')
430
507
 
431
- User.using(:brazil).count.should == 0
432
- User.using(:master).count.should == 1
508
+ expect(User.using(:brazil).count).to eq(0)
509
+ expect(User.using(:master).count).to eq(1)
433
510
 
434
- User.using(:brazil).transaction do
435
- User.find_by_name("Thiago").should be_nil
436
- User.create!(:name => "Brazil")
511
+ User.using(:brazil).transaction do
512
+ expect(User.find_by_name('Thiago')).to be_nil
513
+ User.create!(:name => 'Brazil')
514
+ end
515
+
516
+ expect(User.using(:brazil).count).to eq(1)
517
+ expect(User.using(:master).count).to eq(1)
518
+ end
437
519
  end
438
520
 
439
- User.using(:brazil).count.should == 1
440
- User.using(:master).count.should == 1
521
+ context 'when assigning a database' do
522
+ it 'works as expected' do
523
+ klass = User.using(:brazil)
524
+
525
+ klass.transaction do
526
+ klass.create!(:name => 'Brazil')
527
+ end
528
+
529
+ expect(klass.find_by_name('Brazil')).to be_present
530
+ end
531
+ end
441
532
  end
442
533
 
443
- describe "deleting a record" do
534
+ describe "#finder methods" do
444
535
  before(:each) do
445
- @user = User.using(:brazil).create!(:name => "User1")
536
+ @user1 = User.using(:brazil).create!(:name => 'User1')
537
+ @user2 = User.using(:brazil).create!(:name => 'User2')
538
+ @user3 = User.using(:brazil).create!(:name => 'User3')
539
+ end
540
+
541
+ it "#find_each should work with a block" do
542
+ result_array = []
543
+
544
+ User.using(:brazil).where("name is not NULL").find_each do |user|
545
+ result_array << user
546
+ end
547
+
548
+ expect(result_array).to eq([@user1, @user2, @user3])
549
+ end
550
+
551
+ it "#find_each should work with a where.not(...)" do
552
+ result_array = []
553
+
554
+ User.using(:brazil).where.not(:name => 'User2').find_each do |user|
555
+ result_array << user
556
+ end
557
+
558
+ expect(result_array).to eq([@user1, @user3])
559
+ end
560
+
561
+ it "#find_each should work as an enumerator" do
562
+ result_array = []
563
+
564
+ User.using(:brazil).where("name is not NULL").find_each.each do |user|
565
+ result_array << user
566
+ end
567
+
568
+ expect(result_array).to eq([@user1, @user2, @user3])
569
+ end
570
+
571
+ it "#find_each should work as a lazy enumerator" do
572
+ result_array = []
573
+
574
+ User.using(:brazil).where("name is not NULL").find_each.lazy.each do |user|
575
+ result_array << user
576
+ end
577
+
578
+ expect(result_array).to eq([@user1, @user2, @user3])
579
+ end
580
+
581
+ it "#find_in_batches should work with a block" do
582
+ result_array = []
583
+
584
+ User.using(:brazil).where("name is not NULL").find_in_batches(batch_size: 1) do |user|
585
+ result_array << user
586
+ end
587
+
588
+ expect(result_array).to eq([[@user1], [@user2], [@user3]])
589
+ end
590
+
591
+ it "#find_in_batches should work as an enumerator" do
592
+ result_array = []
593
+
594
+ User.using(:brazil).where("name is not NULL").find_in_batches(batch_size: 1).each do |user|
595
+ result_array << user
596
+ end
597
+
598
+ expect(result_array).to eq([[@user1], [@user2], [@user3]])
599
+ end
600
+
601
+ it "#find_in_batches should work as a lazy enumerator" do
602
+ result_array = []
603
+
604
+ User.using(:brazil).where("name is not NULL").find_in_batches(batch_size: 1).lazy.each do |user|
605
+ result_array << user
606
+ end
607
+
608
+ expect(result_array).to eq([[@user1], [@user2], [@user3]])
609
+ end
610
+ end
611
+
612
+ describe 'deleting a record' do
613
+ before(:each) do
614
+ @user = User.using(:brazil).create!(:name => 'User1')
446
615
  @user2 = User.using(:brazil).find(@user.id)
447
616
  end
448
617
 
449
- it "delete" do
618
+ it 'delete' do
450
619
  @user2.delete
451
- lambda { User.using(:brazil).find(@user2.id) }.should raise_error(ActiveRecord::RecordNotFound)
620
+ expect { User.using(:brazil).find(@user2.id) }.to raise_error(ActiveRecord::RecordNotFound)
452
621
  end
453
622
 
454
623
  it "delete within block shouldn't lose shard" do
455
624
  Octopus.using(:brazil) do
456
625
  @user2.delete
457
- @user3 = User.create(:name => "User3")
626
+ @user3 = User.create(:name => 'User3')
458
627
 
459
- User.connection.current_shard.should == :brazil
460
- User.find(@user3.id).should == @user3
628
+ expect(User.connection.current_shard).to eq(:brazil)
629
+ expect(User.find(@user3.id)).to eq(@user3)
461
630
  end
462
631
  end
463
632
 
464
- it "destroy" do
633
+ it 'destroy' do
465
634
  @user2.destroy
466
- lambda { User.using(:brazil).find(@user2.id) }.should raise_error(ActiveRecord::RecordNotFound)
635
+ expect { User.using(:brazil).find(@user2.id) }.to raise_error(ActiveRecord::RecordNotFound)
467
636
  end
468
637
 
469
638
  it "destroy within block shouldn't lose shard" do
470
639
  Octopus.using(:brazil) do
471
640
  @user2.destroy
472
- @user3 = User.create(:name => "User3")
641
+ @user3 = User.create(:name => 'User3')
642
+
643
+ expect(User.connection.current_shard).to eq(:brazil)
644
+ expect(User.find(@user3.id)).to eq(@user3)
645
+ end
646
+ end
647
+ end
648
+ end
649
+
650
+ describe 'custom connection' do
651
+ context 'by default' do
652
+ it 'with plain call should use custom connection' do
653
+ expect(CustomConnection.connection.current_database).to eq('octopus_shard_2')
654
+ end
655
+
656
+ it 'should ignore using called on relation' do
657
+ expect(CustomConnection.using(:postgresql_shard).connection.current_database).to eq('octopus_shard_2')
658
+ end
659
+
660
+ it 'should ignore Octopus.using block' do
661
+ Octopus.using(:postgresql_shard) do
662
+ expect(CustomConnection.connection.current_database).to eq('octopus_shard_2')
663
+ end
664
+ end
665
+
666
+ it 'should save to correct shard' do
667
+ expect { CustomConnection.create(:value => 'custom value') }.to change {
668
+ CustomConnection
669
+ .connection
670
+ .execute("select count(*) as ct from custom where value = 'custom value'")
671
+ .to_a.first.first
672
+ }.by 1
673
+ end
674
+ end
675
+
676
+ context 'with allowed_shards configured' do
677
+ before do
678
+ CustomConnection.allow_shard :postgresql_shard
679
+ end
680
+
681
+ it 'with plain call should use custom connection' do
682
+ expect(CustomConnection.connection.current_database).to eq('octopus_shard_2')
683
+ end
684
+
685
+ it 'with using called on relation with allowed shard should use' do
686
+ expect(CustomConnection.using(:postgresql_shard).connection.current_database).to eq('octopus_shard_1')
687
+ end
473
688
 
474
- User.connection.current_shard.should == :brazil
475
- User.find(@user3.id).should == @user3
689
+ it 'within Octopus.using block with allowed shard should use' do
690
+ Octopus.using(:postgresql_shard) do
691
+ expect(CustomConnection.connection.current_database).to eq('octopus_shard_1')
692
+ end
693
+ end
694
+
695
+ it 'with using called on relation with disallowed shard should not use' do
696
+ expect(CustomConnection.using(:brazil).connection.current_database).to eq('octopus_shard_2')
697
+ end
698
+
699
+ it 'within Octopus.using block with disallowed shard should not use' do
700
+ Octopus.using(:brazil) do
701
+ expect(CustomConnection.connection.current_database).to eq('octopus_shard_2')
702
+ end
703
+ end
704
+
705
+ it 'should save to correct shard' do
706
+ expect { CustomConnection.create(:value => 'custom value') }.to change {
707
+ CustomConnection
708
+ .connection
709
+ .execute("select count(*) as ct from custom where value = 'custom value'")
710
+ .to_a.first.first
711
+ }.by 1
712
+ end
713
+
714
+ it 'should clean up correctly' do
715
+ User.create!(:name => 'CleanUser')
716
+ CustomConnection.using(:postgresql_shard).first
717
+ expect(User.first).not_to be_nil
718
+ end
719
+
720
+ it 'should clean up correctly even inside block' do
721
+ User.create!(:name => 'CleanUser')
722
+
723
+ Octopus.using(:master) do
724
+ CustomConnection.using(:postgresql_shard).connection.execute('select count(*) from users')
725
+ expect(User.first).not_to be_nil
476
726
  end
477
727
  end
478
728
  end
729
+
730
+ describe 'clear_active_connections!' do
731
+ it 'should not leak connection' do
732
+ CustomConnection.create(:value => 'custom value')
733
+
734
+ # This is what Rails, Sidekiq etc call--this normally handles all connection pools in the app
735
+ expect { ActiveRecord::Base.clear_active_connections! }
736
+ .to change { CustomConnection.connection_pool.active_connection? }
737
+
738
+ expect(CustomConnection.connection_pool.active_connection?).to be_falsey
739
+ end
740
+ end
479
741
  end
480
742
 
481
- describe "when using set_table_name" do
743
+ describe 'when using set_table_name' do
482
744
  it 'should work correctly' do
483
- Bacon.using(:brazil).create!(:name => "YUMMMYYYY")
745
+ Bacon.using(:brazil).create!(:name => 'YUMMMYYYY')
484
746
  end
485
747
 
486
748
  it 'should work correctly with a block' do
487
- Cheese.using(:brazil).create!(:name => "YUMMMYYYY")
749
+ Cheese.using(:brazil).create!(:name => 'YUMMMYYYY')
488
750
  end
489
751
  end
490
752
 
491
- describe "when using table_name=" do
753
+ describe 'when using table_name=' do
492
754
  it 'should work correctly' do
493
- Ham.using(:brazil).create!(:name => "YUMMMYYYY")
755
+ Ham.using(:brazil).create!(:name => 'YUMMMYYYY')
494
756
  end
495
757
  end
496
758
 
497
- describe "when using a environment with a single adapter" do
759
+ describe 'when using a environment with a single adapter' do
498
760
  it 'should not clean the table name' do
499
761
  OctopusHelper.using_environment :production_fully_replicated do
500
- Keyboard.should_not_receive(:reset_table_name)
501
- Keyboard.using(:master).create!(:name => "Master Cat")
762
+ expect(Keyboard).not_to receive(:reset_table_name)
763
+ Keyboard.using(:master).create!(:name => 'Master Cat')
502
764
  end
503
765
  end
504
766
  end
505
767
 
506
- describe "when you have joins/include" do
768
+ describe 'when you have joins/include' do
507
769
  before(:each) do
508
- @client1 = Client.using(:brazil).create(:name => "Thiago")
770
+ @client1 = Client.using(:brazil).create(:name => 'Thiago')
509
771
 
510
772
  Octopus.using(:canada) do
511
- @client2 = Client.create(:name => "Mike")
512
- @client3 = Client.create(:name => "Joao")
513
- @item1 = Item.create(:client => @client2, :name => "Item 1")
514
- @item2 = Item.create(:client => @client2, :name => "Item 2")
515
- @item3 = Item.create(:client => @client3, :name => "Item 3")
516
- @part1 = Part.create(:item => @item1, :name => "Part 1")
517
- @part2 = Part.create(:item => @item1, :name => "Part 2")
518
- @part3 = Part.create(:item => @item2, :name => "Part 3")
773
+ @client2 = Client.create(:name => 'Mike')
774
+ @client3 = Client.create(:name => 'Joao')
775
+ @item1 = Item.create(:client => @client2, :name => 'Item 1')
776
+ @item2 = Item.create(:client => @client2, :name => 'Item 2')
777
+ @item3 = Item.create(:client => @client3, :name => 'Item 3')
778
+ @part1 = Part.create(:item => @item1, :name => 'Part 1')
779
+ @part2 = Part.create(:item => @item1, :name => 'Part 2')
780
+ @part3 = Part.create(:item => @item2, :name => 'Part 3')
519
781
  end
520
782
 
521
- @item4 = Item.using(:brazil).create(:client => @client1, :name => "Item 4")
522
- end
523
-
524
- it "should work with the rails 2.x syntax" do
525
- items = Item.using(:canada).find(:all, :joins => :client, :conditions => { :clients => { :id => @client2.id } })
526
- items.should == [@item1, @item2]
783
+ @item4 = Item.using(:brazil).create(:client => @client1, :name => 'Item 4')
527
784
  end
528
785
 
529
- it "should work using the rails 3.x syntax" do
786
+ it 'should work using the rails 3.x syntax' do
530
787
  items = Item.using(:canada).joins(:client).where("clients.id = #{@client2.id}").all
531
- items.should == [@item1, @item2]
532
- end
533
-
534
- it "should work for include also, rails 2.x syntax" do
535
- items = Item.using(:canada).find(:all, :include => :client, :conditions => { :clients => { :id => @client2.id } })
536
- items.should == [@item1, @item2]
537
- end
538
-
539
- it "should work for include also, rails 3.x syntax" do
540
- items = Item.using(:canada).includes(:client).where("clients.id = #{@client2.id}").all
541
- items.should == [@item1, @item2]
788
+ expect(items).to eq([@item1, @item2])
542
789
  end
543
790
 
544
- it "should work for multiple includes, with rails 2.x syntax" do
545
- parts = Part.using(:canada).find(:all, :include => {:item => :client}, :conditions => {:clients => { :id => @client2.id}})
546
- parts.should == [@part1, @part2, @part3]
547
- parts.first.item.client.should == @client2
548
- end
549
-
550
- it "should work for multiple join, with rails 2.x syntax" do
551
- parts = Part.using(:canada).find(:all, :joins => {:item => :client}, :conditions => {:clients => { :id => @client2.id}})
552
- parts.should == [@part1, @part2, @part3]
553
- parts.first.item.client.should == @client2
791
+ it 'should work for include also, rails 3.x syntax' do
792
+ items = Item.using(:canada).includes(:client).where(:clients => { :id => @client2.id }).all
793
+ expect(items).to eq([@item1, @item2])
554
794
  end
555
795
  end
556
796
 
557
- describe "ActiveRecord::Base Validations" do
558
- it "should work correctly when using validations" do
559
- @key = Keyboard.create!(:name => "Key")
560
- lambda { Keyboard.using(:brazil).create!(:name => "Key") }.should_not raise_error()
561
- lambda { Keyboard.create!(:name => "Key") }.should raise_error()
797
+ describe 'ActiveRecord::Base Validations' do
798
+ it 'should work correctly when using validations' do
799
+ @key = Keyboard.create!(:name => 'Key')
800
+ expect { Keyboard.using(:brazil).create!(:name => 'Key') }.not_to raise_error
801
+ expect { Keyboard.create!(:name => 'Key') }.to raise_error(ActiveRecord::RecordInvalid)
562
802
  end
563
803
 
564
- it "should work correctly when using validations with using syntax" do
565
- @key = Keyboard.using(:brazil).create!(:name => "Key")
566
- lambda { Keyboard.create!(:name => "Key") }.should_not raise_error()
567
- lambda { Keyboard.using(:brazil).create!(:name => "Key") }.should raise_error()
804
+ it 'should work correctly when using validations with using syntax' do
805
+ @key = Keyboard.using(:brazil).create!(:name => 'Key')
806
+ expect { Keyboard.create!(:name => 'Key') }.not_to raise_error
807
+ expect { Keyboard.using(:brazil).create!(:name => 'Key') }
808
+ .to raise_error(ActiveRecord::RecordInvalid)
568
809
  end
569
810
  end
570
811
 
571
- describe "#replicated_model method" do
572
- it "should be replicated" do
812
+ describe '#replicated_model method' do
813
+ it 'should be replicated' do
573
814
  OctopusHelper.using_environment :production_replicated do
574
- ActiveRecord::Base.connection_proxy.instance_variable_get(:@replicated).should be_true
815
+ expect(ActiveRecord::Base.connection_proxy.replicated).to be true
575
816
  end
576
817
  end
577
818
 
578
- it "should mark the Cat model as replicated" do
819
+ it 'should mark the Cat model as replicated' do
579
820
  OctopusHelper.using_environment :production_replicated do
580
- User.replicated.should be_false
581
- Cat.replicated.should be_true
821
+ expect(User.replicated).to be_falsey
822
+ expect(Cat.replicated).to be true
823
+ end
824
+ end
825
+
826
+ it "should work on a fully replicated environment" do
827
+ OctopusHelper.using_environment :production_fully_replicated do
828
+ User.using(:slave1).create!(name: 'Thiago')
829
+ User.using(:slave2).create!(name: 'Thiago')
830
+
831
+ replicated_cat = User.find_by_name 'Thiago'
832
+
833
+ expect(replicated_cat.current_shard.to_s).to match(/master/)
582
834
  end
583
835
  end
584
836
  end