mongoid 7.2.3 → 7.3.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.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +16 -0
  5. data/lib/config/locales/en.yml +2 -2
  6. data/lib/mongoid/association/accessors.rb +1 -1
  7. data/lib/mongoid/association/constrainable.rb +1 -1
  8. data/lib/mongoid/association/depending.rb +4 -4
  9. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  10. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  11. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
  12. data/lib/mongoid/association/nested/many.rb +1 -1
  13. data/lib/mongoid/association/nested/one.rb +4 -2
  14. data/lib/mongoid/association/proxy.rb +6 -1
  15. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  16. data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
  17. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  18. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  19. data/lib/mongoid/attributes.rb +24 -13
  20. data/lib/mongoid/attributes/projector.rb +120 -0
  21. data/lib/mongoid/cacheable.rb +2 -2
  22. data/lib/mongoid/clients.rb +1 -1
  23. data/lib/mongoid/clients/factory.rb +22 -8
  24. data/lib/mongoid/config.rb +19 -2
  25. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  26. data/lib/mongoid/copyable.rb +1 -1
  27. data/lib/mongoid/criteria.rb +4 -5
  28. data/lib/mongoid/criteria/findable.rb +1 -1
  29. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  30. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  31. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  32. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  33. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  34. data/lib/mongoid/document.rb +1 -15
  35. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  36. data/lib/mongoid/evolvable.rb +1 -1
  37. data/lib/mongoid/extensions/boolean.rb +1 -2
  38. data/lib/mongoid/extensions/false_class.rb +1 -1
  39. data/lib/mongoid/extensions/hash.rb +2 -2
  40. data/lib/mongoid/extensions/true_class.rb +1 -1
  41. data/lib/mongoid/fields.rb +43 -5
  42. data/lib/mongoid/inspectable.rb +1 -1
  43. data/lib/mongoid/matcher.rb +7 -0
  44. data/lib/mongoid/matcher/bits.rb +41 -0
  45. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  46. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  47. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  48. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  49. data/lib/mongoid/matcher/expression.rb +4 -0
  50. data/lib/mongoid/matcher/field_operator.rb +6 -0
  51. data/lib/mongoid/matcher/mod.rb +17 -0
  52. data/lib/mongoid/matcher/type.rb +99 -0
  53. data/lib/mongoid/persistable/deletable.rb +1 -2
  54. data/lib/mongoid/persistable/destroyable.rb +8 -2
  55. data/lib/mongoid/persistable/updatable.rb +27 -2
  56. data/lib/mongoid/query_cache.rb +35 -29
  57. data/lib/mongoid/selectable.rb +5 -7
  58. data/lib/mongoid/shardable.rb +21 -5
  59. data/lib/mongoid/touchable.rb +23 -4
  60. data/lib/mongoid/version.rb +1 -1
  61. data/spec/integration/associations/embeds_many_spec.rb +44 -0
  62. data/spec/integration/associations/has_one_spec.rb +48 -0
  63. data/spec/integration/criteria/date_field_spec.rb +1 -1
  64. data/spec/integration/document_spec.rb +9 -0
  65. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  66. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  67. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  68. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  69. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  70. data/spec/integration/matcher_operator_data/in.yml +16 -0
  71. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  72. data/spec/integration/matcher_operator_data/type.yml +70 -0
  73. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  74. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  75. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  76. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  77. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  78. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  79. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  80. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  81. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  82. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  83. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  84. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  85. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  86. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  87. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  88. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  89. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  90. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  91. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  92. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  93. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  94. data/spec/lite_spec_helper.rb +2 -0
  95. data/spec/mongoid/association/depending_spec.rb +391 -352
  96. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  97. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  98. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  99. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  100. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
  101. data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
  102. data/spec/mongoid/atomic/paths_spec.rb +64 -12
  103. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  104. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  105. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  106. data/spec/mongoid/attributes_spec.rb +98 -6
  107. data/spec/mongoid/clients/factory_spec.rb +48 -0
  108. data/spec/mongoid/config_spec.rb +32 -0
  109. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  110. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  111. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  112. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  113. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  114. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +229 -24
  115. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  116. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  117. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  118. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  119. data/spec/mongoid/criteria_spec.rb +0 -275
  120. data/spec/mongoid/document_spec.rb +13 -13
  121. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  122. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  123. data/spec/mongoid/extensions/string_spec.rb +5 -5
  124. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  125. data/spec/mongoid/fields/localized_spec.rb +4 -4
  126. data/spec/mongoid/fields_spec.rb +4 -4
  127. data/spec/mongoid/inspectable_spec.rb +12 -4
  128. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  129. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  130. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  131. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  132. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  133. data/spec/mongoid/reloadable_spec.rb +18 -1
  134. data/spec/mongoid/shardable_spec.rb +44 -0
  135. data/spec/mongoid/touchable_spec.rb +104 -16
  136. data/spec/mongoid/touchable_spec_models.rb +52 -0
  137. data/spec/mongoid/validatable_spec.rb +1 -1
  138. data/spec/spec_helper.rb +6 -2
  139. data/spec/support/client_registry.rb +9 -0
  140. data/spec/support/models/bolt.rb +8 -0
  141. data/spec/support/models/hole.rb +13 -0
  142. data/spec/support/models/mop.rb +0 -1
  143. data/spec/support/models/nut.rb +8 -0
  144. data/spec/support/models/person.rb +6 -0
  145. data/spec/support/models/sealer.rb +8 -0
  146. data/spec/support/models/shirt.rb +12 -0
  147. data/spec/support/models/spacer.rb +8 -0
  148. data/spec/support/models/threadlocker.rb +8 -0
  149. data/spec/support/models/washer.rb +8 -0
  150. metadata +97 -3
  151. metadata.gz.sig +5 -3
  152. data/spec/support/cluster_config.rb +0 -158
@@ -0,0 +1,15 @@
1
+ - name: existing field - matches string
2
+ document:
3
+ name: bob
4
+ query:
5
+ name:
6
+ $type: 2
7
+ matches: true
8
+
9
+ - name: existing field - does not match string
10
+ document:
11
+ pi: 3
12
+ query:
13
+ pi:
14
+ $type: 2
15
+ matches: false
@@ -0,0 +1,32 @@
1
+ - name: symbol in untyped field - matches
2
+ document:
3
+ name: :hello
4
+ query:
5
+ name:
6
+ $type: 14
7
+ matches: true
8
+
9
+ - name: symbol field - matches
10
+ document:
11
+ symbol_field: :hello
12
+ query:
13
+ symbol_field:
14
+ $type: 14
15
+ matches: true
16
+
17
+ - name: bson symbol - matches
18
+ document:
19
+ bson_symbol_field: !ruby/object:BSON::Symbol::Raw
20
+ symbol: hello
21
+ query:
22
+ bson_symbol_field:
23
+ $type: 14
24
+ matches: true
25
+
26
+ - name: string field - does not match
27
+ document:
28
+ pi: hello
29
+ query:
30
+ pi:
31
+ $type: 14
32
+ matches: false
@@ -0,0 +1,25 @@
1
+ - name: existing field - matches timestamp
2
+ document:
3
+ time: !ruby/object:BSON::Timestamp
4
+ seconds: 4
5
+ increment: 2
6
+ query:
7
+ time:
8
+ $type: 17
9
+ matches: true
10
+
11
+ - name: existing field - does not match timestamp
12
+ document:
13
+ name: 3
14
+ query:
15
+ name:
16
+ $type: 17
17
+ matches: false
18
+
19
+ - name: Ruby Time instance - does not match
20
+ document:
21
+ time_field: 2020-11-19 00:00:00
22
+ query:
23
+ time_field:
24
+ $type: 17
25
+ matches: false
@@ -0,0 +1,17 @@
1
+ - name: existing field - matches undefined
2
+ document:
3
+ price: !ruby/object:BSON::Undefined
4
+ # dummy field so Undefined gets constructed
5
+ test: 42
6
+ query:
7
+ price:
8
+ $type: 6
9
+ matches: true
10
+
11
+ - name: existing field - does not match undefined
12
+ document:
13
+ pi: 3
14
+ query:
15
+ pi:
16
+ $type: 6
17
+ matches: false
@@ -15,6 +15,8 @@ require "mongo"
15
15
  # https://github.com/jruby/jruby/issues/5599
16
16
  require 'pp'
17
17
 
18
+ autoload :Timecop, 'timecop'
19
+
18
20
  require 'support/spec_config'
19
21
  require 'mrss/lite_constraints'
20
22
  require "support/session_registry"
@@ -5,7 +5,7 @@ require "spec_helper"
5
5
 
6
6
  describe Mongoid::Association::Depending do
7
7
 
8
- describe '#self.included' do
8
+ describe '.included' do
9
9
 
10
10
  context 'when a destroy dependent is defined' do
11
11
 
@@ -264,7 +264,7 @@ describe Mongoid::Association::Depending do
264
264
  Person.relations = relations_before
265
265
  end
266
266
 
267
- describe "#apply_delete_dependencies!" do
267
+ describe "#apply_destroy_dependencies!" do
268
268
 
269
269
  let(:band) do
270
270
  Band.new
@@ -283,7 +283,7 @@ describe Mongoid::Association::Depending do
283
283
  end
284
284
 
285
285
  it "ignores the dependency" do
286
- expect(band.apply_delete_dependencies!).to eq([Band.relations["records"]])
286
+ expect(band.apply_destroy_dependencies!).to eq([Band.relations["records"]])
287
287
  end
288
288
  end
289
289
  end
@@ -303,7 +303,7 @@ describe Mongoid::Association::Depending do
303
303
 
304
304
  it "does not raise an error" do
305
305
  expect {
306
- klass.new.apply_delete_dependencies!
306
+ klass.new.apply_destroy_dependencies!
307
307
  }.not_to raise_error
308
308
  end
309
309
  end
@@ -351,72 +351,65 @@ describe Mongoid::Association::Depending do
351
351
  end
352
352
  end
353
353
 
354
- [:delete, :destroy].each do |method|
355
-
356
- describe "##{method}" do
357
-
358
- context "when cascading removals" do
359
-
360
- context "when strategy is delete" do
361
-
362
- let(:person) do
363
- Person.create
364
- end
365
-
366
- let!(:post) do
367
- person.posts.create(title: "Testing")
368
- end
354
+ describe '#delete and #destroy' do
355
+ context "when cascading removals" do
369
356
 
357
+ shared_examples 'destroys dependents if parent is destroyed but does not if parent is deleted' do
358
+ context '#destroy' do
370
359
  before do
371
- person.send(method)
360
+ parent.destroy
372
361
  end
373
362
 
374
363
  it "deletes the associated documents" do
375
364
  expect {
376
- Post.find(post.id)
365
+ child.class.find(child.id)
377
366
  }.to raise_error(Mongoid::Errors::DocumentNotFound)
378
367
  end
379
368
  end
380
369
 
381
- context "when strategy is destroy" do
382
-
383
- let(:person) do
384
- Person.create
370
+ context '#delete' do
371
+ before do
372
+ parent.delete
385
373
  end
386
374
 
387
- let!(:game) do
388
- person.create_game(name: "Pong")
375
+ it "does not delete the associated documents" do
376
+ child.class.find(child.id).should == child
389
377
  end
378
+ end
379
+ end
390
380
 
391
- before do
392
- person.send(method)
393
- end
381
+ context "when strategy is delete" do
394
382
 
395
- it "destroys the associated documents" do
396
- expect {
397
- Game.find(game.id)
398
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
399
- end
383
+ let(:parent) do
384
+ Person.create
400
385
  end
401
386
 
402
- context "when strategy is nullify" do
387
+ let!(:child) do
388
+ parent.posts.create(title: "Testing")
389
+ end
403
390
 
404
- context "when nullifying a references many" do
391
+ include_examples 'destroys dependents if parent is destroyed but does not if parent is deleted'
392
+ end
405
393
 
406
- let(:movie) do
407
- Movie.create(title: "Bladerunner")
408
- end
394
+ context "when strategy is destroy" do
409
395
 
410
- let!(:rating) do
411
- movie.ratings.create(value: 10)
412
- end
396
+ let(:parent) do
397
+ Person.create
398
+ end
413
399
 
414
- let(:from_db) do
415
- Rating.find(rating.id)
416
- end
400
+ let!(:child) do
401
+ parent.create_game(name: "Pong")
402
+ end
403
+
404
+ include_examples 'destroys dependents if parent is destroyed but does not if parent is deleted'
405
+ end
417
406
 
407
+ context "when strategy is nullify" do
408
+
409
+ shared_examples 'removes references if parent is destroyed but does not if parent is deleted' do
410
+ context '#destroy' do
418
411
  before do
419
- movie.send(method)
412
+ parent.destroy
420
413
  end
421
414
 
422
415
  it "removes the references to the removed document" do
@@ -424,59 +417,87 @@ describe Mongoid::Association::Depending do
424
417
  end
425
418
  end
426
419
 
427
- context "when nullifying a references one" do
420
+ context '#delete' do
421
+ before do
422
+ parent.delete
423
+ end
424
+
425
+ it "does not remove the references to the removed document" do
426
+ from_db.ratable_id.should == parent.id
427
+ end
428
+ end
429
+ end
430
+
431
+ context "when nullifying a references many" do
428
432
 
429
- context "when the relation exists" do
433
+ let(:parent) do
434
+ Movie.create(title: "Bladerunner")
435
+ end
430
436
 
431
- let(:book) do
432
- Book.create(title: "Neuromancer")
433
- end
437
+ let!(:rating) do
438
+ parent.ratings.create(value: 10)
439
+ end
434
440
 
435
- let!(:rating) do
436
- book.create_rating(value: 10)
437
- end
441
+ let(:from_db) do
442
+ Rating.find(rating.id)
443
+ end
438
444
 
439
- let(:from_db) do
440
- Rating.find(rating.id)
441
- end
445
+ include_examples 'removes references if parent is destroyed but does not if parent is deleted'
446
+ end
442
447
 
443
- before do
444
- book.send(method)
445
- end
448
+ context "when nullifying a references one" do
446
449
 
447
- it "removes the references to the removed document" do
448
- expect(from_db.ratable_id).to be_nil
449
- end
450
- end
450
+ context "when the relation exists" do
451
451
 
452
- context "when the relation is nil" do
452
+ let(:parent) do
453
+ Book.create(title: "Neuromancer")
454
+ end
453
455
 
454
- let(:book) do
455
- Book.create(title: "Neuromancer")
456
- end
456
+ let!(:rating) do
457
+ parent.create_rating(value: 10)
458
+ end
457
459
 
458
- it "returns nil" do
459
- expect(book.send(method)).to be true
460
- end
460
+ let(:from_db) do
461
+ Rating.find(rating.id)
461
462
  end
463
+
464
+ include_examples 'removes references if parent is destroyed but does not if parent is deleted'
462
465
  end
463
466
 
464
- context "when nullifying a many to many" do
467
+ context "when no association target exists" do
465
468
 
466
- let(:person) do
467
- Person.create
469
+ let(:parent) do
470
+ Book.create(title: "Neuromancer")
468
471
  end
469
472
 
470
- let!(:preference) do
471
- person.preferences.create(name: "Setting")
472
- end
473
+ [:delete, :destroy].each do |method|
473
474
 
474
- let(:from_db) do
475
- Preference.find(preference.id)
475
+ describe "##{method}" do
476
+ it "succeeds" do
477
+ expect(parent.send(method)).to be true
478
+ end
479
+ end
476
480
  end
481
+ end
482
+ end
483
+
484
+ context "when nullifying a many to many" do
485
+
486
+ let(:person) do
487
+ Person.create
488
+ end
489
+
490
+ let!(:preference) do
491
+ person.preferences.create(name: "Setting")
492
+ end
493
+
494
+ let(:from_db) do
495
+ Preference.find(preference.id)
496
+ end
477
497
 
498
+ context '#destroy' do
478
499
  before do
479
- person.send(method)
500
+ person.destroy
480
501
  end
481
502
 
482
503
  it "removes the references from the removed document" do
@@ -487,356 +508,327 @@ describe Mongoid::Association::Depending do
487
508
  expect(from_db.person_ids).to_not include(person.id)
488
509
  end
489
510
  end
490
- end
491
-
492
- context "when dependent is restrict_with_exception" do
493
-
494
- context "when restricting a references many" do
495
511
 
496
- let!(:association) do
497
- Person.has_many :drugs, dependent: :restrict_with_exception
498
- end
499
-
500
- after do
501
- Person.dependents.delete(association)
502
- Person.has_many :drugs, validate: false
512
+ context '#delete' do
513
+ before do
514
+ person.delete
503
515
  end
504
516
 
505
- context "when the relation is empty" do
506
-
507
- let(:person) do
508
- Person.new drugs: []
509
- end
510
-
511
- it "raises no error" do
512
- expect { person.send(method) }.to_not raise_error
513
- end
514
-
515
- it "deletes the parent" do
516
- person.send(method)
517
- expect(person).to be_destroyed
518
- end
517
+ it "keeps the references from the removed document" do
518
+ expect(person.preference_ids).to include(preference.id)
519
519
  end
520
520
 
521
- context "when the relation is not empty" do
522
-
523
- let(:person) do
524
- Person.new drugs: [Drug.new]
525
- end
526
-
527
- it "raises DeleteRestriction error" do
528
- expect { person.send(method) }.to raise_error(Mongoid::Errors::DeleteRestriction)
529
- end
521
+ it "keeps the references to the removed document" do
522
+ expect(from_db.person_ids).to include(person.id)
530
523
  end
531
524
  end
525
+ end
526
+ end
532
527
 
533
- context "when restricting a references one" do
528
+ shared_examples 'deletes the parent with #delete and #destroy' do
529
+ [:delete, :destroy].each do |method|
534
530
 
535
- let!(:association) do
536
- Person.has_one :account, dependent: :restrict_with_exception
531
+ describe "##{method}" do
532
+ it "raises no error" do
533
+ expect { person.send(method) }.to_not raise_error
537
534
  end
538
535
 
539
- after do
540
- Person.dependents.delete(association)
541
- Person.has_one :account, validate: false
536
+ it "deletes the parent" do
537
+ person.send(method)
538
+ expect(person).to be_destroyed
542
539
  end
540
+ end
541
+ end
542
+ end
543
543
 
544
- context "when the relation is empty" do
544
+ shared_examples 'raises an error with #destroy and deletes the parent with #delete' do
545
+ context '#destroy' do
546
+ it "raises DeleteRestriction error" do
547
+ expect { person.destroy }.to raise_error(Mongoid::Errors::DeleteRestriction)
548
+ end
549
+ end
545
550
 
546
- let(:person) do
547
- Person.new account: nil
548
- end
551
+ context '#delete' do
552
+ it "deletes the parent" do
553
+ person.delete
554
+ expect(person).to be_destroyed
555
+ end
556
+ end
557
+ end
549
558
 
550
- it "raises no error" do
551
- expect { person.send(method) }.to_not raise_error
552
- end
559
+ context "when dependent is restrict_with_exception" do
553
560
 
554
- it "deletes the parent" do
555
- person.send(method)
556
- expect(person).to be_destroyed
557
- end
558
- end
561
+ context "when restricting a references many" do
559
562
 
560
- context "when the relation is not empty" do
563
+ let!(:association) do
564
+ Person.has_many :drugs, dependent: :restrict_with_exception
565
+ end
561
566
 
562
- let(:person) do
563
- Person.new account: Account.new(name: 'test')
564
- end
567
+ after do
568
+ Person.dependents.delete(association)
569
+ Person.has_many :drugs, validate: false
570
+ end
565
571
 
566
- it "raises DeleteRestriction error" do
567
- expect { person.send(method) }.to raise_error(Mongoid::Errors::DeleteRestriction)
568
- end
572
+ context "when the relation is empty" do
573
+
574
+ let(:person) do
575
+ Person.new drugs: []
569
576
  end
577
+
578
+ include_examples 'deletes the parent with #delete and #destroy'
570
579
  end
571
580
 
572
- context "when restricting a many to many" do
581
+ context "when the relation is not empty" do
573
582
 
574
- let!(:association) do
575
- Person.has_and_belongs_to_many :houses, dependent: :restrict_with_exception
583
+ let(:person) do
584
+ Person.new drugs: [Drug.new]
576
585
  end
577
586
 
578
- after do
579
- Person.dependents.delete(association)
580
- Person.has_and_belongs_to_many :houses, validate: false
581
- end
587
+ include_examples 'raises an error with #destroy and deletes the parent with #delete'
588
+ end
589
+ end
582
590
 
583
- context "when the relation is empty" do
591
+ context "when restricting a references one" do
584
592
 
585
- let(:person) do
586
- Person.new houses: []
587
- end
593
+ let!(:association) do
594
+ Person.has_one :account, dependent: :restrict_with_exception
595
+ end
588
596
 
589
- it "raises no error" do
590
- expect { person.send(method) }.to_not raise_error
591
- end
597
+ after do
598
+ Person.dependents.delete(association)
599
+ Person.has_one :account, validate: false
600
+ end
592
601
 
593
- it "deletes the parent" do
594
- person.send(method)
595
- expect(person).to be_destroyed
596
- end
602
+ context "when the relation is empty" do
603
+
604
+ let(:person) do
605
+ Person.new account: nil
597
606
  end
598
607
 
599
- context "when the relation is not empty" do
608
+ include_examples 'deletes the parent with #delete and #destroy'
609
+ end
600
610
 
601
- let(:person) do
602
- Person.new houses: [House.new]
603
- end
611
+ context "when the relation is not empty" do
604
612
 
605
- it "raises DeleteRestriction error" do
606
- expect { person.send(method) }.to raise_error(Mongoid::Errors::DeleteRestriction)
607
- end
613
+ let(:person) do
614
+ Person.new account: Account.new(name: 'test')
608
615
  end
616
+
617
+ include_examples 'raises an error with #destroy and deletes the parent with #delete'
609
618
  end
610
619
  end
611
- end
612
- end
613
- end
614
-
615
- context 'when the strategy is :delete_all' do
616
-
617
- let(:person) do
618
- Person.create
619
- end
620
620
 
621
- context "when cascading a has one" do
621
+ context "when restricting a many to many" do
622
622
 
623
- context "when the relation exists" do
623
+ let!(:association) do
624
+ Person.has_and_belongs_to_many :houses, dependent: :restrict_with_exception
625
+ end
624
626
 
625
- let!(:home) do
626
- person.create_home
627
- end
627
+ after do
628
+ Person.dependents.delete(association)
629
+ Person.has_and_belongs_to_many :houses, validate: false
630
+ end
628
631
 
629
- before do
630
- person.delete
631
- end
632
+ context "when the relation is empty" do
632
633
 
633
- it "deletes the relation" do
634
- expect(home).to be_destroyed
635
- end
634
+ let(:person) do
635
+ Person.new houses: []
636
+ end
636
637
 
637
- it "persists the deletion" do
638
- expect {
639
- home.reload
640
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
641
- end
642
- end
638
+ include_examples 'deletes the parent with #delete and #destroy'
639
+ end
643
640
 
644
- context "when the relation does not exist" do
641
+ context "when the relation is not empty" do
645
642
 
646
- before do
647
- person.delete
648
- end
643
+ let(:person) do
644
+ Person.new houses: [House.new]
645
+ end
649
646
 
650
- it "deletes the base document" do
651
- expect(person).to be_destroyed
647
+ include_examples 'raises an error with #destroy and deletes the parent with #delete'
648
+ end
652
649
  end
653
650
  end
654
651
  end
655
652
 
656
- context "when cascading a has many" do
653
+ context 'when the strategy is :delete_all' do
657
654
 
658
- context "when the relation has documents" do
655
+ let(:person) do
656
+ Person.create
657
+ end
659
658
 
660
- let!(:post_one) do
661
- person.posts.create(title: "one")
662
- end
659
+ context "when cascading a has one" do
663
660
 
664
- let!(:post_two) do
665
- person.posts.create(title: "two")
666
- end
661
+ context "when the relation exists" do
667
662
 
668
- context "when the documents are in memory" do
663
+ let!(:home) do
664
+ person.create_home
665
+ end
669
666
 
670
667
  before do
671
- expect(post_one).to receive(:delete).never
672
- expect(post_two).to receive(:delete).never
673
- person.delete
668
+ person.destroy
674
669
  end
675
670
 
676
- it "deletes the first document" do
677
- expect(post_one).to be_destroyed
671
+ it "deletes the dependents" do
672
+ expect(home).to be_destroyed
678
673
  end
679
674
 
680
- it "deletes the second document" do
681
- expect(post_two).to be_destroyed
675
+ it "persists the deletion" do
676
+ expect {
677
+ home.reload
678
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
682
679
  end
680
+ end
683
681
 
684
- it "unbinds the first document" do
685
- expect(post_one.person).to be_nil
686
- end
682
+ context "when the association target does not exist" do
687
683
 
688
- it "unbinds the second document" do
689
- expect(post_two.person).to be_nil
684
+ before do
685
+ person.destroy
690
686
  end
691
687
 
692
- it "removes the documents from the relation" do
693
- expect(person.posts).to be_empty
688
+ it "deletes the base document" do
689
+ expect(person).to be_destroyed
694
690
  end
691
+ end
692
+ end
695
693
 
696
- it "persists the first deletion" do
697
- expect {
698
- post_one.reload
699
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
694
+ context "when cascading a has many" do
695
+
696
+ context "when the relation has documents" do
697
+
698
+ let!(:post_one) do
699
+ person.posts.create(title: "one")
700
700
  end
701
701
 
702
- it "persists the second deletion" do
703
- expect {
704
- post_two.reload
705
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
702
+ let!(:post_two) do
703
+ person.posts.create(title: "two")
706
704
  end
707
- end
708
- end
709
- end
710
- end
711
705
 
712
- context 'when the strategy is :destroy' do
706
+ context "when the documents are in memory" do
713
707
 
714
- let!(:association) do
715
- Person.has_many :destroyable_posts, class_name: "Post", dependent: :destroy
716
- end
708
+ before do
709
+ expect(post_one).to receive(:delete).never
710
+ expect(post_two).to receive(:delete).never
711
+ person.destroy
712
+ end
717
713
 
718
- after do
719
- Person.dependents.delete(association)
720
- end
714
+ it "deletes the first document" do
715
+ expect(post_one).to be_destroyed
716
+ end
721
717
 
722
- let(:person) do
723
- Person.new
724
- end
718
+ it "deletes the second document" do
719
+ expect(post_two).to be_destroyed
720
+ end
725
721
 
726
- let(:post) do
727
- Post.new
728
- end
722
+ it "unbinds the first document" do
723
+ expect(post_one.person).to be_nil
724
+ end
729
725
 
730
- context "when the documents exist" do
726
+ it "unbinds the second document" do
727
+ expect(post_two.person).to be_nil
728
+ end
731
729
 
732
- before do
733
- expect(post).to receive(:destroy)
734
- person.destroyable_posts << post
735
- end
730
+ it "removes the documents from the relation" do
731
+ expect(person.posts).to be_empty
732
+ end
733
+
734
+ it "persists the first deletion" do
735
+ expect {
736
+ post_one.reload
737
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
738
+ end
736
739
 
737
- it "destroys all documents in the relation" do
738
- person.delete
740
+ it "persists the second deletion" do
741
+ expect {
742
+ post_two.reload
743
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
744
+ end
745
+ end
746
+ end
739
747
  end
740
748
  end
741
749
 
742
- context "when no documents exist" do
750
+ context 'when the strategy is :destroy' do
743
751
 
744
- before do
745
- expect(post).to receive(:destroy).never
752
+ let!(:association) do
753
+ Person.has_many :destroyable_posts, class_name: "Post", dependent: :destroy
746
754
  end
747
755
 
748
- it "it does not destroy the relation" do
749
- person.delete
756
+ after do
757
+ Person.dependents.delete(association)
750
758
  end
751
- end
752
- end
753
759
 
754
- context 'when the strategy is :nullify' do
755
-
756
- let!(:association) do
757
- Person.has_many :nullifyable_posts, class_name: "Post", dependent: :nullify
758
- end
759
-
760
- after do
761
- Person.dependents.delete(association)
762
- end
763
-
764
- let(:person) do
765
- Person.new
766
- end
760
+ let(:person) do
761
+ Person.new
762
+ end
767
763
 
768
- let(:posts_relation) do
769
- person.posts
770
- end
764
+ let(:post) do
765
+ Post.new
766
+ end
771
767
 
772
- before do
773
- allow(person).to receive(:nullifyable_posts).and_return(posts_relation)
774
- expect(posts_relation).to receive(:nullify)
775
- end
768
+ context "when the documents exist" do
776
769
 
777
- it "nullifies the relation" do
778
- person.delete
779
- end
780
- end
770
+ before do
771
+ expect(post).to receive(:destroy)
772
+ person.destroyable_posts << post
773
+ end
781
774
 
782
- context 'when the strategy is :restrict_with_exception' do
775
+ it "destroys all documents in the association" do
776
+ person.destroy
777
+ end
778
+ end
783
779
 
784
- let(:person) do
785
- Person.new
786
- end
780
+ context "when no documents exist" do
787
781
 
788
- let(:post) do
789
- Post.new
790
- end
782
+ before do
783
+ expect(post).to receive(:destroy).never
784
+ end
791
785
 
792
- let!(:association) do
793
- Person.has_many :restrictable_posts, class_name: "Post", dependent: :restrict_with_exception
786
+ it "it does not destroy the association target" do
787
+ person.destroy
788
+ end
789
+ end
794
790
  end
795
791
 
796
- after do
797
- Person.dependents.delete(association)
798
- end
792
+ context 'when the strategy is :nullify' do
799
793
 
800
- context 'when there are related objects' do
794
+ let!(:association) do
795
+ Person.has_many :nullifyable_posts, class_name: "Post", dependent: :nullify
796
+ end
801
797
 
802
- before do
803
- person.restrictable_posts << post
804
- expect(post).to receive(:delete).never
805
- expect(post).to receive(:destroy).never
798
+ after do
799
+ Person.dependents.delete(association)
806
800
  end
807
801
 
808
- it 'raises an exception and leaves the related one intact' do
809
- expect { person.delete }.to raise_exception(Mongoid::Errors::DeleteRestriction)
802
+ let(:person) do
803
+ Person.new
810
804
  end
811
- end
812
805
 
813
- context 'when there are no related objects' do
806
+ let(:posts_relation) do
807
+ person.posts
808
+ end
814
809
 
815
810
  before do
816
- expect(post).to receive(:delete).never
817
- expect(post).to receive(:destroy).never
811
+ allow(person).to receive(:nullifyable_posts).and_return(posts_relation)
812
+ expect(posts_relation).to receive(:nullify)
818
813
  end
819
814
 
820
- it 'deletes the object and leaves the other one intact' do
821
- expect(person.delete).to be(true)
815
+ it "nullifies the association target" do
816
+ person.destroy
822
817
  end
823
818
  end
824
- end
825
819
 
826
- context 'when the strategy is :restrict_with_error' do
820
+ context 'when the strategy is :restrict_with_exception' do
827
821
 
828
- context "when restricting a one-to-many" do
829
-
830
822
  let(:person) do
831
823
  Person.new
832
824
  end
833
-
825
+
834
826
  let(:post) do
835
827
  Post.new
836
828
  end
837
829
 
838
830
  let!(:association) do
839
- Person.has_many :restrictable_posts, class_name: "Post", dependent: :restrict_with_error
831
+ Person.has_many :restrictable_posts, class_name: "Post", dependent: :restrict_with_exception
840
832
  end
841
833
 
842
834
  after do
@@ -847,13 +839,12 @@ describe Mongoid::Association::Depending do
847
839
 
848
840
  before do
849
841
  person.restrictable_posts << post
842
+ expect(post).to receive(:delete).never
843
+ expect(post).to receive(:destroy).never
850
844
  end
851
845
 
852
- it 'adds an error to the parent object' do
853
- expect(person.delete).to be(false)
854
-
855
- person.errors[:restrictable_posts].first.should ==
856
- "is not empty and prevents the document from being destroyed"
846
+ it 'raises an exception and leaves the related one intact' do
847
+ expect { person.destroy }.to raise_exception(Mongoid::Errors::DeleteRestriction)
857
848
  end
858
849
  end
859
850
 
@@ -865,53 +856,101 @@ describe Mongoid::Association::Depending do
865
856
  end
866
857
 
867
858
  it 'deletes the object and leaves the other one intact' do
868
- expect(person.delete).to be(true)
859
+ expect(person.destroy).to be(true)
869
860
  end
870
861
  end
862
+ end
871
863
 
872
- context 'when deleted inside a transaction' do
873
- require_transaction_support
874
-
875
- before do
876
- person.restrictable_posts << post
864
+ context 'when the strategy is :restrict_with_error' do
865
+
866
+ context "when restricting a one-to-many" do
867
+
868
+ let(:person) do
869
+ Person.new
870
+ end
871
+
872
+ let(:post) do
873
+ Post.new
874
+ end
875
+
876
+ let!(:association) do
877
+ Person.has_many :restrictable_posts, class_name: "Post", dependent: :restrict_with_error
877
878
  end
878
879
 
879
- it 'doesn\'t raise an exception' do
880
- person.with_session do |session|
881
- session.with_transaction do
882
- expect { person.destroy }.to_not raise_error
880
+ after do
881
+ Person.dependents.delete(association)
882
+ end
883
+
884
+ context 'when there are related objects' do
885
+
886
+ before do
887
+ person.restrictable_posts << post
888
+ end
889
+
890
+ it 'adds an error to the parent object' do
891
+ expect(person.destroy).to be(false)
892
+
893
+ person.errors[:restrictable_posts].first.should ==
894
+ "is not empty and prevents the document from being destroyed"
895
+ end
896
+ end
897
+
898
+ context 'when there are no related objects' do
899
+
900
+ before do
901
+ expect(post).to receive(:delete).never
902
+ expect(post).to receive(:destroy).never
903
+ end
904
+
905
+ it 'deletes the object and leaves the other one intact' do
906
+ expect(person.destroy).to be(true)
907
+ end
908
+ end
909
+
910
+ context 'when deleted inside a transaction' do
911
+ require_transaction_support
912
+
913
+ before do
914
+ person.restrictable_posts << post
915
+ end
916
+
917
+ it 'doesn\'t raise an exception' do
918
+ person.with_session do |session|
919
+ session.with_transaction do
920
+ expect { person.destroy }.to_not raise_error
921
+ end
883
922
  end
884
923
  end
885
924
  end
886
925
  end
887
- end
888
926
 
889
- context "when restricting a many to many" do
927
+ context "when restricting a many to many" do
890
928
 
891
- let!(:association) do
892
- Person.has_and_belongs_to_many :houses, dependent: :restrict_with_error
893
- end
929
+ let!(:association) do
930
+ Person.has_and_belongs_to_many :houses, dependent: :restrict_with_error
931
+ end
894
932
 
895
- after do
896
- Person.dependents.delete(association)
897
- Person.has_and_belongs_to_many :houses, validate: false
898
- end
933
+ after do
934
+ Person.dependents.delete(association)
935
+ Person.has_and_belongs_to_many :houses, validate: false
936
+ end
899
937
 
900
- let(:person) do
901
- Person.new houses: [House.new]
902
- end
938
+ let(:person) do
939
+ Person.new houses: [House.new]
940
+ end
903
941
 
904
- it "returns false" do
905
- expect(person.destroy).to be false
906
- end
942
+ it "returns false" do
943
+ expect(person.destroy).to be false
944
+ end
907
945
 
908
- context "when inside a transaction" do
909
- require_transaction_support
910
-
911
- it 'doesn\'t raise an exception inside a transaction' do
912
- person.with_session do |session|
913
- session.with_transaction do
914
- expect { person.destroy }.to_not raise_error
946
+ context "when inside a transaction" do
947
+ require_transaction_support
948
+
949
+ it 'doesn\'t raise an exception inside a transaction' do
950
+ person.with_session do |session|
951
+ session.with_transaction do
952
+ expect { person.destroy }.to_not raise_error
953
+ end
915
954
  end
916
955
  end
917
956
  end