mongoid 7.2.0.rc1 → 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 (214) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +45 -10
  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/buildable.rb +8 -0
  19. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  20. data/lib/mongoid/association/referenced/has_one/proxy.rb +6 -1
  21. data/lib/mongoid/attributes.rb +32 -14
  22. data/lib/mongoid/attributes/projector.rb +120 -0
  23. data/lib/mongoid/cacheable.rb +2 -2
  24. data/lib/mongoid/clients.rb +1 -1
  25. data/lib/mongoid/clients/factory.rb +22 -8
  26. data/lib/mongoid/config.rb +19 -2
  27. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  28. data/lib/mongoid/copyable.rb +6 -2
  29. data/lib/mongoid/criteria.rb +4 -5
  30. data/lib/mongoid/criteria/findable.rb +1 -1
  31. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  32. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  33. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  34. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  35. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  36. data/lib/mongoid/criteria/queryable/selector.rb +0 -4
  37. data/lib/mongoid/document.rb +4 -17
  38. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  39. data/lib/mongoid/evolvable.rb +1 -1
  40. data/lib/mongoid/extensions.rb +1 -0
  41. data/lib/mongoid/extensions/boolean.rb +1 -2
  42. data/lib/mongoid/extensions/false_class.rb +1 -1
  43. data/lib/mongoid/extensions/hash.rb +2 -2
  44. data/lib/mongoid/extensions/true_class.rb +1 -1
  45. data/lib/mongoid/fields.rb +46 -5
  46. data/lib/mongoid/inspectable.rb +1 -1
  47. data/lib/mongoid/interceptable.rb +3 -1
  48. data/lib/mongoid/matcher.rb +26 -43
  49. data/lib/mongoid/matcher/bits.rb +41 -0
  50. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  51. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  52. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  53. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  54. data/lib/mongoid/matcher/elem_match.rb +2 -1
  55. data/lib/mongoid/matcher/expression.rb +9 -14
  56. data/lib/mongoid/matcher/field_expression.rb +4 -5
  57. data/lib/mongoid/matcher/field_operator.rb +13 -11
  58. data/lib/mongoid/matcher/mod.rb +17 -0
  59. data/lib/mongoid/matcher/type.rb +99 -0
  60. data/lib/mongoid/persistable/deletable.rb +1 -2
  61. data/lib/mongoid/persistable/destroyable.rb +8 -2
  62. data/lib/mongoid/persistable/updatable.rb +27 -2
  63. data/lib/mongoid/query_cache.rb +35 -29
  64. data/lib/mongoid/reloadable.rb +5 -0
  65. data/lib/mongoid/selectable.rb +5 -7
  66. data/lib/mongoid/shardable.rb +21 -5
  67. data/lib/mongoid/stringified_symbol.rb +53 -0
  68. data/lib/mongoid/touchable.rb +23 -4
  69. data/lib/mongoid/version.rb +1 -1
  70. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  71. data/spec/README.md +19 -4
  72. data/spec/integration/app_spec.rb +175 -88
  73. data/spec/integration/associations/embeds_many_spec.rb +68 -0
  74. data/spec/integration/associations/embeds_one_spec.rb +24 -0
  75. data/spec/integration/associations/has_many_spec.rb +60 -0
  76. data/spec/integration/associations/has_one_spec.rb +108 -0
  77. data/spec/integration/callbacks_models.rb +49 -0
  78. data/spec/integration/callbacks_spec.rb +216 -0
  79. data/spec/integration/criteria/date_field_spec.rb +1 -1
  80. data/spec/integration/document_spec.rb +30 -0
  81. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  82. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  83. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  84. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  85. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  86. data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
  87. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  88. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  89. data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
  90. data/spec/integration/matcher_operator_data/in.yml +16 -0
  91. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  92. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  93. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  94. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  95. data/spec/integration/matcher_operator_data/type.yml +70 -0
  96. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  97. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  98. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  99. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  100. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  101. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  102. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  103. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  104. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  105. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  106. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  107. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  108. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  109. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  110. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  111. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  112. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  113. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  114. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  115. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  116. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  117. data/spec/integration/stringified_symbol_field_spec.rb +190 -0
  118. data/spec/lite_spec_helper.rb +9 -7
  119. data/spec/mongoid/association/depending_spec.rb +391 -352
  120. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  121. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  122. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  123. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  124. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  125. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
  126. data/spec/mongoid/association/referenced/has_many_models.rb +12 -0
  127. data/spec/mongoid/association/referenced/has_one_models.rb +20 -0
  128. data/spec/mongoid/association/referenced/has_one_spec.rb +1 -1
  129. data/spec/mongoid/atomic/paths_spec.rb +105 -12
  130. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  131. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  132. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  133. data/spec/mongoid/attributes_spec.rb +333 -0
  134. data/spec/mongoid/clients/factory_spec.rb +48 -0
  135. data/spec/mongoid/config_spec.rb +32 -0
  136. data/spec/mongoid/contextual/atomic_spec.rb +17 -4
  137. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  138. data/spec/mongoid/copyable_spec.rb +44 -17
  139. data/spec/mongoid/copyable_spec_models.rb +14 -0
  140. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  141. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  142. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  143. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  144. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +265 -24
  145. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  146. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  147. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  148. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  149. data/spec/mongoid/criteria_spec.rb +0 -275
  150. data/spec/mongoid/document_fields_spec.rb +26 -0
  151. data/spec/mongoid/document_spec.rb +13 -13
  152. data/spec/mongoid/equality_spec.rb +0 -1
  153. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  154. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  155. data/spec/mongoid/extensions/string_spec.rb +5 -5
  156. data/spec/mongoid/extensions/stringified_symbol_spec.rb +85 -0
  157. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  158. data/spec/mongoid/fields/localized_spec.rb +4 -4
  159. data/spec/mongoid/fields_spec.rb +4 -4
  160. data/spec/mongoid/inspectable_spec.rb +12 -4
  161. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  162. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
  163. data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
  164. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  165. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  166. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  167. data/spec/mongoid/persistable/settable_spec.rb +30 -0
  168. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  169. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  170. data/spec/mongoid/reloadable_spec.rb +18 -1
  171. data/spec/mongoid/shardable_spec.rb +44 -0
  172. data/spec/mongoid/touchable_spec.rb +104 -16
  173. data/spec/mongoid/touchable_spec_models.rb +52 -0
  174. data/spec/mongoid/validatable_spec.rb +1 -1
  175. data/spec/shared/LICENSE +20 -0
  176. data/spec/shared/bin/get-mongodb-download-url +17 -0
  177. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  178. data/spec/shared/lib/mrss/cluster_config.rb +221 -0
  179. data/spec/shared/lib/mrss/constraints.rb +354 -0
  180. data/spec/shared/lib/mrss/docker_runner.rb +265 -0
  181. data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
  182. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  183. data/spec/shared/lib/mrss/spec_organizer.rb +162 -0
  184. data/spec/shared/lib/mrss/utils.rb +15 -0
  185. data/spec/shared/share/Dockerfile.erb +231 -0
  186. data/spec/shared/shlib/distro.sh +73 -0
  187. data/spec/shared/shlib/server.sh +290 -0
  188. data/spec/shared/shlib/set_env.sh +128 -0
  189. data/spec/spec_helper.rb +7 -1
  190. data/spec/support/client_registry.rb +9 -0
  191. data/spec/support/constraints.rb +0 -226
  192. data/spec/support/models/bolt.rb +8 -0
  193. data/spec/support/models/customer.rb +11 -0
  194. data/spec/support/models/customer_address.rb +12 -0
  195. data/spec/support/models/dictionary.rb +6 -0
  196. data/spec/support/models/hole.rb +13 -0
  197. data/spec/support/models/mop.rb +9 -0
  198. data/spec/support/models/nut.rb +8 -0
  199. data/spec/support/models/order.rb +11 -0
  200. data/spec/support/models/person.rb +8 -0
  201. data/spec/support/models/sealer.rb +8 -0
  202. data/spec/support/models/series.rb +1 -0
  203. data/spec/support/models/shirt.rb +12 -0
  204. data/spec/support/models/spacer.rb +8 -0
  205. data/spec/support/models/threadlocker.rb +8 -0
  206. data/spec/support/models/washer.rb +8 -0
  207. data/spec/support/models/wiki_page.rb +1 -0
  208. data/spec/support/spec_config.rb +8 -0
  209. metadata +655 -507
  210. metadata.gz.sig +0 -0
  211. data/spec/support/child_process_helper.rb +0 -79
  212. data/spec/support/cluster_config.rb +0 -158
  213. data/spec/support/lite_constraints.rb +0 -22
  214. data/spec/support/spec_organizer.rb +0 -130
@@ -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
@@ -137,20 +137,24 @@ describe Mongoid::Association::Nested::One do
137
137
  { allow_destroy: true }
138
138
  end
139
139
 
140
- let(:builder) do
141
- described_class.new(association, {
142
- id: name.id,
143
- last_name: "Lang",
144
- _destroy: true
145
- }, options)
146
- end
147
-
148
- before do
149
- builder.build(person)
150
- end
151
-
152
- it "deletes the relation" do
153
- expect(person.name).to be_nil
140
+ %i(id _id).each do |id_field|
141
+ context "#{id_field}" do
142
+ let(:builder) do
143
+ described_class.new(association, {
144
+ id_field => name.id,
145
+ last_name: "Lang",
146
+ _destroy: true
147
+ }, options)
148
+ end
149
+
150
+ before do
151
+ builder.build(person)
152
+ end
153
+
154
+ it "deletes the relation" do
155
+ expect(person.name).to be_nil
156
+ end
157
+ end
154
158
  end
155
159
  end
156
160
  end
@@ -127,6 +127,23 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
127
127
  it "does not save the target" do
128
128
  expect(person).to_not be_persisted
129
129
  end
130
+
131
+ it "drops private visibility from private methods" do
132
+ # This is unfortunate but it appears that Ruby does not
133
+ # have a way to distinguish how method_missing was invoked
134
+ # (i.e. via an explicit send or method call).
135
+ # See https://jira.mongodb.org/browse/MONGOID-5009
136
+ game.person.secret_name.should == 'secret'
137
+ end
138
+
139
+ it "allows private methods to be invoked" do
140
+ game.person.send(:secret_name).should == 'secret'
141
+ end
142
+
143
+ it "properly exposes delegated methods visibility" do
144
+ expect(defined?(game.person.id)).to eq("method")
145
+ expect(defined?(game.person.secret_name)).to be_nil
146
+ end
130
147
  end
131
148
 
132
149
  context "when the child is not a new record" do
@@ -508,7 +525,7 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
508
525
  context "when child is destroyed" do
509
526
 
510
527
  before do
511
- account.delete
528
+ account.destroy
512
529
  end
513
530
 
514
531
  it "deletes child" do
@@ -548,7 +565,7 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
548
565
  context "when child is destroyed" do
549
566
 
550
567
  before do
551
- drug.delete
568
+ drug.destroy
552
569
  end
553
570
 
554
571
  it "deletes child" do
@@ -600,10 +617,10 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
600
617
 
601
618
  context "when parent is persisted" do
602
619
 
603
- context "when child is deleted" do
620
+ context "when child is destroyed" do
604
621
 
605
622
  before do
606
- account.delete
623
+ account.destroy
607
624
  end
608
625
 
609
626
  it "deletes child" do
@@ -643,7 +660,7 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
643
660
  context "when child is destroyed" do
644
661
 
645
662
  before do
646
- drug.delete
663
+ drug.destroy
647
664
  end
648
665
 
649
666
  it "deletes child" do
@@ -690,10 +707,10 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
690
707
 
691
708
  context "when parent is persisted" do
692
709
 
693
- context "when child is deleted" do
710
+ context "when child is destroyed" do
694
711
 
695
712
  before do
696
- account.delete
713
+ account.destroy
697
714
  end
698
715
 
699
716
  it "deletes child" do
@@ -732,7 +749,7 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
732
749
  context "when child is destroyed" do
733
750
 
734
751
  before do
735
- drug.delete
752
+ drug.destroy
736
753
  end
737
754
 
738
755
  it "deletes child" do
@@ -14,7 +14,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Binding do
14
14
  end
15
15
 
16
16
  let(:target) do
17
- Mongoid::Association::Referenced::HasMany::Targets::Enumerable.new([ preference ])
17
+ Mongoid::Association::Referenced::HasMany::Enumerable.new([ preference ])
18
18
  end
19
19
 
20
20
  let(:association) do
@@ -14,7 +14,7 @@ describe Mongoid::Association::Referenced::HasMany::Binding do
14
14
  end
15
15
 
16
16
  let(:target) do
17
- Mongoid::Association::Referenced::HasMany::Targets::Enumerable.new([ post ])
17
+ Mongoid::Association::Referenced::HasMany::Enumerable.new([ post ])
18
18
  end
19
19
 
20
20
  let(:association) do
@@ -3,7 +3,7 @@
3
3
 
4
4
  require "spec_helper"
5
5
 
6
- describe Mongoid::Association::Referenced::HasMany::Targets::Enumerable do
6
+ describe Mongoid::Association::Referenced::HasMany::Enumerable do
7
7
 
8
8
  describe "#==" do
9
9
 
@@ -47,3 +47,15 @@ class HmmTicket
47
47
 
48
48
  belongs_to :person
49
49
  end
50
+
51
+ class HmmBus
52
+ include Mongoid::Document
53
+
54
+ has_many :seats, class_name: 'HmmBusSeat'
55
+ end
56
+
57
+ class HmmBusSeat
58
+ include Mongoid::Document
59
+
60
+ # No belongs_to :bus
61
+ end
@@ -19,6 +19,14 @@ class HomAccreditation
19
19
 
20
20
  field :degree, type: String
21
21
  field :year, type: Integer, default: 2012
22
+
23
+ def format
24
+ 'fmt'
25
+ end
26
+
27
+ def price
28
+ 42
29
+ end
22
30
  end
23
31
 
24
32
  class HomAccreditation::Child
@@ -58,3 +66,15 @@ class HomPolymorphicChild
58
66
 
59
67
  belongs_to :p_parent, polymorphic: true
60
68
  end
69
+
70
+ class HomBus
71
+ include Mongoid::Document
72
+
73
+ has_one :driver, class_name: 'HomBusDriver'
74
+ end
75
+
76
+ class HomBusDriver
77
+ include Mongoid::Document
78
+
79
+ # No belongs_to :bus
80
+ end
@@ -748,7 +748,7 @@ describe Mongoid::Association::Referenced::HasOne do
748
748
  end
749
749
  end
750
750
 
751
- describe '##inverse' do
751
+ describe '#inverse' do
752
752
 
753
753
  context 'when polymorphic' do
754
754
 
@@ -113,10 +113,33 @@ describe Mongoid::Atomic::Paths do
113
113
  person.addresses << address
114
114
  end
115
115
 
116
- it "returns the association with id.atomic_selector" do
117
- expect(address.atomic_selector).to eq(
118
- { "_id" => person.id, "addresses._id" => address.id }
119
- )
116
+ context 'when the parent is persisted' do
117
+
118
+ let(:person) do
119
+ Person.create!
120
+ end
121
+
122
+ before do
123
+ person.should be_persisted
124
+ end
125
+
126
+ it "returns the association with id.atomic_selector" do
127
+ expect(address.atomic_selector).to eq(
128
+ { "_id" => person.id, "addresses._id" => address.id }
129
+ )
130
+ end
131
+ end
132
+
133
+ context 'when the parent is not persisted' do
134
+ before do
135
+ person.should be_new_record
136
+ end
137
+
138
+ it "returns the association with id.atomic_selector" do
139
+ expect(address.atomic_selector).to eq(
140
+ { "_id" => person.id, "addresses._id" => address.id }
141
+ )
142
+ end
120
143
  end
121
144
  end
122
145
 
@@ -127,14 +150,43 @@ describe Mongoid::Atomic::Paths do
127
150
  person.addresses << address
128
151
  end
129
152
 
130
- it "returns the JSON notation to the document with ids" do
131
- expect(location.atomic_selector).to eq(
132
- {
133
- "_id" => person.id,
134
- "addresses._id" => address.id,
135
- "addresses.locations._id" => location.id
136
- }
137
- )
153
+ context 'when the parent is persisted' do
154
+
155
+ let(:person) do
156
+ Person.create!
157
+ end
158
+
159
+ before do
160
+ person.should be_persisted
161
+ end
162
+
163
+ it "returns the JSON notation to the document with ids" do
164
+ expect(location.atomic_selector).to eq(
165
+ {
166
+ "_id" => person.id,
167
+ "addresses._id" => address.id,
168
+ "addresses.0.locations._id" => location.id
169
+ }
170
+ )
171
+ end
172
+ end
173
+
174
+ context 'when the parent is not persisted' do
175
+ before do
176
+ person.should be_new_record
177
+ end
178
+
179
+ it "returns the JSON notation to the document with ids" do
180
+ expect(location.atomic_selector).to eq(
181
+ {
182
+ "_id" => person.id,
183
+ "addresses._id" => address.id,
184
+ # This condition is technically acceptable for finds
185
+ # but probably won't work for modifications of 'locations'.
186
+ "addresses.locations._id" => location.id
187
+ }
188
+ )
189
+ end
138
190
  end
139
191
  end
140
192
  end
@@ -268,5 +320,46 @@ describe Mongoid::Atomic::Paths do
268
320
  end
269
321
  end
270
322
  end
323
+
324
+ context "when the same class is embedded in multiple associations" do
325
+
326
+ let(:customer) do
327
+ Customer.new
328
+ end
329
+
330
+ context "assignment after saving" do
331
+
332
+ it "correctly sets the association for the embedded class" do
333
+ pending 'MONGOID-5039'
334
+
335
+ customer.home_address = CustomerAddress.new
336
+ customer.work_address = CustomerAddress.new
337
+
338
+ expect(customer.home_address.atomic_path).to eq("home_address")
339
+ expect(customer.work_address.atomic_path).to eq("work_address")
340
+
341
+ customer.save!
342
+
343
+ customer.home_address = CustomerAddress.new
344
+ customer.work_address = CustomerAddress.new
345
+
346
+ expect(customer.home_address.atomic_path).to eq("home_address")
347
+ expect(customer.work_address.atomic_path).to eq("work_address")
348
+ end
349
+ end
350
+
351
+ context "inverse assignment" do
352
+
353
+ it "correctly returns the path for each embedded class" do
354
+ pending 'MONGOID-5039'
355
+
356
+ customer.work_address = CustomerAddress.new
357
+ customer.work_address.addressable = customer
358
+
359
+ expect(customer.home_address.atomic_path).to eq("home_address")
360
+ expect(customer.work_address.atomic_path).to eq("work_address")
361
+ end
362
+ end
363
+ end
271
364
  end
272
365
  end
@@ -0,0 +1,105 @@
1
+ - name: embedded field - inclusion
2
+ projection:
3
+ foo.bar: 1
4
+
5
+ queries: &embedded-field-inclusion-expectations
6
+ # Top-level field is allowed as a container
7
+ - query: foo
8
+ allowed: true
9
+
10
+ # Unmentioned field is not allowed
11
+ - query: bar
12
+ allowed: false
13
+
14
+ # A peer to the field isn't allowed
15
+ - query: foo.buck
16
+ allowed: false
17
+
18
+ # A more nested field is allowed
19
+ - query: foo.bar.baz
20
+ allowed: true
21
+
22
+ - name: embedded field - exclusion
23
+ projection:
24
+ foo.bar: 0
25
+
26
+ queries: &embedded-field-exclusion-expectations
27
+ # Top-level field is allowed
28
+ - query: foo
29
+ allowed: true
30
+
31
+ # Unmentioned field is allowed
32
+ - query: bar
33
+ allowed: true
34
+
35
+ # A peer to the excluded field is allowed
36
+ - query: foo.buck
37
+ allowed: true
38
+
39
+ # A more nested field is not allowed
40
+ - query: foo.bar.baz
41
+ allowed: false
42
+
43
+ - name: parent and child fields - inclusion
44
+ projection:
45
+ foo.bar: 1
46
+ foo.bar.baz: 1
47
+
48
+ queries:
49
+ # Top-level field is allowed
50
+ - query: foo
51
+ allowed: true
52
+
53
+ # Second-level field is allowed
54
+ - query: foo.bar
55
+ allowed: true
56
+
57
+ # Third-level field is also allowed
58
+ - query: foo.bar.baz
59
+ allowed: true
60
+
61
+ # Fourth-level field is still allowed
62
+ - query: foo.bar.baz.zzz
63
+ allowed: true
64
+
65
+ # Unmentioned siblings are not allowed
66
+ - query: buck
67
+ allowed: false
68
+ - query: foo.buck
69
+ allowed: false
70
+
71
+ # This sibling is under the second-level include and is allowed
72
+ - query: foo.bar.buck
73
+ allowed: true
74
+
75
+ - name: parent and child fields - exclusion
76
+ projection:
77
+ foo.bar: 0
78
+ foo.bar.baz: 0
79
+
80
+ queries:
81
+ # Top-level field is allowed
82
+ - query: foo
83
+ allowed: true
84
+
85
+ # Second-level field is not allowed
86
+ - query: foo.bar
87
+ allowed: false
88
+
89
+ # Third-level field is also not allowed
90
+ - query: foo.bar.baz
91
+ allowed: false
92
+
93
+ # Fourth-level field is still not allowed
94
+ - query: foo.bar.baz.zzz
95
+ allowed: false
96
+
97
+ # Unmentioned siblings are allowed
98
+ - query: buck
99
+ allowed: true
100
+ - query: foo.buck
101
+ allowed: true
102
+
103
+ # This sibling is under the second-level exclude and is disallowed
104
+ - query: foo.bar.buck
105
+ allowed: false