mongoid 8.0.5 → 8.0.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/lib/mongoid/association/macros.rb +6 -0
  4. data/lib/mongoid/attributes/processing.rb +29 -5
  5. data/lib/mongoid/config/options.rb +3 -0
  6. data/lib/mongoid/config.rb +30 -0
  7. data/lib/mongoid/contextual/mongo.rb +24 -1
  8. data/lib/mongoid/criteria/queryable/selector.rb +1 -1
  9. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  10. data/lib/mongoid/deprecable.rb +3 -2
  11. data/lib/mongoid/deprecation.rb +3 -3
  12. data/lib/mongoid/extensions/hash.rb +24 -2
  13. data/lib/mongoid/fields.rb +45 -18
  14. data/lib/mongoid/interceptable.rb +122 -13
  15. data/lib/mongoid/version.rb +1 -1
  16. data/spec/integration/callbacks_spec.rb +20 -0
  17. data/spec/mongoid/attributes_spec.rb +27 -0
  18. data/spec/mongoid/config_spec.rb +11 -2
  19. data/spec/mongoid/contextual/mongo_spec.rb +89 -14
  20. data/spec/mongoid/copyable_spec.rb +1 -1
  21. data/spec/mongoid/criteria/queryable/selector_spec.rb +75 -2
  22. data/spec/mongoid/criteria/queryable/storable_spec.rb +72 -0
  23. data/spec/mongoid/extensions/hash_spec.rb +3 -3
  24. data/spec/mongoid/fields_spec.rb +43 -0
  25. data/spec/mongoid/interceptable_spec.rb +362 -161
  26. data/spec/shared/lib/mrss/docker_runner.rb +7 -0
  27. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  28. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  29. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  30. data/spec/shared/lib/mrss/utils.rb +28 -6
  31. data/spec/shared/share/Dockerfile.erb +36 -40
  32. data/spec/shared/shlib/server.sh +32 -8
  33. data/spec/shared/shlib/set_env.sh +4 -4
  34. data/spec/support/models/person.rb +1 -0
  35. data/spec/support/models/purse.rb +9 -0
  36. data.tar.gz.sig +0 -0
  37. metadata +10 -8
  38. metadata.gz.sig +0 -0
@@ -158,6 +158,16 @@ describe Mongoid::Contextual::Mongo do
158
158
  end
159
159
  end
160
160
  end
161
+
162
+ context 'when for_js is present' do
163
+ let(:context) do
164
+ Band.for_js('this.name == "Depeche Mode"')
165
+ end
166
+
167
+ it 'counts the expected records' do
168
+ expect(context.count).to eq(1)
169
+ end
170
+ end
161
171
  end
162
172
 
163
173
  describe "#estimated_count" do
@@ -1179,33 +1189,49 @@ describe Mongoid::Contextual::Mongo do
1179
1189
  let!(:person2) { Person.create!(ssn: BSON::Decimal128.new("1")) }
1180
1190
  let(:tally) { Person.tally("ssn") }
1181
1191
 
1192
+ let(:tallied_classes) do
1193
+ tally.keys.map(&:class).sort do |a, b|
1194
+ a.to_s.casecmp(b.to_s)
1195
+ end
1196
+ end
1197
+
1182
1198
  context "< BSON 5" do
1183
1199
  max_bson_version '4.99.99'
1184
1200
 
1185
1201
  it "stores the correct types in the database" do
1186
- Person.find(person1.id).attributes["ssn"].should be_a BSON::Regexp::Raw
1187
- Person.find(person2.id).attributes["ssn"].should be_a BSON::Decimal128
1202
+ expect(Person.find(person1.id).attributes["ssn"]).to be_a BSON::Regexp::Raw
1203
+ expect(Person.find(person2.id).attributes["ssn"]).to be_a BSON::Decimal128
1204
+ end
1205
+
1206
+ it "tallies the correct type" do
1207
+ expect(tallied_classes).to be == [ BSON::Decimal128, BSON::Regexp::Raw ]
1208
+ end
1209
+ end
1210
+
1211
+ context '>= BSON 5' do
1212
+ min_bson_version "5.0"
1213
+
1214
+ it "stores the correct types in the database" do
1215
+ expect(Person.find(person1.id).ssn).to be_a BSON::Regexp::Raw
1216
+ expect(Person.find(person2.id).ssn).to be_a BigDecimal
1188
1217
  end
1189
1218
 
1190
1219
  it "tallies the correct type" do
1191
- tally.keys.map(&:class).sort do |a,b|
1192
- a.to_s <=> b.to_s
1193
- end.should == [BSON::Decimal128, BSON::Regexp::Raw]
1220
+ expect(tallied_classes).to be == [ BigDecimal, BSON::Regexp::Raw ]
1194
1221
  end
1195
1222
  end
1196
1223
 
1197
- context ">= BSON 5" do
1224
+ context '>= BSON 5 with decimal128 allowed' do
1198
1225
  min_bson_version "5.0"
1226
+ config_override :allow_bson5_decimal128, true
1199
1227
 
1200
1228
  it "stores the correct types in the database" do
1201
- Person.find(person1.id).ssn.should be_a BSON::Regexp::Raw
1202
- Person.find(person2.id).ssn.should be_a BigDeimal
1229
+ expect(Person.find(person1.id).ssn).to be_a BSON::Regexp::Raw
1230
+ expect(Person.find(person2.id).ssn).to be_a BSON::Decimal128
1203
1231
  end
1204
1232
 
1205
1233
  it "tallies the correct type" do
1206
- tally.keys.map(&:class).sort do |a,b|
1207
- a.to_s <=> b.to_s
1208
- end.should == [BigDecimal, BSON::Regexp::Raw]
1234
+ expect(tallied_classes).to be == [ BSON::Decimal128, BSON::Regexp::Raw ]
1209
1235
  end
1210
1236
  end
1211
1237
  end
@@ -3547,16 +3573,65 @@ describe Mongoid::Contextual::Mongo do
3547
3573
 
3548
3574
  context "when the attributes are in the correct type" do
3549
3575
 
3576
+ context "when operation is $set" do
3577
+
3578
+ before do
3579
+ context.update_all("$set" => { name: "Smiths" })
3580
+ end
3581
+
3582
+ it "updates the first matching document" do
3583
+ expect(depeche_mode.reload.name).to eq("Smiths")
3584
+ end
3585
+
3586
+ it "updates the last matching document" do
3587
+ expect(new_order.reload.name).to eq("Smiths")
3588
+ end
3589
+ end
3590
+
3591
+ context "when operation is $push" do
3592
+
3593
+ before do
3594
+ depeche_mode.update_attribute(:genres, ["electronic"])
3595
+ new_order.update_attribute(:genres, ["electronic"])
3596
+ context.update_all("$push" => { genres: "pop" })
3597
+ end
3598
+
3599
+ it "updates the first matching document" do
3600
+ expect(depeche_mode.reload.genres).to eq(["electronic", "pop"])
3601
+ end
3602
+
3603
+ it "updates the last matching document" do
3604
+ expect(new_order.reload.genres).to eq(["electronic", "pop"])
3605
+ end
3606
+ end
3607
+
3608
+ context "when operation is $addToSet" do
3609
+
3610
+ before do
3611
+ context.update_all("$addToSet" => { genres: "electronic" })
3612
+ end
3613
+
3614
+ it "updates the first matching document" do
3615
+ expect(depeche_mode.reload.genres).to eq(["electronic"])
3616
+ end
3617
+
3618
+ it "updates the last matching document" do
3619
+ expect(new_order.reload.genres).to eq(["electronic"])
3620
+ end
3621
+ end
3622
+ end
3623
+
3624
+ context 'when using aliased field names' do
3550
3625
  before do
3551
- context.update_all("$set" => { name: "Smiths" })
3626
+ context.update_all('$set' => { years: 100 })
3552
3627
  end
3553
3628
 
3554
3629
  it "updates the first matching document" do
3555
- expect(depeche_mode.reload.name).to eq("Smiths")
3630
+ expect(depeche_mode.reload.years).to eq(100)
3556
3631
  end
3557
3632
 
3558
3633
  it "updates the last matching document" do
3559
- expect(new_order.reload.name).to eq("Smiths")
3634
+ expect(new_order.reload.years).to eq(100)
3560
3635
  end
3561
3636
  end
3562
3637
 
@@ -90,7 +90,7 @@ describe Mongoid::Copyable do
90
90
  end
91
91
 
92
92
  it 'calls constructor with explicitly declared attributes only' do
93
- expect(Mongoid::Factory).to receive(:build).with(cls, 'name' => 'test').and_call_original
93
+ expect(Mongoid::Factory).to receive(:build).with(cls, { 'name' => 'test' }).and_call_original
94
94
  cloned
95
95
  end
96
96
  end
@@ -44,7 +44,7 @@ describe Mongoid::Criteria::Queryable::Selector do
44
44
  end
45
45
  end
46
46
 
47
- context "when selector contains a $nin" do
47
+ context "when selector contains a $nin string" do
48
48
 
49
49
  let(:initial) do
50
50
  { "$nin" => ["foo"] }
@@ -72,7 +72,35 @@ describe Mongoid::Criteria::Queryable::Selector do
72
72
  end
73
73
  end
74
74
 
75
- context "when selector contains a $in" do
75
+ context "when selector contains a $nin symbol" do
76
+
77
+ let(:initial) do
78
+ { :$nin => ["foo"] }
79
+ end
80
+
81
+ before do
82
+ selector["field"] = initial
83
+ end
84
+
85
+ context "when merging in a new $nin" do
86
+
87
+ let(:other) do
88
+ { "field" => { :$nin => ["bar"] } }
89
+ end
90
+
91
+ before do
92
+ selector.merge!(other)
93
+ end
94
+
95
+ it "combines the two $nin queries into one" do
96
+ expect(selector).to eq({
97
+ "field" => { :$nin => ["foo", "bar"] }
98
+ })
99
+ end
100
+ end
101
+ end
102
+
103
+ context "when selector contains a $in string" do
76
104
 
77
105
  let(:initial) do
78
106
  { "$in" => [1, 2] }
@@ -117,6 +145,51 @@ describe Mongoid::Criteria::Queryable::Selector do
117
145
  end
118
146
  end
119
147
 
148
+ context "when selector contains a $in symbol" do
149
+
150
+ let(:initial) do
151
+ { :$in => [1, 2] }
152
+ end
153
+
154
+ before do
155
+ selector["field"] = initial
156
+ end
157
+
158
+ context "when merging in a new $in with an intersecting value" do
159
+
160
+ let(:other) do
161
+ { "field" => { :$in => [1] } }
162
+ end
163
+
164
+ before do
165
+ selector.merge!(other)
166
+ end
167
+
168
+ it "intersects the $in values" do
169
+ expect(selector).to eq({
170
+ "field" => { :$in => [1] }
171
+ })
172
+ end
173
+ end
174
+
175
+ context "when merging in a new $in with no intersecting values" do
176
+
177
+ let(:other) do
178
+ { "field" => { :$in => [3] } }
179
+ end
180
+
181
+ before do
182
+ selector.merge!(other)
183
+ end
184
+
185
+ it "intersects the $in values" do
186
+ expect(selector).to eq({
187
+ "field" => { :$in => [] }
188
+ })
189
+ end
190
+ end
191
+ end
192
+
120
193
  context "when selector is not nested" do
121
194
 
122
195
  before do
@@ -210,7 +210,79 @@ describe Mongoid::Criteria::Queryable::Storable do
210
210
  }
211
211
  end
212
212
  end
213
+
214
+ context 'when value is a hash combine values with different operator keys' do
215
+ let(:base) do
216
+ query.add_field_expression('foo', {'$in' => ['bar']})
217
+ end
218
+
219
+ let(:modified) do
220
+ base.add_field_expression('foo', {'$nin' => ['zoom']})
221
+ end
222
+
223
+ it 'combines the conditions using $and' do
224
+ modified.selector.should == {
225
+ 'foo' => {
226
+ '$in' => ['bar'],
227
+ '$nin' => ['zoom']
228
+ }
229
+ }
230
+ end
231
+ end
232
+
233
+ context 'when value is a hash with symbol operator key combine values with different operator keys' do
234
+ let(:base) do
235
+ query.add_field_expression('foo', {:$in => ['bar']})
236
+ end
237
+
238
+ let(:modified) do
239
+ base.add_field_expression('foo', {:$nin => ['zoom']})
240
+ end
241
+
242
+ it 'combines the conditions using $and' do
243
+ modified.selector.should == {
244
+ 'foo' => {
245
+ :$in => ['bar'],
246
+ :$nin => ['zoom']
247
+ }
248
+ }
249
+ end
250
+ end
251
+
252
+ context 'when value is a hash add values with same operator keys using $and' do
253
+ let(:base) do
254
+ query.add_field_expression('foo', {'$in' => ['bar']})
255
+ end
256
+
257
+ let(:modified) do
258
+ base.add_field_expression('foo', {'$in' => ['zoom']})
259
+ end
260
+
261
+ it 'adds the new condition using $and' do
262
+ modified.selector.should == {
263
+ 'foo' => {'$in' => ['bar']},
264
+ '$and' => ['foo' => {'$in' => ['zoom']}]
265
+ }
266
+ end
267
+ end
268
+
269
+ context 'when value is a hash with symbol operator key add values with same operator keys using $and' do
270
+ let(:base) do
271
+ query.add_field_expression('foo', {:$in => ['bar']})
272
+ end
273
+
274
+ let(:modified) do
275
+ base.add_field_expression('foo', {:$in => ['zoom']})
276
+ end
277
+
278
+ it 'adds the new condition using $and' do
279
+ modified.selector.should == {
280
+ 'foo' => {:$in => ['bar']},
281
+ '$and' => ['foo' => {:$in => ['zoom']}]
282
+ }
283
+ end
213
284
  end
285
+ end
214
286
 
215
287
  describe '#add_operator_expression' do
216
288
  let(:query_method) { :add_operator_expression }
@@ -178,7 +178,7 @@ describe Mongoid::Extensions::Hash do
178
178
 
179
179
  it "moves the non hash values under the provided key" do
180
180
  expect(consolidated).to eq({
181
- "$set" => { name: "Tool", likes: 10 }, "$inc" => { plays: 1 }
181
+ "$set" => { 'name' => "Tool", likes: 10 }, "$inc" => { 'plays' => 1 }
182
182
  })
183
183
  end
184
184
  end
@@ -195,7 +195,7 @@ describe Mongoid::Extensions::Hash do
195
195
 
196
196
  it "moves the non hash values under the provided key" do
197
197
  expect(consolidated).to eq({
198
- "$set" => { likes: 10, name: "Tool" }, "$inc" => { plays: 1 }
198
+ "$set" => { likes: 10, 'name' => "Tool" }, "$inc" => { 'plays' => 1 }
199
199
  })
200
200
  end
201
201
  end
@@ -213,7 +213,7 @@ describe Mongoid::Extensions::Hash do
213
213
 
214
214
  it "moves the non hash values under the provided key" do
215
215
  expect(consolidated).to eq({
216
- "$set" => { likes: 10, name: "Tool" }, "$inc" => { plays: 1 }
216
+ "$set" => { likes: 10, name: "Tool" }, "$inc" => { 'plays' => 1 }
217
217
  })
218
218
  end
219
219
  end
@@ -567,6 +567,49 @@ describe Mongoid::Fields do
567
567
  end
568
568
  end
569
569
  end
570
+
571
+ context 'when the field is declared as BSON::Decimal128' do
572
+ let(:document) { Mop.create!(decimal128_field: BSON::Decimal128.new(Math::PI.to_s)).reload }
573
+
574
+ shared_context 'BSON::Decimal128 is BigDecimal' do
575
+ it 'should return a BigDecimal' do
576
+ expect(document.decimal128_field).to be_a BigDecimal
577
+ end
578
+ end
579
+
580
+ shared_context 'BSON::Decimal128 is BSON::Decimal128' do
581
+ it 'should return a BSON::Decimal128' do
582
+ expect(document.decimal128_field).to be_a BSON::Decimal128
583
+ end
584
+ end
585
+
586
+ it 'is declared as BSON::Decimal128' do
587
+ expect(Mop.fields['decimal128_field'].type).to be == BSON::Decimal128
588
+ end
589
+
590
+ context 'when BSON version <= 4' do
591
+ max_bson_version '4.99.99'
592
+ it_behaves_like 'BSON::Decimal128 is BSON::Decimal128'
593
+ end
594
+
595
+ context 'when BSON version >= 5' do
596
+ min_bson_version '5.0.0'
597
+
598
+ context 'when allow_bson5_decimal128 is false' do
599
+ config_override :allow_bson5_decimal128, false
600
+ it_behaves_like 'BSON::Decimal128 is BigDecimal'
601
+ end
602
+
603
+ context 'when allow_bson5_decimal128 is true' do
604
+ config_override :allow_bson5_decimal128, true
605
+ it_behaves_like 'BSON::Decimal128 is BSON::Decimal128'
606
+ end
607
+
608
+ context 'when allow_bson5_decimal128 is default' do
609
+ it_behaves_like 'BSON::Decimal128 is BigDecimal'
610
+ end
611
+ end
612
+ end
570
613
  end
571
614
 
572
615
  describe "#getter_before_type_cast" do