octoball 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Octoball
4
+ module ShardedPersistence
5
+ # cover methods using `self.class.connection`.
6
+ # NOTE: decrement! is implemented using increment!
7
+ [:update_columns, :increment!, :reload, :_delete_row, :_touch_row, :_update_row, :_create_record,
8
+ :transaction, :with_transaction_returning_status].each do |method|
9
+ class_eval <<-"END", __FILE__, __LINE__ + 1
10
+ def #{method}(*args, &block)
11
+ return super if !current_shard || current_shard == ActiveRecord::Base.current_shard
12
+ ActiveRecord::Base.connected_to(shard: current_shard, role: Octoball.current_role) do
13
+ super
14
+ end
15
+ end
16
+ ruby2_keywords(:#{method}) if respond_to?(:ruby2_keywords, true)
17
+ END
18
+ end
19
+
20
+ private
21
+
22
+ def init_internals
23
+ super
24
+ @current_shard = self.class.connection.current_shard
25
+ end
26
+ end
27
+
28
+ ::ActiveRecord::Base.prepend(ShardedPersistence)
29
+ end
@@ -0,0 +1,99 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Octoball
4
+ class RelationProxy < BasicObject
5
+ attr_reader :current_shard
6
+
7
+ def initialize(rel, shard)
8
+ @rel = rel
9
+ self.current_shard = shard
10
+ end
11
+
12
+ def current_shard=(shard)
13
+ @current_shard = shard
14
+ @rel.current_shard = shard unless @rel.is_a?(::Enumerator)
15
+ end
16
+
17
+ def using(shard)
18
+ self.current_shard = shard
19
+ self
20
+ end
21
+
22
+ def ar_relation
23
+ @rel
24
+ end
25
+
26
+ def respond_to?(method, include_all = false)
27
+ return true if [:ar_relation, :current_shard, :current_shard=, :using].include?(method)
28
+ @rel.respond_to?(method, include_all)
29
+ end
30
+
31
+ ENUM_METHODS = (::Enumerable.instance_methods - ::Object.instance_methods).reject do |m|
32
+ ::ActiveRecord::Relation.instance_method(m).source_location rescue nil
33
+ end + [:each, :map, :index_by]
34
+ ENUM_WITH_BLOCK_METHODS = [:find, :select, :none?, :any?, :one?, :many?, :sum]
35
+
36
+ def method_missing(method, *args, &block)
37
+ # raise NoMethodError unless the method is defined in @rel
38
+ return @rel.public_send(method, *args, &block) unless @rel.respond_to?(method)
39
+
40
+ preamble = <<-EOS
41
+ def #{method}(*margs, &mblock)
42
+ return @rel.#{method}(*margs, &mblock) unless @current_shard
43
+ EOS
44
+ postamble = <<-EOS
45
+ return ret unless ret.is_a?(::ActiveRecord::Relation) || ret.is_a?(::ActiveRecord::QueryMethods::WhereChain) || ret.is_a?(::Enumerator)
46
+ ::Octoball::RelationProxy.new(ret, @current_shard)
47
+ end
48
+ ruby2_keywords(:#{method}) if respond_to?(:ruby2_keywords, true)
49
+ EOS
50
+ connected_to = '::ActiveRecord::Base.connected_to(role: ::Octoball.current_role, shard: @current_shard)'
51
+
52
+ if ENUM_METHODS.include?(method)
53
+ ::Octoball::RelationProxy.class_eval <<-EOS, __FILE__, __LINE__ - 1
54
+ #{preamble}
55
+ ret = #{connected_to} { @rel.to_a }.#{method}(*margs, &mblock)
56
+ #{postamble}
57
+ EOS
58
+ elsif ENUM_WITH_BLOCK_METHODS.include?(method)
59
+ ::Octoball::RelationProxy.class_eval <<-EOS, __FILE__, __LINE__ - 1
60
+ #{preamble}
61
+ ret = nil
62
+ if mblock
63
+ ret = #{connected_to} { @rel.to_a }.#{method}(*margs, &mblock)
64
+ else
65
+ #{connected_to} { ret = @rel.#{method}(*margs, &mblock); nil } # return nil avoid loading relation
66
+ end
67
+ #{postamble}
68
+ EOS
69
+ else
70
+ ::Octoball::RelationProxy.class_eval <<-EOS, __FILE__, __LINE__ - 1
71
+ #{preamble}
72
+ ret = nil
73
+ #{connected_to} { ret = @rel.#{method}(*margs, &mblock); nil } # return nil to avoid loading relation
74
+ #{postamble}
75
+ EOS
76
+ end
77
+
78
+ public_send(method, *args, &block)
79
+ end
80
+ ruby2_keywords(:method_missing) if respond_to?(:ruby2_keywords, true)
81
+
82
+ def inspect
83
+ return @rel.inspect unless @current_shard
84
+ ::ActiveRecord::Base.connected_to(shard: @current_shard, role: ::Octoball.current_role) { @rel.inspect }
85
+ end
86
+
87
+ def ==(obj)
88
+ return false if obj.respond_to?(:current_shard) && obj.current_shard != @current_shard
89
+ return @rel == obj unless @current_shard
90
+ ::ActiveRecord::Base.connected_to(shard: @current_shard, role: ::Octoball.current_role) { @rel == obj }
91
+ end
92
+
93
+ def ===(obj)
94
+ return false if obj.respond_to?(:current_shard) && obj.current_shard != @current_shard
95
+ return @rel === obj unless @current_shard
96
+ ::ActiveRecord::Base.connected_to(shard: @current_shard, role: ::Octoball.current_role) { @rel === obj }
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Octoball
4
+ VERSION = '0.1.0'
5
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ $LOAD_PATH.push File.expand_path('../lib', __FILE__)
3
+ require 'octoball/version'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'octoball'
7
+ s.version = Octoball::VERSION
8
+ s.licenses = ['MIT']
9
+ s.summary = "Octopus-like Database Sharding Helper for ActiveRecord 6.1+"
10
+ s.description = "Octoball provides Octopus-like database sharding helper methods for ActiveRecord 6.1 or later, using Rails' native horizontal sharding handling. This provides migration path to Rails 6.1+ for applications using Octopus gem with older Rails."
11
+ s.authors = ["Tomoki Sekiyama"]
12
+ s.email = 'tomoki.sekiyama@aktsk.jp'
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {spec}/*`.split("\n")
15
+ s.homepage = 'https://github.com/aktsk/octoball'
16
+ s.require_paths = ['lib']
17
+
18
+ s.required_ruby_version = '>= 2.7.0'
19
+
20
+ s.add_dependency 'activerecord', '>= 6.1'
21
+ s.add_dependency 'activesupport', '>= 6.1'
22
+
23
+ s.add_development_dependency 'mysql2'
24
+ s.add_development_dependency 'rake'
25
+ s.add_development_dependency 'rspec', '>= 3'
26
+ s.add_development_dependency 'rubocop'
27
+ s.add_development_dependency 'byebug'
28
+ end
@@ -0,0 +1,84 @@
1
+ class TestTables < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table(:users) do |u|
4
+ u.string :name
5
+ u.integer :number
6
+ u.boolean :admin
7
+ u.datetime :created_at
8
+ u.datetime :updated_at
9
+ end
10
+
11
+ create_table(:clients) do |u|
12
+ u.string :country
13
+ u.string :name
14
+ end
15
+
16
+ create_table(:cats) do |u|
17
+ u.string :name
18
+ end
19
+
20
+ create_table(:items) do |u|
21
+ u.string :name
22
+ u.integer :client_id
23
+ end
24
+
25
+ create_table(:computers) do |u|
26
+ u.string :name
27
+ end
28
+
29
+ create_table(:keyboards) do |u|
30
+ u.string :name
31
+ u.integer :computer_id
32
+ end
33
+
34
+ create_table(:roles) do |u|
35
+ u.string :name
36
+ end
37
+
38
+ create_table(:permissions) do |u|
39
+ u.string :name
40
+ end
41
+
42
+ create_table(:permissions_roles, :id => false) do |u|
43
+ u.integer :role_id
44
+ u.integer :permission_id
45
+ end
46
+
47
+ create_table(:assignments) do |u|
48
+ u.integer :programmer_id
49
+ u.integer :project_id
50
+ end
51
+
52
+ create_table(:programmers) do |u|
53
+ u.string :name
54
+ end
55
+
56
+ create_table(:projects) do |u|
57
+ u.string :name
58
+ end
59
+
60
+ create_table(:comments) do |u|
61
+ u.string :name
62
+ u.string :commentable_type
63
+ u.integer :commentable_id
64
+ u.boolean :open, default: false
65
+ end
66
+
67
+ create_table(:parts) do |u|
68
+ u.string :name
69
+ u.integer :item_id
70
+ end
71
+
72
+ create_table(:yummy) do |u|
73
+ u.string :name
74
+ end
75
+
76
+ create_table(:adverts) do |u|
77
+ u.string :name
78
+ end
79
+
80
+ create_table(:custom) do |u|
81
+ u.string :value
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,19 @@
1
+ class AloneShardTables < ActiveRecord::Migration[6.1]
2
+ def change
3
+ create_table(:mmorpg_players) do |u|
4
+ u.string :player_name
5
+ end
6
+
7
+ create_table(:weapons) do |u|
8
+ u.integer :mmorpg_player_id
9
+ u.string :name
10
+ u.string :hand
11
+ end
12
+
13
+ create_table(:skills) do |u|
14
+ u.integer :mmorpg_player_id
15
+ u.integer :weapon_id
16
+ u.string :name
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationRecord < ActiveRecord::Base
4
+ self.abstract_class = true
5
+
6
+ connects_to shards: {
7
+ master: { writing: :shard1 },
8
+ brazil: { writing: :shard2 },
9
+ canada: { writing: :shard3 },
10
+ russia: { writing: :shard4 },
11
+ alone_shard: { writing: :shard5 },
12
+ }
13
+ end
@@ -0,0 +1,1024 @@
1
+ require 'spec_helper'
2
+
3
+ describe Octoball::ShardedSingularAssociation, :shards => [:brazil, :master, :canada] do
4
+ describe 'when you have a 1 x 1 relationship' do
5
+ before(:each) do
6
+ @computer_brazil = Computer.using(:brazil).create!(:name => 'Computer Brazil')
7
+ @computer_master = Computer.create!(:name => 'Computer Brazil')
8
+ @keyboard_brazil = Keyboard.using(:brazil).create!(:name => 'Keyboard Brazil', :computer => @computer_brazil)
9
+ @keyboard_master = Keyboard.create!(:name => 'Keyboard Master', :computer => @computer_master)
10
+ end
11
+
12
+ it 'should find the models' do
13
+ expect(@keyboard_master.computer).to eq(@computer_master)
14
+ expect(@keyboard_brazil.computer).to eq(@computer_brazil)
15
+ end
16
+
17
+ it 'should read correctly the relationed model' do
18
+ new_computer_brazil = Computer.using(:brazil).create!(:name => 'New Computer Brazil')
19
+ _new_computer_hello = Computer.create!(:name => 'New Computer Brazil')
20
+ @keyboard_brazil.computer = new_computer_brazil
21
+ @keyboard_brazil.save
22
+ @keyboard_brazil.reload
23
+ expect(@keyboard_brazil.computer_id).to eq(new_computer_brazil.id)
24
+ expect(@keyboard_brazil.computer).to eq(new_computer_brazil)
25
+ new_computer_brazil.save
26
+ new_computer_brazil.reload
27
+ expect(new_computer_brazil.keyboard).to eq(@keyboard_brazil)
28
+ end
29
+
30
+ it 'should join/merge correctly with the relationed model' do
31
+ new_computer_brazil = Computer.using(:brazil).create!(:name => 'New Computer Brazil')
32
+ @keyboard_brazil.computer = new_computer_brazil
33
+ @keyboard_brazil.save
34
+ expect(Keyboard.using(:brazil).joins(:computer).merge(Computer.where(name: 'New Computer Brazil'))).to eq([@keyboard_brazil])
35
+ expect(Keyboard.using(:brazil).joins(:computer).merge(Computer.using(:master).where(name: 'New Computer Brazil'))).to eq([@keyboard_brazil])
36
+ end
37
+
38
+ it 'should work when using #build_computer or #build_keyboard' do
39
+ c = Computer.using(:brazil).create!(:name => 'Computer Brazil')
40
+ k = c.build_keyboard(:name => 'Building keyboard')
41
+ c.save
42
+ k.save
43
+ expect(c.keyboard).to eq(k)
44
+ expect(k.computer_id).to eq(c.id)
45
+ expect(k.computer).to eq(c)
46
+ end
47
+
48
+ it 'should work when using #create_computer or #create_keyboard' do
49
+ c = Computer.using(:brazil).create!(:name => 'Computer Brazil')
50
+ k = c.create_keyboard(:name => 'Building keyboard')
51
+ c.save
52
+ k.save
53
+ expect(c.keyboard).to eq(k)
54
+ expect(k.computer_id).to eq(c.id)
55
+ expect(k.computer).to eq(c)
56
+ end
57
+
58
+ it 'should include models' do
59
+ c = Computer.using(:brazil).create!(:name => 'Computer Brazil')
60
+ k = c.create_keyboard(:name => 'Building keyboard')
61
+ c.save
62
+ k.save
63
+
64
+ expect(Computer.using(:brazil).includes(:keyboard).find(c.id)).to eq(c)
65
+ end
66
+ end
67
+
68
+ describe 'when you have a N x N relationship' do
69
+ before(:each) do
70
+ @brazil_role = Role.using(:brazil).create!(:name => 'Brazil Role')
71
+ @master_role = Role.create!(:name => 'Master Role')
72
+ @permission_brazil = Permission.using(:brazil).create!(:name => 'Brazil Permission')
73
+ @permission_master = Permission.using(:master).create!(:name => 'Master Permission')
74
+ @brazil_role.permissions << @permission_brazil
75
+ @brazil_role.save
76
+ Client.using(:master).create!(:name => 'teste')
77
+ end
78
+
79
+ it 'should find all models in the specified shard' do
80
+ expect(@brazil_role.permission_ids).to eq([@permission_brazil.id])
81
+ expect(@brazil_role.permissions).to eq([@permission_brazil])
82
+
83
+ expect(@brazil_role.permissions.first).to eq(@permission_brazil)
84
+ expect(@brazil_role.permissions.first!).to eq(@permission_brazil)
85
+ expect(@brazil_role.permissions.last).to eq(@permission_brazil)
86
+ end
87
+
88
+ it 'should finds the client that the item belongs' do
89
+ expect(@permission_brazil.role_ids).to eq([@brazil_role.id])
90
+ expect(@permission_brazil.roles).to eq([@brazil_role])
91
+
92
+ expect(@permission_brazil.roles.first).to eq(@brazil_role)
93
+ expect(@permission_brazil.roles.first!).to eq(@brazil_role)
94
+ expect(@permission_brazil.roles.last).to eq(@brazil_role)
95
+ end
96
+
97
+ it 'should update the attribute for the item' do
98
+ new_brazil_role = Role.using(:brazil).create!(:name => 'new Role')
99
+ @permission_brazil.roles = [new_brazil_role]
100
+ expect(@permission_brazil.roles).to eq([new_brazil_role])
101
+ @permission_brazil.save
102
+ @permission_brazil.reload
103
+ expect(@permission_brazil.role_ids).to eq([new_brazil_role.id])
104
+ expect(@permission_brazil.roles).to eq([new_brazil_role])
105
+ end
106
+
107
+ it 'should work for build method' do
108
+ new_brazil_role = Role.using(:brazil).create!(:name => 'Brazil Role')
109
+ c = new_brazil_role.permissions.create(:name => 'new Permission')
110
+ c.save
111
+ new_brazil_role.save
112
+ expect(c.roles).to eq([new_brazil_role])
113
+ expect(new_brazil_role.permissions).to eq([c])
114
+ end
115
+
116
+ describe 'it should work when using' do
117
+ before(:each) do
118
+ @permission_brazil_2 = Permission.using(:brazil).create!(:name => 'Brazil Item 2')
119
+ @role = Role.using(:brazil).create!(:name => 'testes')
120
+ end
121
+
122
+ it 'update' do
123
+ @permission_brazil_2.update(:role_ids => [@role.id])
124
+ expect(@permission_brazil_2.roles.to_set).to eq([@role].to_set)
125
+ end
126
+
127
+ it '<<' do
128
+ @permission_brazil_2.roles << @role
129
+ @role.save
130
+ @permission_brazil_2.save
131
+ @permission_brazil_2.reload
132
+ expect(@permission_brazil_2.roles.to_set).to eq([@role].to_set)
133
+ end
134
+
135
+ it 'build' do
136
+ role = @permission_brazil_2.roles.build(:name => 'Builded Role')
137
+ @permission_brazil_2.save
138
+ expect(@permission_brazil_2.roles.to_set).to eq([role].to_set)
139
+ end
140
+
141
+ it 'create' do
142
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
143
+ expect(@permission_brazil_2.roles.to_set).to eq([role].to_set)
144
+ end
145
+
146
+ it 'create' do
147
+ role = @permission_brazil_2.roles.create!(:name => 'Builded Role')
148
+ expect(@permission_brazil_2.roles.to_set).to eq([role].to_set)
149
+ end
150
+
151
+ it 'count' do
152
+ expect(@permission_brazil_2.roles.count).to eq(0)
153
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
154
+ expect(@permission_brazil_2.roles.count).to eq(1)
155
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
156
+ expect(@permission_brazil_2.roles.count).to eq(2)
157
+ end
158
+
159
+ it 'size' do
160
+ expect(@permission_brazil_2.roles.size).to eq(0)
161
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
162
+ expect(@permission_brazil_2.roles.size).to eq(1)
163
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
164
+ expect(@permission_brazil_2.roles.size).to eq(2)
165
+ end
166
+
167
+ it 'length' do
168
+ expect(@permission_brazil_2.roles.length).to eq(0)
169
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
170
+ expect(@permission_brazil_2.roles.length).to eq(1)
171
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
172
+ expect(@permission_brazil_2.roles.length).to eq(2)
173
+ end
174
+
175
+ it 'empty?' do
176
+ expect(@permission_brazil_2.roles.empty?).to be true
177
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
178
+ expect(@permission_brazil_2.roles.empty?).to be false
179
+ end
180
+
181
+ it 'delete_all' do
182
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
183
+ expect(@permission_brazil_2.roles.empty?).to be false
184
+ @permission_brazil_2.roles.delete_all
185
+ expect(@permission_brazil_2.roles.empty?).to be true
186
+ end
187
+
188
+ it 'destroy_all' do
189
+ _role = @permission_brazil_2.roles.create(:name => 'Builded Role')
190
+ expect(@permission_brazil_2.roles.empty?).to be false
191
+ @permission_brazil_2.roles.destroy_all
192
+ expect(@permission_brazil_2.roles.empty?).to be true
193
+ end
194
+
195
+ it 'find' do
196
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
197
+ expect(@permission_brazil_2.roles.first).to eq(role)
198
+ @permission_brazil_2.roles.destroy_all
199
+ expect(@permission_brazil_2.roles.first).to be_nil
200
+ end
201
+
202
+ it 'where' do
203
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
204
+ expect(@permission_brazil_2.roles.where('1=1')).to eq([role])
205
+ @permission_brazil_2.roles.destroy_all
206
+ expect(@permission_brazil_2.roles.where('1=1')).to be_empty
207
+ end
208
+
209
+ it 'map' do
210
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
211
+ expect(@permission_brazil_2.roles.map(&:id)).to eq([role.id])
212
+ @permission_brazil_2.roles.destroy_all
213
+ expect(@permission_brazil_2.roles.map(&:id)).to be_empty
214
+ end
215
+
216
+ it 'where + map' do
217
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
218
+ expect(@permission_brazil_2.roles.where('1=1').map(&:id)).to eq([role.id])
219
+ @permission_brazil_2.roles.destroy_all
220
+ expect(@permission_brazil_2.roles.where('1=1').map(&:id)).to be_empty
221
+ end
222
+
223
+ # each_with_index is not listed in active_record/relation/delegation.rb
224
+ it 'where + each_with_index + map (enum method chain)' do
225
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
226
+ expect(@permission_brazil_2.roles.where('1=1').each_with_index.map { |r, i| [r.id, i]}).to eq([[role.id, 0]])
227
+ @permission_brazil_2.roles.destroy_all
228
+ expect(@permission_brazil_2.roles.where('1=1').each_with_index.map { |r, i| [r.id, i]}).to be_empty
229
+ end
230
+
231
+ # sum & index_by is specialized in active_support/core_ext/enumerable.rb
232
+ it 'where + sum' do
233
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
234
+ expect(@permission_brazil_2.roles.where('1=1').sum(&:id)).to eq(role.id)
235
+ @permission_brazil_2.roles.destroy_all
236
+ expect(@permission_brazil_2.roles.where('1=1').sum(&:id)).to eq(0)
237
+ end
238
+
239
+ it 'where + index_by' do
240
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
241
+ expect(@permission_brazil_2.roles.where('1=1').index_by(&:id)).to eq(role.id => role)
242
+ @permission_brazil_2.roles.destroy_all
243
+ expect(@permission_brazil_2.roles.where('1=1').index_by(&:id)).to be_empty
244
+ end
245
+
246
+ it 'where + find' do
247
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
248
+ expect(@permission_brazil_2.roles.where('1=1').find([role.id])).to eq([role])
249
+ @permission_brazil_2.roles.destroy_all
250
+ expect { @permission_brazil_2.roles.where('1=1').find([role.id]) }.to raise_error ActiveRecord::RecordNotFound
251
+ end
252
+
253
+ it 'where + find with block' do
254
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
255
+ expect(@permission_brazil_2.roles.where('1=1').find { |r| r.id == role.id }).to eq(role)
256
+ @permission_brazil_2.roles.destroy_all
257
+ expect(@permission_brazil_2.roles.where('1=1').find { |r| r.id == role.id }).to be_nil
258
+ end
259
+
260
+ it 'where + select' do
261
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
262
+ expect(@permission_brazil_2.roles.where('1=1').select(:name).first.name).to eq(role.name)
263
+ @permission_brazil_2.roles.destroy_all
264
+ expect(@permission_brazil_2.roles.where('1=1').select(:name)).to be_empty
265
+ end
266
+
267
+ it 'where + select with block' do
268
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
269
+ expect(@permission_brazil_2.roles.where('1=1').select { |r| r.id == role.id }).to eq([role])
270
+ @permission_brazil_2.roles.destroy_all
271
+ expect(@permission_brazil_2.roles.where('1=1').select { |r| r.id == role.id }).to be_empty
272
+ end
273
+
274
+ it 'where + any?' do
275
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
276
+ expect(@permission_brazil_2.roles.where('1=1').any?).to be true
277
+ @permission_brazil_2.roles.destroy_all
278
+ expect(@permission_brazil_2.roles.where('1=1').any?).to be false
279
+ end
280
+
281
+ it 'where + any? with block' do
282
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
283
+ expect(@permission_brazil_2.roles.where('1=1').any? { |r| r.id == role.id }).to be true
284
+ @permission_brazil_2.roles.destroy_all
285
+ expect(@permission_brazil_2.roles.where('1=1').any? { |r| r.id == role.id }).to be false
286
+ end
287
+
288
+ it 'exists?' do
289
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
290
+ expect(@permission_brazil_2.roles.exists?(role.id)).to be true
291
+ @permission_brazil_2.roles.destroy_all
292
+ expect(@permission_brazil_2.roles.exists?(role.id)).to be false
293
+ end
294
+
295
+ it 'clear' do
296
+ _rol = @permission_brazil_2.roles.create(:name => 'Builded Role')
297
+ expect(@permission_brazil_2.roles.empty?).to be false
298
+ @permission_brazil_2.roles.clear
299
+ expect(@permission_brazil_2.roles.empty?).to be true
300
+ end
301
+
302
+ it 'delete' do
303
+ role = @permission_brazil_2.roles.create(:name => 'Builded Role')
304
+ expect(@permission_brazil_2.roles.empty?).to be false
305
+ @permission_brazil_2.roles.delete(role)
306
+ @permission_brazil_2.reload
307
+ @role.reload
308
+ expect(@role.permissions).to eq([])
309
+ expect(@permission_brazil_2.roles).to eq([])
310
+ end
311
+ end
312
+ end
313
+
314
+ describe 'when you have has_many :through' do
315
+ before(:each) do
316
+ @programmer = Programmer.using(:brazil).create!(:name => 'Thiago')
317
+ @project = Project.using(:brazil).create!(:name => 'RubySoc')
318
+ @project2 = Project.using(:brazil).create!(:name => 'Cobol Application')
319
+ @programmer.projects << @project
320
+ @programmer.save
321
+ Project.using(:master).create!(:name => 'Project Master')
322
+ end
323
+
324
+ it 'should find all models in the specified shard' do
325
+ expect(@programmer.project_ids).to eq([@project.id])
326
+ expect(@programmer.projects).to eq([@project])
327
+
328
+ expect(@programmer.projects.first).to eq(@project)
329
+ expect(@programmer.projects.last).to eq(@project)
330
+ end
331
+
332
+ it 'should update the attribute for the item' do
333
+ new_brazil_programmer = Programmer.using(:brazil).create!(:name => 'Joao')
334
+ @project.programmers = [new_brazil_programmer]
335
+ expect(@project.programmers).to eq([new_brazil_programmer])
336
+ @project.save
337
+ @project.reload
338
+ expect(@project.programmer_ids).to eq([new_brazil_programmer.id])
339
+ expect(@project.programmers).to eq([new_brazil_programmer])
340
+ end
341
+
342
+ it 'should work for create method' do
343
+ new_brazil_programmer = Programmer.using(:brazil).create!(:name => 'Joao')
344
+ c = new_brazil_programmer.projects.create(:name => 'new Project')
345
+ c.save
346
+ new_brazil_programmer.save
347
+ expect(c.programmers).to eq([new_brazil_programmer])
348
+ expect(new_brazil_programmer.projects).to eq([c])
349
+ end
350
+
351
+ describe 'it should work when using' do
352
+ before(:each) do
353
+ @new_brazil_programmer = Programmer.using(:brazil).create!(:name => 'Jose')
354
+ @project = Project.using(:brazil).create!(:name => 'VB Application :-(')
355
+ end
356
+
357
+ it 'update' do
358
+ @new_brazil_programmer.update(:project_ids => [@project.id])
359
+ expect(@new_brazil_programmer.projects.to_set).to eq([@project].to_set)
360
+ end
361
+
362
+ it '<<' do
363
+ @new_brazil_programmer.projects << @project
364
+ @project.save
365
+ @new_brazil_programmer.save
366
+ @new_brazil_programmer.reload
367
+ expect(@new_brazil_programmer.projects.to_set).to eq([@project].to_set)
368
+ end
369
+
370
+ it 'build' do
371
+ role = @new_brazil_programmer.projects.build(:name => 'New VB App :-/')
372
+ @new_brazil_programmer.save
373
+ expect(@new_brazil_programmer.projects.to_set).to eq([role].to_set)
374
+ end
375
+
376
+ it 'create' do
377
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
378
+ expect(@new_brazil_programmer.projects.to_set).to eq([role].to_set)
379
+ end
380
+
381
+ it 'create' do
382
+ role = @new_brazil_programmer.projects.create!(:name => 'New VB App :-/')
383
+ expect(@new_brazil_programmer.projects.to_set).to eq([role].to_set)
384
+ end
385
+
386
+ it 'count' do
387
+ expect(@new_brazil_programmer.projects.count).to eq(0)
388
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
389
+ expect(@new_brazil_programmer.projects.count).to eq(1)
390
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
391
+ expect(@new_brazil_programmer.projects.count).to eq(2)
392
+ end
393
+
394
+ it 'size' do
395
+ expect(@new_brazil_programmer.projects.size).to eq(0)
396
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
397
+ expect(@new_brazil_programmer.projects.size).to eq(1)
398
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
399
+ expect(@new_brazil_programmer.projects.size).to eq(2)
400
+ end
401
+
402
+ it 'length' do
403
+ expect(@new_brazil_programmer.projects.length).to eq(0)
404
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
405
+ expect(@new_brazil_programmer.projects.length).to eq(1)
406
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
407
+ expect(@new_brazil_programmer.projects.length).to eq(2)
408
+ end
409
+
410
+ it 'empty?' do
411
+ expect(@new_brazil_programmer.projects.empty?).to be true
412
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
413
+ expect(@new_brazil_programmer.projects.empty?).to be false
414
+ end
415
+
416
+ it 'delete_all' do
417
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
418
+ expect(@new_brazil_programmer.projects.empty?).to be false
419
+ @new_brazil_programmer.projects.delete_all
420
+ expect(@new_brazil_programmer.projects.empty?).to be true
421
+ end
422
+
423
+ it 'destroy_all' do
424
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
425
+ expect(@new_brazil_programmer.projects.empty?).to be false
426
+ @new_brazil_programmer.projects.destroy_all
427
+ expect(@new_brazil_programmer.projects.empty?).to be true
428
+ end
429
+
430
+ it 'find' do
431
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
432
+ expect(@new_brazil_programmer.projects.first).to eq(role)
433
+ @new_brazil_programmer.projects.destroy_all
434
+ expect(@new_brazil_programmer.projects.first).to be_nil
435
+ end
436
+
437
+ it 'where' do
438
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
439
+ expect(@new_brazil_programmer.projects.where('1=1')).to eq([role])
440
+ @new_brazil_programmer.projects.destroy_all
441
+ expect(@new_brazil_programmer.projects.where('1=1')).to be_empty
442
+ end
443
+
444
+ it 'map' do
445
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
446
+ expect(@new_brazil_programmer.projects.map(&:id)).to eq([role.id])
447
+ @new_brazil_programmer.projects.destroy_all
448
+ expect(@new_brazil_programmer.projects.map(&:id)).to be_empty
449
+ end
450
+
451
+ it 'where + map' do
452
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
453
+ expect(@new_brazil_programmer.projects.where('1=1').map(&:id)).to eq([role.id])
454
+ @new_brazil_programmer.projects.destroy_all
455
+ expect(@new_brazil_programmer.projects.where('1=1').map(&:id)).to be_empty
456
+ end
457
+
458
+ it 'where + each_with_index + map (enum method chain)' do
459
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
460
+ expect(@new_brazil_programmer.projects.where('1=1').each_with_index.map { |r, i| [r.id, i] }).to eq([[role.id, 0]])
461
+ @new_brazil_programmer.projects.destroy_all
462
+ expect(@new_brazil_programmer.projects.where('1=1').each_with_index.map { |r, i| [r.id, i] }).to be_empty
463
+ end
464
+
465
+ it 'where + sum' do
466
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
467
+ expect(@new_brazil_programmer.projects.where('1=1').sum(&:id)).to eq(role.id)
468
+ @new_brazil_programmer.projects.destroy_all
469
+ expect(@new_brazil_programmer.projects.where('1=1').sum(&:id)).to eq(0)
470
+ end
471
+
472
+ it 'where + index_by' do
473
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
474
+ expect(@new_brazil_programmer.projects.where('1=1').index_by(&:id)).to eq(role.id => role)
475
+ @new_brazil_programmer.projects.destroy_all
476
+ expect(@new_brazil_programmer.projects.where('1=1').index_by(&:id)).to be_empty
477
+ end
478
+
479
+ it 'where + find' do
480
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
481
+ expect(@new_brazil_programmer.projects.where('1=1').find(role.id)).to eq(role)
482
+ @new_brazil_programmer.projects.destroy_all
483
+ expect { @new_brazil_programmer.projects.where('1=1').find(role.id) }.to raise_error ActiveRecord::RecordNotFound
484
+ end
485
+
486
+ it 'where + find with block' do
487
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
488
+ expect(@new_brazil_programmer.projects.where('1=1').find { |r| r.id == role.id }).to eq(role)
489
+ @new_brazil_programmer.projects.destroy_all
490
+ expect(@new_brazil_programmer.projects.where('1=1').find { |r| r.id == role.id }).to be_nil
491
+ end
492
+
493
+ it 'where + select' do
494
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
495
+ expect(@new_brazil_programmer.projects.where('1=1').select(:name).first.name).to eq(role.name)
496
+ @new_brazil_programmer.projects.destroy_all
497
+ expect(@new_brazil_programmer.projects.where('1=1').select(:name)).to be_empty
498
+ end
499
+
500
+ it 'where + select with block' do
501
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
502
+ expect(@new_brazil_programmer.projects.where('1=1').select { |r| r.id == role.id }).to eq([role])
503
+ @new_brazil_programmer.projects.destroy_all
504
+ expect(@new_brazil_programmer.projects.where('1=1').select { |r| r.id == role.id }).to be_empty
505
+ end
506
+
507
+ it 'where + any?' do
508
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
509
+ expect(@new_brazil_programmer.projects.where('1=1').any?).to be true
510
+ @new_brazil_programmer.projects.destroy_all
511
+ expect(@new_brazil_programmer.projects.where('1=1').any?).to be false
512
+ end
513
+
514
+ it 'where + any? with block' do
515
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
516
+ expect(@new_brazil_programmer.projects.where('1=1').any? { |r| r.id == role.id }).to be true
517
+ @new_brazil_programmer.projects.destroy_all
518
+ expect(@new_brazil_programmer.projects.where('1=1').any? { |r| r.id == role.id }).to be false
519
+ end
520
+
521
+ it 'exists?' do
522
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
523
+ expect(@new_brazil_programmer.projects.exists?(role.id)).to be true
524
+ @new_brazil_programmer.projects.destroy_all
525
+ expect(@new_brazil_programmer.projects.exists?(role.id)).to be false
526
+ end
527
+
528
+ it 'clear' do
529
+ _role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
530
+ expect(@new_brazil_programmer.projects.empty?).to be false
531
+ @new_brazil_programmer.projects.clear
532
+ expect(@new_brazil_programmer.projects.empty?).to be true
533
+ end
534
+
535
+ it 'delete' do
536
+ role = @new_brazil_programmer.projects.create(:name => 'New VB App :-/')
537
+ expect(@new_brazil_programmer.projects.empty?).to be false
538
+ @new_brazil_programmer.projects.delete(role)
539
+ @new_brazil_programmer.reload
540
+ @project.reload
541
+ expect(@project.programmers).to eq([])
542
+ expect(@new_brazil_programmer.projects).to eq([])
543
+ end
544
+ end
545
+ end
546
+
547
+ describe 'when you have a 1 x N relationship' do
548
+ before(:each) do
549
+ @brazil_client = Client.using(:brazil).create!(:name => 'Brazil Client')
550
+ @master_client = Client.create!(:name => 'Master Client')
551
+ @item_brazil = Item.using(:brazil).create!(:name => 'Brazil Item', :client => @brazil_client)
552
+ @item_master = Item.create!(:name => 'Master Item', :client => @master_client)
553
+ @brazil_client = Client.using(:brazil).find_by_name('Brazil Client')
554
+ Client.using(:master).create!(:name => 'teste')
555
+ end
556
+
557
+ it 'should find all models in the specified shard' do
558
+ expect(@brazil_client.item_ids).to eq([@item_brazil.id])
559
+ expect(@brazil_client.items).to eq([@item_brazil])
560
+
561
+ expect(@brazil_client.items.last).to eq(@item_brazil)
562
+ expect(@brazil_client.items.first).to eq(@item_brazil)
563
+ end
564
+
565
+ it 'should finds the client that the item belongs' do
566
+ expect(@item_brazil.client).to eq(@brazil_client)
567
+ end
568
+
569
+ it 'should raise error if you try to add a record from a different shard' do
570
+ expect do
571
+ @brazil_client.items << Item.using(:canada).create!(:name => 'New User')
572
+ end.to raise_error(Octoball::MismatchedShards)
573
+ end
574
+
575
+ it 'should make difference if the shard is a symbol for raising MismatchedShards' do
576
+ expect do
577
+ @brazil_client.items << Item.using(:brazil).create!(:name => 'New Brazil Item')
578
+ end.not_to raise_error
579
+ end
580
+
581
+ it 'should update the attribute for the item' do
582
+ new_brazil_client = Client.using(:brazil).create!(:name => 'new Client')
583
+ @item_brazil.client = new_brazil_client
584
+ expect(@item_brazil.client).to eq(new_brazil_client)
585
+ @item_brazil.save
586
+ @item_brazil.reload
587
+ expect(@item_brazil.client_id).to eq(new_brazil_client.id)
588
+ expect(@item_brazil.client).to eq(new_brazil_client)
589
+ end
590
+
591
+ it 'should work for build method' do
592
+ item2 = Item.using(:brazil).create!(:name => 'Brazil Item')
593
+ c = item2.create_client(:name => 'new Client')
594
+ c.save
595
+ item2.save
596
+ expect(item2.client).to eq(c)
597
+ expect(c.items).to eq([item2])
598
+ end
599
+
600
+ context 'when calling methods on a collection generated by an association' do
601
+ let(:collection) { @brazil_client.items }
602
+ before :each do
603
+ @brazil_client.items.create(:name => 'Brazil Item #2')
604
+ end
605
+
606
+ it "can call collection indexes directly without resetting the collection's current_shard" do
607
+ last_item = collection[1]
608
+ expect(collection.length).to eq(2)
609
+ expect(collection).to eq([collection[0], last_item])
610
+ end
611
+
612
+ it "can call methods on the collection without resetting the collection's current_shard" do
613
+ last_item = collection[collection.size - 1]
614
+ expect(collection.length).to eq(2)
615
+ expect(collection).to eq([collection[0], last_item])
616
+ end
617
+ end
618
+
619
+ describe 'it should work when using' do
620
+ before(:each) do
621
+ @item_brazil_2 = Item.using(:brazil).create!(:name => 'Brazil Item 2')
622
+ expect(@brazil_client.items.to_set).to eq([@item_brazil].to_set)
623
+ end
624
+
625
+ it 'update' do
626
+ @brazil_client.update(:item_ids => [@item_brazil_2.id, @item_brazil.id])
627
+ expect(@brazil_client.items.to_set).to eq([@item_brazil, @item_brazil_2].to_set)
628
+ end
629
+
630
+ it '<<' do
631
+ @brazil_client.items << @item_brazil_2
632
+ expect(@brazil_client.items.to_set).to eq([@item_brazil, @item_brazil_2].to_set)
633
+ end
634
+
635
+ it 'all' do
636
+ item = @brazil_client.items.build(:name => 'Builded Item')
637
+ item.save
638
+ i = @brazil_client.items
639
+ expect(i.to_set).to eq([@item_brazil, item].to_set)
640
+ expect(i.reload.all.to_set).to eq([@item_brazil, item].to_set)
641
+ end
642
+
643
+ it 'build' do
644
+ item = @brazil_client.items.build(:name => 'Builded Item')
645
+ item.save
646
+ expect(@brazil_client.items.to_set).to eq([@item_brazil, item].to_set)
647
+ end
648
+
649
+ it 'create' do
650
+ item = @brazil_client.items.create(:name => 'Builded Item')
651
+ expect(@brazil_client.items.to_set).to eq([@item_brazil, item].to_set)
652
+ end
653
+
654
+ it 'count' do
655
+ expect(@brazil_client.items.count).to eq(1)
656
+ _itm = @brazil_client.items.create(:name => 'Builded Item')
657
+ expect(@brazil_client.items.count).to eq(2)
658
+ end
659
+
660
+ it 'size' do
661
+ expect(@brazil_client.items.size).to eq(1)
662
+ _itm = @brazil_client.items.create(:name => 'Builded Item')
663
+ expect(@brazil_client.items.size).to eq(2)
664
+ end
665
+
666
+ it 'create!' do
667
+ item = @brazil_client.items.create!(:name => 'Builded Item')
668
+ expect(@brazil_client.items.to_set).to eq([@item_brazil, item].to_set)
669
+ end
670
+
671
+ it 'length' do
672
+ expect(@brazil_client.items.length).to eq(1)
673
+ _itm = @brazil_client.items.create(:name => 'Builded Item')
674
+ expect(@brazil_client.items.length).to eq(2)
675
+ end
676
+
677
+ it 'empty?' do
678
+ expect(@brazil_client.items.empty?).to be false
679
+ c = Client.create!(:name => 'Client1')
680
+ expect(c.items.empty?).to be true
681
+ end
682
+
683
+ it 'delete' do
684
+ expect(@brazil_client.items.empty?).to be false
685
+ @brazil_client.items.delete(@item_brazil)
686
+ @brazil_client.reload
687
+ @item_brazil.reload
688
+ expect(@item_brazil.client).to be_nil
689
+ expect(@brazil_client.items).to eq([])
690
+ expect(@brazil_client.items.empty?).to be true
691
+ end
692
+
693
+ it 'delete_all' do
694
+ expect(@brazil_client.items.empty?).to be false
695
+ @brazil_client.items.delete_all
696
+ expect(@brazil_client.items.empty?).to be true
697
+ end
698
+
699
+ it 'destroy_all' do
700
+ expect(@brazil_client.items.empty?).to be false
701
+ @brazil_client.items.destroy_all
702
+ expect(@brazil_client.items.empty?).to be true
703
+ end
704
+
705
+ it 'find' do
706
+ expect(@brazil_client.items.first).to eq(@item_brazil)
707
+ @brazil_client.items.destroy_all
708
+ expect(@brazil_client.items.first).to be_nil
709
+ end
710
+
711
+ it 'where' do
712
+ expect(@brazil_client.items.where('1=1')).to eq([@item_brazil])
713
+ @brazil_client.items.destroy_all
714
+ expect(@brazil_client.items.where('1=1')).to be_empty
715
+ end
716
+
717
+ it 'map' do
718
+ expect(@brazil_client.items.map(&:id)).to eq([@item_brazil.id])
719
+ @brazil_client.items.destroy_all
720
+ expect(@brazil_client.items.map(&:id)).to be_empty
721
+ end
722
+
723
+ it 'where + map' do
724
+ expect(@brazil_client.items.where('1=1').map(&:id)).to eq([@item_brazil.id])
725
+ @brazil_client.items.destroy_all
726
+ expect(@brazil_client.items.where('1=1').map(&:id)).to be_empty
727
+ end
728
+
729
+ it 'where + each_with_index + map (enum method chain)' do
730
+ expect(@brazil_client.items.where('1=1').each_with_index.map { |r, i| [r.id, i]}).to eq([[@item_brazil.id, 0]])
731
+ @brazil_client.items.destroy_all
732
+ expect(@brazil_client.items.where('1=1').each_with_index.map { |r, i| [r.id, i]}).to be_empty
733
+ end
734
+
735
+ it 'where + sum' do
736
+ expect(@brazil_client.items.where('1=1').sum(&:id)).to eq(@item_brazil.id)
737
+ @brazil_client.items.destroy_all
738
+ expect(@brazil_client.items.where('1=1').sum(&:id)).to eq(0)
739
+ end
740
+
741
+ it 'where + index_by' do
742
+ expect(@brazil_client.items.where('1=1').index_by(&:id)).to eq(@item_brazil.id => @item_brazil)
743
+ @brazil_client.items.destroy_all
744
+ expect(@brazil_client.items.where('1=1').index_by(&:id)).to be_empty
745
+ end
746
+
747
+ it 'where + find' do
748
+ expect(@brazil_client.items.where('1=1').find(@item_brazil.id)).to eq(@item_brazil)
749
+ @brazil_client.items.destroy_all
750
+ expect { @brazil_client.items.where('1=1').find(@item_brazil.id) }.to raise_error ActiveRecord::RecordNotFound
751
+ end
752
+
753
+ it 'where + find with block' do
754
+ expect(@brazil_client.items.where('1=1').find { |i| i.id == @item_brazil.id }).to eq(@item_brazil)
755
+ @brazil_client.items.destroy_all
756
+ expect(@brazil_client.items.where('1=1').find { |i| i.id == @item_brazil.id }).to be_nil
757
+ end
758
+
759
+ it 'where + select' do
760
+ expect(@brazil_client.items.where('1=1').select(:name).first.name).to eq(@item_brazil.name)
761
+ @brazil_client.items.destroy_all
762
+ expect(@brazil_client.items.where('1=1').select(:name)).to be_empty
763
+ end
764
+
765
+ it 'where + select with block' do
766
+ expect(@brazil_client.items.where('1=1').select { |i| i.id == @item_brazil.id }).to eq([@item_brazil])
767
+ @brazil_client.items.destroy_all
768
+ expect(@brazil_client.items.where('1=1').select { |i| i.id == @item_brazil.id }).to be_empty
769
+ end
770
+
771
+ it 'where + any?' do
772
+ expect(@brazil_client.items.where('1=1').any?).to be true
773
+ @brazil_client.items.destroy_all
774
+ expect(@brazil_client.items.where('1=1').any?).to be false
775
+ end
776
+
777
+ it 'where + any? with block' do
778
+ expect(@brazil_client.items.where('1=1').any? { |i| i.id == @item_brazil.id }).to be true
779
+ @brazil_client.items.destroy_all
780
+ expect(@brazil_client.items.where('1=1').any? { |i| i.id == @item_brazil.id }).to be false
781
+ end
782
+
783
+ it 'exists?' do
784
+ expect(@brazil_client.items.exists?(@item_brazil.id)).to be true
785
+ @brazil_client.items.destroy_all
786
+ expect(@brazil_client.items.exists?(@item_brazil.id)).to be false
787
+ end
788
+
789
+ it 'uniq' do
790
+ expect(@brazil_client.items.uniq).to eq([@item_brazil])
791
+ end
792
+
793
+ it 'clear' do
794
+ expect(@brazil_client.items.empty?).to be false
795
+ @brazil_client.items.clear
796
+ expect(@brazil_client.items.empty?).to be true
797
+ end
798
+ end
799
+ end
800
+
801
+ describe 'when you have a 1 x N polymorphic relationship' do
802
+ before(:each) do
803
+ @brazil_client = Client.using(:brazil).create!(:name => 'Brazil Client')
804
+ @master_client = Client.create!(:name => 'Master Client')
805
+ @comment_brazil = Comment.using(:brazil).create!(:name => 'Brazil Comment', :commentable => @brazil_client)
806
+ @comment_master = Comment.create!(:name => 'Master Comment', :commentable => @master_client)
807
+ @brazil_client = Client.using(:brazil).find_by_name('Brazil Client')
808
+ Client.using(:master).create!(:name => 'teste')
809
+ end
810
+
811
+ it 'should find all models in the specified shard' do
812
+ expect(@brazil_client.comment_ids).to eq([@comment_brazil.id])
813
+ expect(@brazil_client.comments).to eq([@comment_brazil])
814
+ end
815
+
816
+ it 'should finds the client that the comment belongs' do
817
+ expect(@comment_brazil.commentable).to eq(@brazil_client)
818
+ end
819
+
820
+ it 'should update the attribute for the comment' do
821
+ new_brazil_client = Client.using(:brazil).create!(:name => 'new Client')
822
+ @comment_brazil.commentable = new_brazil_client
823
+ expect(@comment_brazil.commentable).to eq(new_brazil_client)
824
+ @comment_brazil.save
825
+ @comment_brazil.reload
826
+ expect(@comment_brazil.commentable_id).to eq(new_brazil_client.id)
827
+ expect(@comment_brazil.commentable).to eq(new_brazil_client)
828
+ end
829
+
830
+ describe 'it should work when using' do
831
+ before(:each) do
832
+ @comment_brazil_2 = Comment.using(:brazil).create!(:name => 'Brazil Comment 2')
833
+ expect(@brazil_client.comments.to_set).to eq([@comment_brazil].to_set)
834
+ end
835
+
836
+ it 'update' do
837
+ @brazil_client.update(:comment_ids => [@comment_brazil_2.id, @comment_brazil.id])
838
+ expect(@brazil_client.comments.to_set).to eq([@comment_brazil, @comment_brazil_2].to_set)
839
+ end
840
+
841
+ it '<<' do
842
+ @brazil_client.comments << @comment_brazil_2
843
+ expect(@brazil_client.comments.to_set).to eq([@comment_brazil, @comment_brazil_2].to_set)
844
+ end
845
+
846
+ it 'all' do
847
+ comment = @brazil_client.comments.build(:name => 'Builded Comment')
848
+ comment.save
849
+ c = @brazil_client.comments
850
+ expect(c.to_set).to eq([@comment_brazil, comment].to_set)
851
+ expect(c.reload.all.to_set).to eq([@comment_brazil, comment].to_set)
852
+ end
853
+
854
+ it 'build' do
855
+ comment = @brazil_client.comments.build(:name => 'Builded Comment')
856
+ comment.save
857
+ expect(@brazil_client.comments.to_set).to eq([@comment_brazil, comment].to_set)
858
+ end
859
+
860
+ it 'create' do
861
+ comment = @brazil_client.comments.create(:name => 'Builded Comment')
862
+ expect(@brazil_client.comments.to_set).to eq([@comment_brazil, comment].to_set)
863
+ end
864
+
865
+ it 'count' do
866
+ expect(@brazil_client.comments.count).to eq(1)
867
+ _cmt = @brazil_client.comments.create(:name => 'Builded Comment')
868
+ expect(@brazil_client.comments.count).to eq(2)
869
+ end
870
+
871
+ it 'group + count' do
872
+ expect(@brazil_client.comments.group(:id).count.length).to eq(1)
873
+ _cmt = @brazil_client.comments.create(:name => 'Builded Comment')
874
+ expect(@brazil_client.comments.group(:id).count.length).to eq(2)
875
+ end
876
+
877
+ it 'size' do
878
+ expect(@brazil_client.comments.size).to eq(1)
879
+ _cmt = @brazil_client.comments.create(:name => 'Builded Comment')
880
+ expect(@brazil_client.comments.size).to eq(2)
881
+ end
882
+
883
+ it 'create!' do
884
+ comment = @brazil_client.comments.create!(:name => 'Builded Comment')
885
+ expect(@brazil_client.comments.to_set).to eq([@comment_brazil, comment].to_set)
886
+ end
887
+
888
+ it 'length' do
889
+ expect(@brazil_client.comments.length).to eq(1)
890
+ _cmt = @brazil_client.comments.create(:name => 'Builded Comment')
891
+ expect(@brazil_client.comments.length).to eq(2)
892
+ end
893
+
894
+ it 'empty?' do
895
+ expect(@brazil_client.comments.empty?).to be false
896
+ c = Client.create!(:name => 'Client1')
897
+ expect(c.comments.empty?).to be true
898
+ end
899
+
900
+ it 'delete' do
901
+ expect(@brazil_client.comments.empty?).to be false
902
+ @brazil_client.comments.delete(@comment_brazil)
903
+ @brazil_client.reload
904
+ @comment_brazil.reload
905
+ expect(@comment_brazil.commentable).to be_nil
906
+ expect(@brazil_client.comments).to eq([])
907
+ expect(@brazil_client.comments.empty?).to be true
908
+ end
909
+
910
+ it 'delete_all' do
911
+ expect(@brazil_client.comments.empty?).to be false
912
+ @brazil_client.comments.delete_all
913
+ expect(@brazil_client.comments.empty?).to be true
914
+ end
915
+
916
+ it 'destroy_all' do
917
+ expect(@brazil_client.comments.empty?).to be false
918
+ @brazil_client.comments.destroy_all
919
+ expect(@brazil_client.comments.empty?).to be true
920
+ end
921
+
922
+ it 'find' do
923
+ expect(@brazil_client.comments.first).to eq(@comment_brazil)
924
+ @brazil_client.comments.destroy_all
925
+ expect(@brazil_client.comments.first).to be_nil
926
+ end
927
+
928
+ it 'where' do
929
+ expect(@brazil_client.comments.where('1=1')).to eq([@comment_brazil])
930
+ @brazil_client.comments.destroy_all
931
+ expect(@brazil_client.comments.where('1=1')).to be_empty
932
+ end
933
+
934
+ it 'map' do
935
+ expect(@brazil_client.comments.map(&:id)).to eq([@comment_brazil.id])
936
+ @brazil_client.comments.destroy_all
937
+ expect(@brazil_client.comments.map(&:id)).to be_empty
938
+ end
939
+
940
+ it 'where + map' do
941
+ expect(@brazil_client.comments.where('1=1').map(&:id)).to eq([@comment_brazil.id])
942
+ @brazil_client.comments.destroy_all
943
+ expect(@brazil_client.comments.where('1=1').map(&:id)).to be_empty
944
+ end
945
+
946
+ it 'where + each_with_index + map (enum method chain)' do
947
+ expect(@brazil_client.comments.where('1=1').each_with_index.map { |r, i| [r.id, i]}).to eq([[@comment_brazil.id, 0]])
948
+ @brazil_client.comments.destroy_all
949
+ expect(@brazil_client.comments.where('1=1').each_with_index.map { |r, i| [r.id, i]}).to be_empty
950
+ end
951
+
952
+ it 'where + sum' do
953
+ expect(@brazil_client.comments.where('1=1').sum(&:id)).to eq(@comment_brazil.id)
954
+ @brazil_client.comments.destroy_all
955
+ expect(@brazil_client.comments.where('1=1').sum(&:id)).to eq(0)
956
+ end
957
+
958
+ it 'where + index_by' do
959
+ expect(@brazil_client.comments.where('1=1').index_by(&:id)).to eq(@comment_brazil.id => @comment_brazil)
960
+ @brazil_client.comments.destroy_all
961
+ expect(@brazil_client.comments.where('1=1').index_by(&:id)).to be_empty
962
+ end
963
+
964
+ it 'where + find' do
965
+ expect(@brazil_client.comments.where('1=1').find(@comment_brazil.id)).to eq(@comment_brazil)
966
+ @brazil_client.comments.destroy_all
967
+ expect { @brazil_client.comments.where('1=1').find(@comment_brazil.id) }.to raise_error ActiveRecord::RecordNotFound
968
+ end
969
+
970
+ it 'where + find with block' do
971
+ expect(@brazil_client.comments.where('1=1').find { |c| c.id == @comment_brazil.id }).to eq(@comment_brazil)
972
+ @brazil_client.comments.destroy_all
973
+ expect(@brazil_client.comments.where('1=1').find { |c| c.id == @comment_brazil.id }).to be_nil
974
+ end
975
+
976
+ it 'where + select' do
977
+ expect(@brazil_client.comments.where('1=1').select(:name).first.name).to eq(@comment_brazil.name)
978
+ @brazil_client.comments.destroy_all
979
+ expect(@brazil_client.comments.where('1=1').select(:name)).to be_empty
980
+ end
981
+
982
+ it 'where + select with block' do
983
+ expect(@brazil_client.comments.where('1=1').select { |c| c.id == @comment_brazil.id }).to eq([@comment_brazil])
984
+ @brazil_client.comments.destroy_all
985
+ expect(@brazil_client.comments.where('1=1').select { |c| c.id == @comment_brazil.id }).to be_empty
986
+ end
987
+
988
+ it 'where + any?' do
989
+ expect(@brazil_client.comments.where('1=1').any?).to be true
990
+ @brazil_client.comments.destroy_all
991
+ expect(@brazil_client.comments.where('1=1').any?).to be false
992
+ end
993
+
994
+ it 'where + any? with block' do
995
+ expect(@brazil_client.comments.where('1=1').any? { |c| c.id == @comment_brazil.id }).to be true
996
+ @brazil_client.comments.destroy_all
997
+ expect(@brazil_client.comments.where('1=1').any? { |c| c.id == @comment_brazil.id }).to be false
998
+ end
999
+
1000
+ it 'exists?' do
1001
+ expect(@brazil_client.comments.exists?(@comment_brazil.id)).to be true
1002
+ @brazil_client.comments.destroy_all
1003
+ expect(@brazil_client.comments.exists?(@comment_brazil.id)).to be false
1004
+ end
1005
+
1006
+ it 'uniq' do
1007
+ expect(@brazil_client.comments.uniq).to eq([@comment_brazil])
1008
+ end
1009
+
1010
+ it 'clear' do
1011
+ expect(@brazil_client.comments.empty?).to be false
1012
+ @brazil_client.comments.clear
1013
+ expect(@brazil_client.comments.empty?).to be true
1014
+ end
1015
+ end
1016
+ end
1017
+
1018
+ it 'block' do
1019
+ @brazil_role = Role.using(:brazil).create!(:name => 'Brazil Role')
1020
+ expect(@brazil_role.permissions.build(:name => 'ok').name).to eq('ok')
1021
+ expect(@brazil_role.permissions.create(:name => 'ok').name).to eq('ok')
1022
+ expect(@brazil_role.permissions.create!(:name => 'ok').name).to eq('ok')
1023
+ end
1024
+ end