mongoid 8.0.5 → 8.0.7

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.
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