octoball 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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