mongoid 8.0.3 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +3 -3
  4. data/README.md +3 -3
  5. data/lib/config/locales/en.yml +46 -14
  6. data/lib/mongoid/association/accessors.rb +2 -2
  7. data/lib/mongoid/association/builders.rb +1 -1
  8. data/lib/mongoid/association/embedded/batchable.rb +2 -2
  9. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
  10. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
  11. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
  12. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +23 -21
  13. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
  14. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
  15. data/lib/mongoid/association/nested/one.rb +40 -2
  16. data/lib/mongoid/association/proxy.rb +1 -1
  17. data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
  18. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +5 -1
  19. data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -2
  20. data/lib/mongoid/association/referenced/has_many/proxy.rb +7 -3
  21. data/lib/mongoid/association/reflections.rb +2 -2
  22. data/lib/mongoid/attributes/dynamic.rb +1 -1
  23. data/lib/mongoid/attributes/nested.rb +2 -2
  24. data/lib/mongoid/attributes/projector.rb +1 -1
  25. data/lib/mongoid/attributes/readonly.rb +1 -1
  26. data/lib/mongoid/attributes.rb +8 -2
  27. data/lib/mongoid/changeable.rb +104 -4
  28. data/lib/mongoid/clients/storage_options.rb +2 -5
  29. data/lib/mongoid/clients/validators/storage.rb +1 -13
  30. data/lib/mongoid/collection_configurable.rb +58 -0
  31. data/lib/mongoid/composable.rb +2 -0
  32. data/lib/mongoid/config/defaults.rb +60 -0
  33. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  34. data/lib/mongoid/config/validators.rb +1 -0
  35. data/lib/mongoid/config.rb +101 -0
  36. data/lib/mongoid/contextual/atomic.rb +1 -1
  37. data/lib/mongoid/contextual/memory.rb +233 -33
  38. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  39. data/lib/mongoid/contextual/mongo.rb +373 -113
  40. data/lib/mongoid/contextual/none.rb +162 -7
  41. data/lib/mongoid/contextual.rb +12 -0
  42. data/lib/mongoid/criteria/findable.rb +2 -2
  43. data/lib/mongoid/criteria/includable.rb +4 -3
  44. data/lib/mongoid/criteria/queryable/extensions/array.rb +1 -1
  45. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -1
  46. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +0 -8
  47. data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -11
  48. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +0 -10
  49. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  50. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  51. data/lib/mongoid/criteria/queryable/optional.rb +8 -8
  52. data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
  53. data/lib/mongoid/criteria/translator.rb +45 -0
  54. data/lib/mongoid/criteria.rb +7 -5
  55. data/lib/mongoid/deprecable.rb +1 -1
  56. data/lib/mongoid/document.rb +50 -13
  57. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  58. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  59. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  60. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  61. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  62. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  63. data/lib/mongoid/errors.rb +4 -1
  64. data/lib/mongoid/extensions/object.rb +2 -2
  65. data/lib/mongoid/extensions/time.rb +2 -0
  66. data/lib/mongoid/factory.rb +21 -8
  67. data/lib/mongoid/fields/localized.rb +10 -0
  68. data/lib/mongoid/fields/standard.rb +10 -0
  69. data/lib/mongoid/fields.rb +69 -13
  70. data/lib/mongoid/findable.rb +27 -3
  71. data/lib/mongoid/interceptable.rb +7 -6
  72. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  73. data/lib/mongoid/matcher/type.rb +1 -1
  74. data/lib/mongoid/matcher.rb +21 -6
  75. data/lib/mongoid/persistable/creatable.rb +1 -0
  76. data/lib/mongoid/persistable/deletable.rb +1 -1
  77. data/lib/mongoid/persistable/savable.rb +13 -1
  78. data/lib/mongoid/persistable/unsettable.rb +2 -2
  79. data/lib/mongoid/persistable/updatable.rb +51 -1
  80. data/lib/mongoid/persistable/upsertable.rb +20 -1
  81. data/lib/mongoid/persistable.rb +3 -0
  82. data/lib/mongoid/query_cache.rb +5 -1
  83. data/lib/mongoid/railties/database.rake +7 -2
  84. data/lib/mongoid/shardable.rb +35 -11
  85. data/lib/mongoid/stateful.rb +22 -1
  86. data/lib/mongoid/tasks/database.rake +12 -0
  87. data/lib/mongoid/tasks/database.rb +20 -0
  88. data/lib/mongoid/threaded.rb +30 -0
  89. data/lib/mongoid/traversable.rb +1 -1
  90. data/lib/mongoid/utils.rb +22 -0
  91. data/lib/mongoid/validatable/macros.rb +5 -5
  92. data/lib/mongoid/validatable.rb +4 -1
  93. data/lib/mongoid/version.rb +1 -1
  94. data/lib/mongoid/warnings.rb +17 -1
  95. data/lib/mongoid.rb +16 -3
  96. data/spec/integration/app_spec.rb +2 -2
  97. data/spec/integration/callbacks_models.rb +37 -0
  98. data/spec/integration/callbacks_spec.rb +134 -0
  99. data/spec/integration/discriminator_key_spec.rb +4 -5
  100. data/spec/integration/i18n_fallbacks_spec.rb +3 -2
  101. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
  102. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +57 -57
  103. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  104. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  105. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
  106. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +148 -224
  107. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +111 -164
  108. data/spec/mongoid/association/syncable_spec.rb +1 -1
  109. data/spec/mongoid/attributes_spec.rb +5 -8
  110. data/spec/mongoid/changeable_spec.rb +299 -24
  111. data/spec/mongoid/clients_spec.rb +122 -13
  112. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  113. data/spec/mongoid/config/defaults_spec.rb +160 -0
  114. data/spec/mongoid/config_spec.rb +154 -18
  115. data/spec/mongoid/contextual/memory_spec.rb +332 -76
  116. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  117. data/spec/mongoid/contextual/mongo_spec.rb +995 -36
  118. data/spec/mongoid/contextual/none_spec.rb +49 -2
  119. data/spec/mongoid/copyable_spec.rb +3 -11
  120. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
  121. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  122. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -0
  123. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  124. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
  125. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
  126. data/spec/mongoid/criteria/queryable/selector_spec.rb +1 -1
  127. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  128. data/spec/mongoid/criteria_projection_spec.rb +1 -4
  129. data/spec/mongoid/criteria_spec.rb +5 -9
  130. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  131. data/spec/mongoid/extensions/time_spec.rb +8 -43
  132. data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
  133. data/spec/mongoid/fields/localized_spec.rb +46 -28
  134. data/spec/mongoid/fields_spec.rb +136 -34
  135. data/spec/mongoid/findable_spec.rb +391 -34
  136. data/spec/mongoid/indexable_spec.rb +16 -10
  137. data/spec/mongoid/interceptable_spec.rb +15 -3
  138. data/spec/mongoid/persistable/deletable_spec.rb +26 -6
  139. data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
  140. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  141. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  142. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  143. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  144. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  145. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  146. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  147. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  148. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  149. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  150. data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
  151. data/spec/mongoid/persistence_context_spec.rb +7 -57
  152. data/spec/mongoid/query_cache_spec.rb +56 -61
  153. data/spec/mongoid/reloadable_spec.rb +24 -4
  154. data/spec/mongoid/scopable_spec.rb +70 -0
  155. data/spec/mongoid/serializable_spec.rb +9 -30
  156. data/spec/mongoid/shardable_models.rb +14 -0
  157. data/spec/mongoid/shardable_spec.rb +153 -61
  158. data/spec/mongoid/stateful_spec.rb +122 -8
  159. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  160. data/spec/mongoid/tasks/database_spec.rb +127 -0
  161. data/spec/mongoid/timestamps_spec.rb +9 -11
  162. data/spec/mongoid/touchable_spec.rb +277 -5
  163. data/spec/mongoid/touchable_spec_models.rb +3 -1
  164. data/spec/mongoid/traversable_spec.rb +9 -24
  165. data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
  166. data/spec/mongoid_spec.rb +35 -9
  167. data/spec/shared/lib/mrss/docker_runner.rb +7 -0
  168. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  169. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  170. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  171. data/spec/shared/lib/mrss/utils.rb +28 -6
  172. data/spec/shared/share/Dockerfile.erb +36 -40
  173. data/spec/shared/shlib/server.sh +32 -8
  174. data/spec/shared/shlib/set_env.sh +4 -4
  175. data/spec/spec_helper.rb +5 -0
  176. data/spec/support/immutable_ids.rb +118 -0
  177. data/spec/support/macros.rb +47 -15
  178. data/spec/support/models/artist.rb +0 -1
  179. data/spec/support/models/band.rb +1 -0
  180. data/spec/support/models/book.rb +1 -0
  181. data/spec/support/models/building.rb +2 -0
  182. data/spec/support/models/cover.rb +10 -0
  183. data/spec/support/models/product.rb +1 -0
  184. data.tar.gz.sig +0 -0
  185. metadata +700 -656
  186. metadata.gz.sig +0 -0
  187. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  188. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
@@ -476,6 +476,188 @@ describe Mongoid::Changeable do
476
476
  end
477
477
  end
478
478
  end
479
+
480
+ context "when including key word args" do
481
+
482
+ let(:person) { Person.new }
483
+
484
+ context "when only including from" do
485
+
486
+ context "when the object has not changed" do
487
+
488
+ it "returns false" do
489
+ expect(person.send(:attribute_changed?, :score, from: nil)).to be false
490
+ end
491
+
492
+ it "returns false using (attribute)_changed?" do
493
+ expect(person.score_changed?(from: nil)).to be false
494
+ end
495
+ end
496
+
497
+ context "when the object has changed from the wrong item" do
498
+
499
+ before do
500
+ person.score = 2
501
+ end
502
+
503
+ it "returns false" do
504
+ expect(person.send(:attribute_changed?, :score, from: 1)).to be false
505
+ end
506
+
507
+ it "returns false using (attribute)_changed?" do
508
+ expect(person.score_changed?(from: 1)).to be false
509
+ end
510
+ end
511
+
512
+ context "when the object has changed from the correct item" do
513
+
514
+ before do
515
+ person.score = 2
516
+ end
517
+
518
+ it "returns true" do
519
+ expect(person.send(:attribute_changed?, :score, from: nil)).to be true
520
+ end
521
+
522
+ it "returns true using (attribute)_changed?" do
523
+ expect(person.score_changed?(from: nil)).to be true
524
+ end
525
+ end
526
+ end
527
+
528
+ context "when only including to" do
529
+
530
+ context "when the object has not changed" do
531
+
532
+ it "returns false" do
533
+ expect(person.send(:attribute_changed?, :score, to: nil)).to be false
534
+ end
535
+
536
+ it "returns false using (attribute)_changed?" do
537
+ expect(person.score_changed?(to: nil)).to be false
538
+ end
539
+ end
540
+
541
+ context "when the object has changed to the wrong item" do
542
+
543
+ before do
544
+ person.score = 2
545
+ end
546
+
547
+ it "returns false" do
548
+ expect(person.send(:attribute_changed?, :score, to: 1)).to be false
549
+ end
550
+
551
+ it "returns false using (attribute)_changed?" do
552
+ expect(person.score_changed?(to: 1)).to be false
553
+ end
554
+ end
555
+
556
+ context "when the object has changed to the correct item" do
557
+
558
+ before do
559
+ person.score = 2
560
+ end
561
+
562
+ it "returns true" do
563
+ expect(person.send(:attribute_changed?, :score, to: 2)).to be true
564
+ end
565
+
566
+ it "returns true using (attribute)_changed?" do
567
+ expect(person.score_changed?(to: 2)).to be true
568
+ end
569
+ end
570
+ end
571
+
572
+ context "when including from and to" do
573
+
574
+ context "when the object has not changed" do
575
+
576
+ it "returns false" do
577
+ expect(person.send(:attribute_changed?, :score, from: nil, to: nil)).to be false
578
+ end
579
+
580
+ it "returns false using (attribute)_changed?" do
581
+ expect(person.score_changed?(from: nil, to: nil)).to be false
582
+ end
583
+ end
584
+
585
+ context "when only the from is correct" do
586
+
587
+ before do
588
+ person.score = 2
589
+ end
590
+
591
+ it "returns false" do
592
+ expect(person.send(:attribute_changed?, :score, from: nil, to: 3)).to be false
593
+ end
594
+
595
+ it "returns false using (attribute)_changed?" do
596
+ expect(person.score_changed?(from: nil, to: 3)).to be false
597
+ end
598
+ end
599
+
600
+ context "when only the to is correct" do
601
+
602
+ before do
603
+ person.score = 2
604
+ end
605
+
606
+ it "returns false" do
607
+ expect(person.send(:attribute_changed?, :score, from: 1, to: 2)).to be false
608
+ end
609
+
610
+ it "returns false using (attribute)_changed?" do
611
+ expect(person.score_changed?(from: 1, to: 2)).to be false
612
+ end
613
+ end
614
+
615
+ context "when the from and to are correct" do
616
+
617
+ before do
618
+ person.score = 2
619
+ end
620
+
621
+ it "returns true" do
622
+ expect(person.send(:attribute_changed?, :score, from: nil, to: 2)).to be true
623
+ end
624
+
625
+ it "returns true using (attribute)_changed?" do
626
+ expect(person.score_changed?(from: nil, to: 2)).to be true
627
+ end
628
+ end
629
+
630
+ context "when value is mongoized" do
631
+
632
+ before do
633
+ person.score = "2"
634
+ end
635
+
636
+ it "returns true with mongoized value" do
637
+ expect(person.send(:attribute_changed?, :score, from: nil, to: 2)).to be true
638
+ end
639
+
640
+ it "returns true with mongoized value using (attribute)_changed?" do
641
+ expect(person.score_changed?(from: nil, to: 2)).to be true
642
+ end
643
+ end
644
+
645
+ context "when value is mongoized" do
646
+
647
+ before do
648
+ person.score = "2"
649
+ end
650
+
651
+ it "returns false with unmongoized value" do
652
+ expect(person.send(:attribute_changed?, :score, from: nil, to: "2")).to be false
653
+ end
654
+
655
+ it "returns false with unmongoized value using (attribute)_changed?" do
656
+ expect(person.score_changed?(from: nil, to: "2")).to be false
657
+ end
658
+ end
659
+ end
660
+ end
479
661
  end
480
662
 
481
663
  describe "#attribute_changed_from_default?" do
@@ -1167,20 +1349,10 @@ describe Mongoid::Changeable do
1167
1349
 
1168
1350
  context "when the document is embedded" do
1169
1351
 
1170
- let(:person) do
1171
- Person.instantiate(title: "Grand Poobah")
1172
- end
1352
+ let(:person) { Person.create(title: "Grand Poobah") }
1353
+ let(:address) { person.addresses.create(street: "Oxford St") }
1173
1354
 
1174
- let(:address) do
1175
- Address.instantiate(street: "Oxford St")
1176
- end
1177
-
1178
- before do
1179
- person.addresses << address
1180
- person.instance_variable_set(:@new_record, false)
1181
- address.instance_variable_set(:@new_record, false)
1182
- address.street = "Bond St"
1183
- end
1355
+ before { address.street = "Bond St" }
1184
1356
 
1185
1357
  it "returns a hash of field names and new values" do
1186
1358
  expect(address.setters).to eq(
@@ -1189,17 +1361,9 @@ describe Mongoid::Changeable do
1189
1361
  end
1190
1362
 
1191
1363
  context "when the document is embedded multiple levels" do
1192
-
1193
- let(:location) do
1194
- Location.new(name: "Home")
1195
- end
1196
-
1197
- before do
1198
- location.instance_variable_set(:@new_record, false)
1199
- address.locations << location
1200
- location.name = "Work"
1201
- end
1202
-
1364
+ let(:location) { address.locations.create(name: "Home") }
1365
+ before { location.name = "Work" }
1366
+
1203
1367
  it "returns the proper hash with locations" do
1204
1368
  expect(location.setters).to eq(
1205
1369
  { "addresses.0.locations.0.name" => "Work" }
@@ -1479,6 +1643,117 @@ describe Mongoid::Changeable do
1479
1643
  end
1480
1644
  end
1481
1645
 
1646
+ describe '#attribute_before_last_save' do
1647
+ let(:person) do
1648
+ Person.create!(title: "Grand Poobah")
1649
+ end
1650
+
1651
+ before do
1652
+ person.title = "Captain Obvious"
1653
+ end
1654
+
1655
+ context "when the document has been saved" do
1656
+ before do
1657
+ person.save!
1658
+ end
1659
+
1660
+ it "returns the changes" do
1661
+ expect(person.attribute_before_last_save(:title)).to eq("Grand Poobah")
1662
+ expect(person.title_before_last_save).to eq("Grand Poobah")
1663
+ end
1664
+ end
1665
+
1666
+ context "when the document has not been saved" do
1667
+ it "returns no changes" do
1668
+ expect(person.attribute_before_last_save(:title)).to be_nil
1669
+ expect(person.title_before_last_save).to be_nil
1670
+ end
1671
+ end
1672
+ end
1673
+
1674
+ describe '#saved_change_to_attribute' do
1675
+ let(:person) do
1676
+ Person.create!(title: "Grand Poobah")
1677
+ end
1678
+
1679
+ before do
1680
+ person.title = "Captain Obvious"
1681
+ end
1682
+
1683
+ context "when the document has been saved" do
1684
+ before do
1685
+ person.save!
1686
+ end
1687
+
1688
+ it "returns the changes" do
1689
+ expect(person.saved_change_to_attribute(:title)).to eq(["Grand Poobah", "Captain Obvious"])
1690
+ expect(person.saved_change_to_title).to eq(["Grand Poobah", "Captain Obvious"])
1691
+ end
1692
+ end
1693
+
1694
+ context "when the document has not been saved" do
1695
+ it "returns changes for the previous save" do
1696
+ expect(person.saved_change_to_attribute(:title)).to eq([nil, "Grand Poobah"])
1697
+ expect(person.saved_change_to_title).to eq([nil, "Grand Poobah"])
1698
+ end
1699
+ end
1700
+ end
1701
+
1702
+ describe '#saved_change_to_attribute?' do
1703
+ context "when the document has been saved" do
1704
+ let(:person) do
1705
+ Person.create!(title: "Grand Poobah")
1706
+ end
1707
+
1708
+ before do
1709
+ person.title = "Captain Obvious"
1710
+ end
1711
+
1712
+ before do
1713
+ person.save!
1714
+ end
1715
+
1716
+ it "detects the changes" do
1717
+ expect(person.saved_change_to_attribute?(:title)).to be_truthy
1718
+ expect(person.saved_change_to_attribute?(:title, from: "Grand Poobah")).to be_truthy
1719
+ expect(person.saved_change_to_attribute?(:title, to: "Captain Obvious")).to be_truthy
1720
+ expect(person.saved_change_to_attribute?(:title, from: "Grand Poobah", to: "Captain Obvious")).to be_truthy
1721
+ expect(person.saved_change_to_title?(from: "Grand Poobah", to: "Captain Obvious")).to be_truthy
1722
+ expect(person.saved_change_to_attribute?(:age)).to be_falsey
1723
+ expect(person.saved_change_to_age?).to be_falsey
1724
+ end
1725
+ end
1726
+
1727
+ context "when the document has not been saved" do
1728
+ let(:person) do
1729
+ Person.new(title: "Grand Poobah")
1730
+ end
1731
+
1732
+ it "returns changes for the previous save" do
1733
+ expect(person.saved_change_to_attribute?(:title)).to be_falsey
1734
+ expect(person.saved_change_to_title?).to be_falsey
1735
+ end
1736
+ end
1737
+ end
1738
+
1739
+ describe '#will_save_change_to_attribute?' do
1740
+ let(:person) do
1741
+ Person.create!(title: "Grand Poobah")
1742
+ end
1743
+
1744
+ before do
1745
+ person.title = "Captain Obvious"
1746
+ end
1747
+
1748
+ it 'correctly detects changes' do
1749
+ expect(person.will_save_change_to_attribute?(:title)).to eq(true)
1750
+ expect(person.will_save_change_to_title?).to eq(true)
1751
+ expect(person.will_save_change_to_attribute?(:score)).to eq(false)
1752
+ expect(person.will_save_change_to_score?).to eq(false)
1753
+ end
1754
+
1755
+ end
1756
+
1482
1757
  context "when fields have been defined pre-dirty inclusion" do
1483
1758
 
1484
1759
  let(:document) do
@@ -738,19 +738,6 @@ describe Mongoid::Clients do
738
738
  end
739
739
  end
740
740
 
741
- context "when provided a class that extends another document" do
742
-
743
- let(:klass) do
744
- Class.new(Band)
745
- end
746
-
747
- it "raises an error" do
748
- expect {
749
- klass.store_in(database: :artists)
750
- }.to raise_error(Mongoid::Errors::InvalidStorageParent)
751
- end
752
- end
753
-
754
741
  context "when provided a hash" do
755
742
 
756
743
  context "when the hash is not valid" do
@@ -762,6 +749,128 @@ describe Mongoid::Clients do
762
749
  end
763
750
  end
764
751
  end
752
+
753
+ context "when it is called on a subclass" do
754
+
755
+ let(:client) { StoreParent.collection.client }
756
+ let(:parent) { StoreParent.create! }
757
+ let(:child1) { StoreChild1.create! }
758
+ let(:child2) { StoreChild2.create! }
759
+
760
+ before do
761
+ class StoreParent
762
+ include Mongoid::Document
763
+ end
764
+
765
+ class StoreChild1 < StoreParent
766
+ end
767
+
768
+ class StoreChild2 < StoreParent
769
+ end
770
+ end
771
+
772
+ after do
773
+ Object.send(:remove_const, :StoreParent)
774
+ Object.send(:remove_const, :StoreChild1)
775
+ Object.send(:remove_const, :StoreChild2)
776
+ end
777
+
778
+ context "when it is not called on the parent" do
779
+
780
+ context "when it is called on all subclasses" do
781
+
782
+ before do
783
+ StoreChild1.store_in collection: :store_ones
784
+ StoreChild2.store_in collection: :store_twos
785
+ [ parent, child1, child2 ]
786
+ end
787
+
788
+ let(:db_parent) { client['store_parents'].find.first }
789
+ let(:db_child1) { client['store_ones'].find.first }
790
+ let(:db_child2) { client['store_twos'].find.first }
791
+
792
+ it "stores the documents in the correct collections" do
793
+ expect(db_parent).to eq({ "_id" => parent.id, "_type" => "StoreParent" })
794
+ expect(db_child1).to eq({ "_id" => child1.id, "_type" => "StoreChild1" })
795
+ expect(db_child2).to eq({ "_id" => child2.id, "_type" => "StoreChild2" })
796
+ end
797
+
798
+ it "only queries from its own collections" do
799
+ expect(StoreParent.count).to eq(1)
800
+ expect(StoreChild1.count).to eq(1)
801
+ expect(StoreChild2.count).to eq(1)
802
+ end
803
+ end
804
+
805
+ context "when it is called on one of the subclasses" do
806
+
807
+ before do
808
+ StoreChild1.store_in collection: :store_ones
809
+ [ parent, child1, child2 ]
810
+ end
811
+
812
+ let(:db_parent) { client['store_parents'].find.first }
813
+ let(:db_child1) { client['store_ones'].find.first }
814
+ let(:db_child2) { client['store_parents'].find.to_a.last }
815
+
816
+ it "stores the documents in the correct collections" do
817
+ expect(db_parent).to eq({ "_id" => parent.id, "_type" => "StoreParent" })
818
+ expect(db_child1).to eq({ "_id" => child1.id, "_type" => "StoreChild1" })
819
+ expect(db_child2).to eq({ "_id" => child2.id, "_type" => "StoreChild2" })
820
+ end
821
+
822
+ it "queries from its own collections" do
823
+ expect(StoreParent.count).to eq(2)
824
+ expect(StoreChild1.count).to eq(1)
825
+ expect(StoreChild2.count).to eq(1)
826
+ end
827
+ end
828
+ end
829
+
830
+ context "when it is called on the parent" do
831
+
832
+ before do
833
+ StoreParent.store_in collection: :st_parents
834
+ end
835
+
836
+ context "when it is called on all subclasses" do
837
+
838
+ before do
839
+ StoreChild1.store_in collection: :store_ones
840
+ StoreChild2.store_in collection: :store_twos
841
+ [ parent, child1, child2 ]
842
+ end
843
+
844
+ let(:db_parent) { client['st_parents'].find.first }
845
+ let(:db_child1) { client['store_ones'].find.first }
846
+ let(:db_child2) { client['store_twos'].find.first }
847
+
848
+ it "stores the documents in the correct collections" do
849
+ expect(db_parent).to eq({ "_id" => parent.id, "_type" => "StoreParent" })
850
+ expect(db_child1).to eq({ "_id" => child1.id, "_type" => "StoreChild1" })
851
+ expect(db_child2).to eq({ "_id" => child2.id, "_type" => "StoreChild2" })
852
+ end
853
+ end
854
+
855
+ context "when it is called on one of the subclasses" do
856
+
857
+ before do
858
+ StoreChild1.store_in collection: :store_ones
859
+ [ parent, child1, child2 ]
860
+ end
861
+
862
+ let(:db_parent) { client['st_parents'].find.first }
863
+ let(:db_child1) { client['store_ones'].find.first }
864
+ let(:db_child2) { client['st_parents'].find.to_a.last }
865
+
866
+ it "stores the documents in the correct collections" do
867
+ expect(db_parent).to eq({ "_id" => parent.id, "_type" => "StoreParent" })
868
+ expect(db_child1).to eq({ "_id" => child1.id, "_type" => "StoreChild1" })
869
+ expect(db_child2).to eq({ "_id" => child2.id, "_type" => "StoreChild2" })
870
+ end
871
+ end
872
+ end
873
+ end
765
874
  end
766
875
 
767
876
  describe ".with" do
@@ -0,0 +1,158 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Mongoid::CollectionConfigurable do
6
+
7
+ before(:all) do
8
+ class CollectionConfigurableValidOptions
9
+ include Mongoid::Document
10
+
11
+ store_in collection_options: {
12
+ capped: true,
13
+ size: 2560
14
+ }
15
+ end
16
+
17
+ class CollectionConfigurableUnknownOptions
18
+ include Mongoid::Document
19
+
20
+ store_in collection_options: {
21
+ i_am_not_an_option: true,
22
+ let_me: { fail: true }
23
+ }
24
+ end
25
+
26
+ class CollectionConfigurableInvalidOptions
27
+ include Mongoid::Document
28
+
29
+ store_in collection_options: {
30
+ capped: true
31
+ # Creating a capped collection requires `size` field; therefore,
32
+ # an attempt to create a collection with only `capped : true` option
33
+ # fails.
34
+ }
35
+ end
36
+ end
37
+
38
+ after(:all) do
39
+ Mongoid.deregister_model(CollectionConfigurableValidOptions)
40
+ Object.send(:remove_const, :CollectionConfigurableValidOptions)
41
+ Mongoid.deregister_model(CollectionConfigurableUnknownOptions)
42
+ Object.send(:remove_const, :CollectionConfigurableUnknownOptions)
43
+ Mongoid.deregister_model(CollectionConfigurableInvalidOptions)
44
+ Object.send(:remove_const, :CollectionConfigurableInvalidOptions)
45
+ end
46
+
47
+ after(:each) do
48
+ [
49
+ CollectionConfigurableValidOptions,
50
+ CollectionConfigurableUnknownOptions
51
+ ].each do |klazz|
52
+ klazz.collection.drop
53
+ end
54
+ end
55
+
56
+ context 'when collection does not exist' do
57
+ context 'with valid options' do
58
+ let(:subject) do
59
+ CollectionConfigurableValidOptions
60
+ end
61
+
62
+ before(:each) do
63
+ subject.create_collection
64
+ end
65
+
66
+ let(:coll_options) do
67
+ subject.collection.database.list_collections(filter: { name: subject.collection_name.to_s }).first
68
+ end
69
+
70
+ it 'creates the collection' do
71
+ expect(coll_options).not_to be_nil
72
+ end
73
+
74
+ it 'passes collection options' do
75
+ expect(coll_options.dig('options', 'capped')).to eq(true)
76
+ expect(coll_options.dig('options', 'size')).to eq(2560)
77
+ end
78
+ end
79
+
80
+ context 'with an unknown collection options' do
81
+ let(:subject) do
82
+ CollectionConfigurableUnknownOptions
83
+ end
84
+
85
+ it 'raises an error' do
86
+ expect do
87
+ subject.create_collection
88
+ end.to raise_error(Mongoid::Errors::CreateCollectionFailure)
89
+ end
90
+ end
91
+
92
+ context 'with invalid options' do
93
+ let(:subject) do
94
+ CollectionConfigurableInvalidOptions
95
+ end
96
+
97
+ it 'raises an error' do
98
+ expect do
99
+ subject.create_collection
100
+ end.to raise_error(Mongoid::Errors::CreateCollectionFailure)
101
+ end
102
+ end
103
+ end
104
+
105
+ context 'when collection exists' do
106
+ let(:subject) do
107
+ CollectionConfigurableValidOptions
108
+ end
109
+
110
+ context 'when force is false' do
111
+ let(:logger) do
112
+ double("logger").tap do |log|
113
+ expect(log).to receive(:debug).once.with(/Collection '#{subject.collection_name}' already exist/)
114
+ end
115
+ end
116
+
117
+ before do
118
+ allow(subject).to receive(:logger).and_return(logger)
119
+ subject.collection.create
120
+ end
121
+
122
+ it 'logs a message' do
123
+ subject.create_collection
124
+ end
125
+ end
126
+
127
+ context 'when force is true' do
128
+ let(:logger) do
129
+ double("logger")
130
+ end
131
+
132
+ let(:coll_options) do
133
+ subject.collection.database.list_collections(filter: { name: subject.collection_name.to_s }).first
134
+ end
135
+
136
+ before do
137
+ allow(subject).to receive(:logger).and_return(logger)
138
+ subject.collection.create
139
+ end
140
+
141
+ it 'does not log a message' do
142
+ expect(logger).to receive(:debug).never.with(/Collection '#{subject.collection_name}' already exist/)
143
+ subject.create_collection(force: true)
144
+ end
145
+
146
+ it 'creates the collection' do
147
+ subject.create_collection(force: true)
148
+ expect(coll_options).not_to be_nil
149
+ end
150
+
151
+ it 'passes collection options' do
152
+ subject.create_collection(force: true)
153
+ expect(coll_options.dig('options', 'capped')).to eq(true)
154
+ expect(coll_options.dig('options', 'size')).to eq(2560)
155
+ end
156
+ end
157
+ end
158
+ end