mongoid 7.2.0 → 7.2.4

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 (70) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/README.md +1 -1
  5. data/lib/mongoid/attributes.rb +8 -1
  6. data/lib/mongoid/criteria/queryable/selector.rb +0 -4
  7. data/lib/mongoid/document.rb +3 -2
  8. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  9. data/lib/mongoid/interceptable.rb +3 -1
  10. data/lib/mongoid/matcher.rb +19 -43
  11. data/lib/mongoid/matcher/elem_match.rb +2 -1
  12. data/lib/mongoid/matcher/expression.rb +5 -14
  13. data/lib/mongoid/matcher/field_expression.rb +4 -5
  14. data/lib/mongoid/matcher/field_operator.rb +7 -11
  15. data/lib/mongoid/reloadable.rb +5 -0
  16. data/lib/mongoid/validatable/associated.rb +1 -1
  17. data/lib/mongoid/validatable/presence.rb +3 -3
  18. data/lib/mongoid/validatable/uniqueness.rb +1 -1
  19. data/lib/mongoid/version.rb +1 -1
  20. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  21. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
  22. data/spec/integration/app_spec.rb +174 -84
  23. data/spec/integration/callbacks_models.rb +49 -0
  24. data/spec/integration/callbacks_spec.rb +216 -0
  25. data/spec/integration/document_spec.rb +21 -0
  26. data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
  27. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  28. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  29. data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
  30. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  31. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  32. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  33. data/spec/lite_spec_helper.rb +3 -4
  34. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  35. data/spec/mongoid/atomic/paths_spec.rb +41 -0
  36. data/spec/mongoid/attributes_spec.rb +241 -0
  37. data/spec/mongoid/contextual/atomic_spec.rb +17 -4
  38. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +36 -0
  39. data/spec/mongoid/document_fields_spec.rb +26 -0
  40. data/spec/mongoid/document_query_spec.rb +51 -0
  41. data/spec/mongoid/errors/mongoid_error_spec.rb +20 -8
  42. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  43. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
  44. data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
  45. data/spec/mongoid/persistable/settable_spec.rb +30 -0
  46. data/spec/mongoid/persistable_spec.rb +2 -2
  47. data/spec/shared/bin/get-mongodb-download-url +17 -0
  48. data/spec/shared/bin/s3-copy +45 -0
  49. data/spec/shared/bin/s3-upload +69 -0
  50. data/spec/shared/lib/mrss/cluster_config.rb +226 -0
  51. data/spec/shared/lib/mrss/constraints.rb +71 -6
  52. data/spec/shared/lib/mrss/docker_runner.rb +271 -0
  53. data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
  54. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  55. data/spec/shared/lib/mrss/spec_organizer.rb +32 -2
  56. data/spec/shared/lib/mrss/utils.rb +15 -0
  57. data/spec/shared/share/Dockerfile.erb +322 -0
  58. data/spec/shared/share/haproxy-1.conf +16 -0
  59. data/spec/shared/share/haproxy-2.conf +17 -0
  60. data/spec/shared/shlib/distro.sh +73 -0
  61. data/spec/shared/shlib/server.sh +317 -0
  62. data/spec/shared/shlib/set_env.sh +131 -0
  63. data/spec/spec_helper.rb +1 -1
  64. data/spec/support/models/customer.rb +11 -0
  65. data/spec/support/models/customer_address.rb +12 -0
  66. data/spec/support/models/dictionary.rb +6 -0
  67. data/spec/support/models/mop.rb +10 -0
  68. data/spec/support/spec_config.rb +8 -0
  69. metadata +554 -508
  70. metadata.gz.sig +3 -2
@@ -0,0 +1,15 @@
1
+ - name: Date field - matches
2
+ document:
3
+ date_field: 2020-12-19
4
+ query:
5
+ date_field:
6
+ $lt: 2020-12-21
7
+ matches: true
8
+
9
+ - name: Date field - does not match
10
+ document:
11
+ date_field: 2020-12-21
12
+ query:
13
+ date_field:
14
+ $lt: 2020-12-21
15
+ matches: false
@@ -0,0 +1,15 @@
1
+ - name: Date field - matches
2
+ document:
3
+ date_field: 2020-12-19
4
+ query:
5
+ date_field:
6
+ $lte: 2020-12-21
7
+ matches: true
8
+
9
+ - name: Date field - does not match
10
+ document:
11
+ date_field: 2020-12-22
12
+ query:
13
+ date_field:
14
+ $lte: 2020-12-21
15
+ matches: false
@@ -0,0 +1,15 @@
1
+ - name: Date field - matches
2
+ document:
3
+ date_field: 2020-12-22
4
+ query:
5
+ date_field:
6
+ $ne: 2020-12-21
7
+ matches: true
8
+
9
+ - name: Date field - does not match
10
+ document:
11
+ date_field: 2020-12-21
12
+ query:
13
+ date_field:
14
+ $ne: 2020-12-21
15
+ matches: false
@@ -51,11 +51,10 @@ RSpec.configure do |config|
51
51
  config.add_formatter(RSpec::Core::Formatters::JsonFormatter, File.join(File.dirname(__FILE__), '../tmp/rspec.json'))
52
52
  end
53
53
 
54
- if SpecConfig.instance.ci?
54
+ if SpecConfig.instance.ci? && !%w(1 true yes).include?(ENV['INTERACTIVE']&.downcase)
55
55
  timeout = if SpecConfig.instance.app_tests?
56
- # Allow 5 minutes per test for the app tests, since they install
57
- # gems for Rails applications which can take a long time.
58
- 300
56
+ # App tests under JRuby take a REALLY long time (over 5 minutes per test).
57
+ 500
59
58
  else
60
59
  # Allow a max of 30 seconds per test.
61
60
  # Tests should take under 10 seconds ideally but it seems
@@ -507,4 +507,54 @@ describe Mongoid::Association::Embedded::EmbeddedIn::Proxy do
507
507
  end
508
508
  end
509
509
  end
510
+
511
+ context "when the same class is embedded multiple times" do
512
+
513
+ let(:customer) do
514
+ Customer.new
515
+ end
516
+
517
+ context "assignment after saving" do
518
+
519
+ it "correctly sets the association for the embedded class" do
520
+ pending 'MONGOID-5039'
521
+
522
+ customer.home_address = CustomerAddress.new
523
+ customer.work_address = CustomerAddress.new
524
+
525
+ expect(customer.home_address._association.store_as).to eq("home_address")
526
+ expect(customer.work_address._association.store_as).to eq("work_address")
527
+
528
+ expect(customer.home_address.instance_eval { _association.store_as }).to eq("home_address")
529
+ expect(customer.work_address.instance_eval { _association.store_as }).to eq("work_address")
530
+
531
+ customer.save!
532
+
533
+ customer.home_address = CustomerAddress.new
534
+ customer.work_address = CustomerAddress.new
535
+
536
+ expect(customer.home_address._association.store_as).to eq("home_address")
537
+ expect(customer.work_address._association.store_as).to eq("work_address")
538
+
539
+ expect(customer.home_address.instance_eval { _association.store_as }).to eq("home_address")
540
+ expect(customer.work_address.instance_eval { _association.store_as }).to eq("work_address")
541
+ end
542
+ end
543
+
544
+ context "inverse assignment" do
545
+
546
+ it "correctly sets the association for the embedded class" do
547
+ pending 'MONGOID-5039'
548
+
549
+ customer.work_address = CustomerAddress.new
550
+ customer.work_address.addressable = customer
551
+
552
+ expect(customer.home_address._association.store_as).to eq("home_address")
553
+ expect(customer.work_address._association.store_as).to eq("work_address")
554
+
555
+ expect(customer.home_address.instance_eval { _association.store_as }).to eq("home_address")
556
+ expect(customer.work_address.instance_eval { _association.store_as }).to eq("work_address")
557
+ end
558
+ end
559
+ end
510
560
  end
@@ -268,5 +268,46 @@ describe Mongoid::Atomic::Paths do
268
268
  end
269
269
  end
270
270
  end
271
+
272
+ context "when the same class is embedded in multiple associations" do
273
+
274
+ let(:customer) do
275
+ Customer.new
276
+ end
277
+
278
+ context "assignment after saving" do
279
+
280
+ it "correctly sets the association for the embedded class" do
281
+ pending 'MONGOID-5039'
282
+
283
+ customer.home_address = CustomerAddress.new
284
+ customer.work_address = CustomerAddress.new
285
+
286
+ expect(customer.home_address.atomic_path).to eq("home_address")
287
+ expect(customer.work_address.atomic_path).to eq("work_address")
288
+
289
+ customer.save!
290
+
291
+ customer.home_address = CustomerAddress.new
292
+ customer.work_address = CustomerAddress.new
293
+
294
+ expect(customer.home_address.atomic_path).to eq("home_address")
295
+ expect(customer.work_address.atomic_path).to eq("work_address")
296
+ end
297
+ end
298
+
299
+ context "inverse assignment" do
300
+
301
+ it "correctly returns the path for each embedded class" do
302
+ pending 'MONGOID-5039'
303
+
304
+ customer.work_address = CustomerAddress.new
305
+ customer.work_address.addressable = customer
306
+
307
+ expect(customer.home_address.atomic_path).to eq("home_address")
308
+ expect(customer.work_address.atomic_path).to eq("work_address")
309
+ end
310
+ end
311
+ end
271
312
  end
272
313
  end
@@ -245,6 +245,97 @@ describe Mongoid::Attributes do
245
245
  end
246
246
  end
247
247
 
248
+ context "when the field was not explicitly defined" do
249
+
250
+ context "when excluding with only and the field was not excluded" do
251
+
252
+ let(:from_db) do
253
+ Person.only(:_id).first
254
+ end
255
+
256
+ it "raises an error" do
257
+ expect {
258
+ from_db[:undefined_field]
259
+ }.to raise_error(ActiveModel::MissingAttributeError)
260
+ end
261
+ end
262
+
263
+ context "when excluding with without and the field was excluded" do
264
+
265
+ let(:from_db) do
266
+ Person.without(:title).first
267
+ end
268
+
269
+ it "raises an error" do
270
+ expect {
271
+ from_db[:title]
272
+ }.to raise_error(ActiveModel::MissingAttributeError)
273
+ end
274
+ end
275
+
276
+ context "when excluding with without and the field was not excluded" do
277
+
278
+ let(:from_db) do
279
+ Person.without(:title).first
280
+ end
281
+
282
+ it "returns nil" do
283
+ from_db[:undefined_field].should be nil
284
+ end
285
+ end
286
+ end
287
+
288
+ context 'when projecting with #only' do
289
+ let!(:person) do
290
+ Person.create(title: 'sir', name: { first_name: 'Jose', language: { name: 'es' } })
291
+ end
292
+
293
+ context 'when projecting an embedded association' do
294
+ let(:from_db) do
295
+ Person.only(:name).first
296
+ end
297
+
298
+ context 'when retrieving a field of the association using the dot notation' do
299
+
300
+ it 'retrieves the field' do
301
+ pending 'MONGOID-5032, fixed in 7.3'
302
+
303
+ expect(from_db['name.first_name']).to eq 'Jose'
304
+ end
305
+ end
306
+
307
+ context 'when retrieving a field of a nested association using the dot notation' do
308
+ it 'retrieves the field' do
309
+ pending 'MONGOID-5032, fixed in 7.3'
310
+
311
+ expect(from_db['name.language.name']).to eq 'es'
312
+ end
313
+ end
314
+ end
315
+
316
+ context 'when projecting a sub-association of an embedded association' do
317
+ let(:from_db) do
318
+ Person.only('name.language').first
319
+ end
320
+
321
+ context 'when retrieving a field under the projected sub-association' do
322
+ it 'retrieves the field' do
323
+ pending 'MONGOID-5032, fixed in 7.3'
324
+
325
+ expect(from_db['name.language.name']).to eq 'es'
326
+ end
327
+ end
328
+
329
+ context 'when retrieving a non-projected field' do
330
+ it 'raises MissingAttributeError' do
331
+ expect do
332
+ from_db['name.first_name']
333
+ end.to raise_error(ActiveModel::MissingAttributeError)
334
+ end
335
+ end
336
+ end
337
+ end
338
+
248
339
  context "when the attribute does not exist" do
249
340
 
250
341
  before do
@@ -329,6 +420,67 @@ describe Mongoid::Attributes do
329
420
  expect(terms).to eq(true)
330
421
  end
331
422
  end
423
+
424
+ context 'when the field is not explicitly defined' do
425
+ let(:bar) { Bar.new }
426
+
427
+ before do
428
+ bar['missing_field'] = 42
429
+ end
430
+
431
+ it 'writes the value into attributes' do
432
+ bar.attributes.should == {'_id' => bar.id, 'missing_field' => 42}
433
+ end
434
+
435
+ it 'makes the attribute accessible via []' do
436
+ bar['missing_field'].should == 42
437
+ end
438
+
439
+ context 'when writing fields on a document with projection' do
440
+
441
+ let!(:person) do
442
+ Person.create(title: "sir")
443
+ end
444
+
445
+ context "when excluding with only and the field was not excluded" do
446
+
447
+ let(:from_db) do
448
+ Person.only(:_id).first
449
+ end
450
+
451
+ it "raises an error" do
452
+ expect {
453
+ from_db[:undefined_field] = 'x'
454
+ }.to raise_error(ActiveModel::MissingAttributeError)
455
+ end
456
+ end
457
+
458
+ context "when excluding with without and the field was excluded" do
459
+
460
+ let(:from_db) do
461
+ Person.without(:title).first
462
+ end
463
+
464
+ it "raises an error" do
465
+ expect {
466
+ from_db[:title] = 'x'
467
+ }.to raise_error(ActiveModel::MissingAttributeError)
468
+ end
469
+ end
470
+
471
+ context "when excluding with without and the field was not excluded" do
472
+
473
+ let(:from_db) do
474
+ Person.without(:title).first
475
+ end
476
+
477
+ it "writes the value" do
478
+ from_db[:undefined_field] = 'x'
479
+ from_db[:undefined_field].should == 'x'
480
+ end
481
+ end
482
+ end
483
+ end
332
484
  end
333
485
 
334
486
  describe "#_id" do
@@ -893,6 +1045,50 @@ describe Mongoid::Attributes do
893
1045
  expect(person.age_before_type_cast).to eq("old")
894
1046
  end
895
1047
  end
1048
+
1049
+ context 'when reading fields on a document with projection' do
1050
+
1051
+ let!(:person) do
1052
+ Person.create(title: "sir")
1053
+ end
1054
+
1055
+ context "when excluding with only and the field was not excluded" do
1056
+
1057
+ let(:from_db) do
1058
+ Person.only(:_id).first
1059
+ end
1060
+
1061
+ it "raises an error" do
1062
+ expect {
1063
+ from_db.read_attribute(:undefined_field)
1064
+ }.to raise_error(ActiveModel::MissingAttributeError)
1065
+ end
1066
+ end
1067
+
1068
+ context "when excluding with without and the field was excluded" do
1069
+
1070
+ let(:from_db) do
1071
+ Person.without(:title).first
1072
+ end
1073
+
1074
+ it "raises an error" do
1075
+ expect {
1076
+ from_db.read_attribute(:title)
1077
+ }.to raise_error(ActiveModel::MissingAttributeError)
1078
+ end
1079
+ end
1080
+
1081
+ context "when excluding with without and the field was not excluded" do
1082
+
1083
+ let(:from_db) do
1084
+ Person.without(:title).first
1085
+ end
1086
+
1087
+ it "returns nil" do
1088
+ from_db.read_attribute(:undefined_field).should be nil
1089
+ end
1090
+ end
1091
+ end
896
1092
  end
897
1093
 
898
1094
  describe "#attribute_present?" do
@@ -1398,6 +1594,51 @@ describe Mongoid::Attributes do
1398
1594
  expect(dictionary.description).to eq('foo')
1399
1595
  end
1400
1596
  end
1597
+
1598
+ context 'when writing fields on a document with projection' do
1599
+
1600
+ let!(:person) do
1601
+ Person.create(title: "sir")
1602
+ end
1603
+
1604
+ context "when excluding with only and the field was not excluded" do
1605
+
1606
+ let(:from_db) do
1607
+ Person.only(:_id).first
1608
+ end
1609
+
1610
+ it "raises an error" do
1611
+ expect {
1612
+ from_db.write_attribute(:undefined_field, 'x')
1613
+ }.to raise_error(ActiveModel::MissingAttributeError)
1614
+ end
1615
+ end
1616
+
1617
+ context "when excluding with without and the field was excluded" do
1618
+
1619
+ let(:from_db) do
1620
+ Person.without(:title).first
1621
+ end
1622
+
1623
+ it "raises an error" do
1624
+ expect {
1625
+ from_db.write_attribute(:title, 'x')
1626
+ }.to raise_error(ActiveModel::MissingAttributeError)
1627
+ end
1628
+ end
1629
+
1630
+ context "when excluding with without and the field was not excluded" do
1631
+
1632
+ let(:from_db) do
1633
+ Person.without(:title).first
1634
+ end
1635
+
1636
+ it "writes the value" do
1637
+ from_db.write_attribute(:undefined_field, 'x')
1638
+ from_db.read_attribute(:undefined_field).should == 'x'
1639
+ end
1640
+ end
1641
+ end
1401
1642
  end
1402
1643
 
1403
1644
  describe "#typed_value_for" do
@@ -753,12 +753,25 @@ describe Mongoid::Contextual::Atomic do
753
753
  context.set(name: "Recoil")
754
754
  end
755
755
 
756
- it "sets existing fields" do
757
- expect(depeche_mode.reload.name).to eq("Recoil")
756
+ shared_examples 'writes as expected' do
757
+ it "sets existing fields" do
758
+ expect(depeche_mode.reload.name).to eq("Recoil")
759
+ end
760
+
761
+ it "sets non existent fields" do
762
+ expect(smiths.reload.name).to eq("Recoil")
763
+ end
758
764
  end
759
765
 
760
- it "sets non existent fields" do
761
- expect(smiths.reload.name).to eq("Recoil")
766
+ include_examples 'writes as expected'
767
+
768
+ context 'when fields being set have been projected out' do
769
+
770
+ let(:criteria) do
771
+ Band.only(:genres)
772
+ end
773
+
774
+ include_examples 'writes as expected'
762
775
  end
763
776
  end
764
777