mongoid 5.4.1 → 6.0.0.beta

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 (264) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/lib/config/locales/en.yml +23 -16
  5. data/lib/mongoid.rb +4 -9
  6. data/lib/mongoid/atomic.rb +1 -1
  7. data/lib/mongoid/atomic/modifiers.rb +8 -12
  8. data/lib/mongoid/attributes.rb +9 -11
  9. data/lib/mongoid/attributes/dynamic.rb +5 -6
  10. data/lib/mongoid/attributes/nested.rb +1 -1
  11. data/lib/mongoid/attributes/processing.rb +4 -0
  12. data/lib/mongoid/attributes/readonly.rb +22 -0
  13. data/lib/mongoid/cacheable.rb +36 -0
  14. data/lib/mongoid/changeable.rb +37 -1
  15. data/lib/mongoid/clients.rb +0 -63
  16. data/lib/mongoid/clients/factory.rb +0 -2
  17. data/lib/mongoid/clients/options.rb +54 -249
  18. data/lib/mongoid/clients/storage_options.rb +1 -69
  19. data/lib/mongoid/composable.rb +26 -2
  20. data/lib/mongoid/config.rb +1 -1
  21. data/lib/mongoid/config/options.rb +1 -1
  22. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -0
  23. data/lib/mongoid/contextual/atomic.rb +6 -9
  24. data/lib/mongoid/contextual/geo_near.rb +2 -3
  25. data/lib/mongoid/contextual/map_reduce.rb +97 -24
  26. data/lib/mongoid/contextual/memory.rb +7 -4
  27. data/lib/mongoid/contextual/mongo.rb +63 -54
  28. data/lib/mongoid/contextual/none.rb +2 -2
  29. data/lib/mongoid/copyable.rb +19 -19
  30. data/lib/mongoid/criteria.rb +5 -4
  31. data/lib/mongoid/criteria/findable.rb +2 -3
  32. data/lib/mongoid/criteria/includable.rb +63 -16
  33. data/lib/mongoid/criteria/marshalable.rb +2 -2
  34. data/lib/mongoid/criteria/modifiable.rb +17 -1
  35. data/lib/mongoid/criteria/options.rb +25 -0
  36. data/lib/mongoid/criteria/queryable.rb +86 -0
  37. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  38. data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
  39. data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
  40. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
  41. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
  42. data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
  43. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
  44. data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
  45. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
  46. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
  47. data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
  48. data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
  49. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +45 -0
  50. data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
  51. data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
  52. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
  53. data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
  54. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
  55. data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
  56. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  57. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  58. data/lib/mongoid/criteria/queryable/mergeable.rb +271 -0
  59. data/lib/mongoid/criteria/queryable/optional.rb +411 -0
  60. data/lib/mongoid/criteria/queryable/options.rb +136 -0
  61. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  62. data/lib/mongoid/criteria/queryable/selectable.rb +662 -0
  63. data/lib/mongoid/criteria/queryable/selector.rb +196 -0
  64. data/lib/mongoid/criteria/queryable/smash.rb +103 -0
  65. data/lib/mongoid/document.rb +9 -23
  66. data/lib/mongoid/errors.rb +2 -1
  67. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  68. data/lib/mongoid/errors/delete_restriction.rb +2 -2
  69. data/lib/mongoid/errors/invalid_field.rb +2 -2
  70. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  71. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  72. data/lib/mongoid/errors/inverse_not_found.rb +1 -1
  73. data/lib/mongoid/errors/mongoid_error.rb +1 -1
  74. data/lib/mongoid/evolvable.rb +1 -1
  75. data/lib/mongoid/extensions.rb +0 -5
  76. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  77. data/lib/mongoid/extensions/date.rb +4 -1
  78. data/lib/mongoid/extensions/hash.rb +2 -3
  79. data/lib/mongoid/extensions/object.rb +2 -2
  80. data/lib/mongoid/extensions/string.rb +4 -3
  81. data/lib/mongoid/extensions/time.rb +5 -2
  82. data/lib/mongoid/factory.rb +1 -0
  83. data/lib/mongoid/fields/foreign_key.rb +2 -2
  84. data/lib/mongoid/fields/localized.rb +3 -8
  85. data/lib/mongoid/fields/validators/macro.rb +18 -0
  86. data/lib/mongoid/findable.rb +3 -3
  87. data/lib/mongoid/indexable.rb +17 -16
  88. data/lib/mongoid/indexable/specification.rb +1 -1
  89. data/lib/mongoid/indexable/validators/options.rb +1 -2
  90. data/lib/mongoid/interceptable.rb +6 -17
  91. data/lib/mongoid/loggable.rb +1 -1
  92. data/lib/mongoid/matchable.rb +3 -10
  93. data/lib/mongoid/matchable/gt.rb +2 -0
  94. data/lib/mongoid/matchable/gte.rb +2 -0
  95. data/lib/mongoid/matchable/lt.rb +2 -0
  96. data/lib/mongoid/matchable/lte.rb +2 -0
  97. data/lib/mongoid/persistable.rb +6 -5
  98. data/lib/mongoid/persistable/creatable.rb +2 -0
  99. data/lib/mongoid/persistable/deletable.rb +7 -3
  100. data/lib/mongoid/persistable/settable.rb +3 -16
  101. data/lib/mongoid/persistable/updatable.rb +10 -12
  102. data/lib/mongoid/persistence_context.rb +216 -0
  103. data/lib/mongoid/query_cache.rb +5 -30
  104. data/lib/mongoid/relations/accessors.rb +6 -2
  105. data/lib/mongoid/relations/auto_save.rb +12 -4
  106. data/lib/mongoid/relations/bindings/embedded/in.rb +4 -0
  107. data/lib/mongoid/relations/bindings/embedded/many.rb +8 -1
  108. data/lib/mongoid/relations/bindings/embedded/one.rb +10 -0
  109. data/lib/mongoid/relations/bindings/referenced/many.rb +4 -0
  110. data/lib/mongoid/relations/builders.rb +2 -2
  111. data/lib/mongoid/relations/builders/embedded/one.rb +1 -1
  112. data/lib/mongoid/relations/builders/nested_attributes/many.rb +1 -1
  113. data/lib/mongoid/relations/conversions.rb +1 -1
  114. data/lib/mongoid/relations/counter_cache.rb +28 -18
  115. data/lib/mongoid/relations/eager.rb +19 -7
  116. data/lib/mongoid/relations/eager/base.rb +5 -5
  117. data/lib/mongoid/relations/embedded/batchable.rb +9 -33
  118. data/lib/mongoid/relations/embedded/in.rb +16 -2
  119. data/lib/mongoid/relations/embedded/many.rb +23 -8
  120. data/lib/mongoid/relations/embedded/one.rb +17 -2
  121. data/lib/mongoid/relations/macros.rb +9 -2
  122. data/lib/mongoid/relations/metadata.rb +3 -3
  123. data/lib/mongoid/relations/nested_builder.rb +1 -1
  124. data/lib/mongoid/relations/options.rb +2 -2
  125. data/lib/mongoid/relations/proxy.rb +2 -33
  126. data/lib/mongoid/relations/referenced/in.rb +23 -11
  127. data/lib/mongoid/relations/referenced/many.rb +24 -16
  128. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  129. data/lib/mongoid/relations/referenced/one.rb +17 -1
  130. data/lib/mongoid/relations/reflections.rb +3 -5
  131. data/lib/mongoid/relations/touchable.rb +1 -1
  132. data/lib/mongoid/reloadable.rb +1 -1
  133. data/lib/mongoid/scopable.rb +3 -3
  134. data/lib/mongoid/serializable.rb +2 -3
  135. data/lib/mongoid/tasks/database.rb +1 -2
  136. data/lib/mongoid/threaded.rb +4 -4
  137. data/lib/mongoid/traversable.rb +1 -1
  138. data/lib/mongoid/validatable.rb +1 -1
  139. data/lib/mongoid/validatable/macros.rb +2 -4
  140. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  141. data/lib/mongoid/version.rb +1 -1
  142. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -7
  143. data/spec/app/models/album.rb +5 -1
  144. data/spec/app/models/artist.rb +21 -0
  145. data/spec/app/models/band.rb +0 -1
  146. data/spec/app/models/church.rb +0 -2
  147. data/spec/app/models/ordered_post.rb +5 -0
  148. data/spec/app/models/oscar.rb +1 -2
  149. data/spec/app/models/person.rb +3 -1
  150. data/spec/app/models/post.rb +0 -1
  151. data/spec/app/models/princess.rb +2 -0
  152. data/spec/app/models/record.rb +1 -0
  153. data/spec/app/models/thing.rb +1 -1
  154. data/spec/config/mongoid.yml +1 -5
  155. data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
  156. data/spec/mongoid/atomic_spec.rb +17 -17
  157. data/spec/mongoid/attributes/nested_spec.rb +14 -14
  158. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  159. data/spec/mongoid/attributes_spec.rb +63 -0
  160. data/spec/mongoid/cacheable_spec.rb +112 -0
  161. data/spec/mongoid/changeable_spec.rb +58 -0
  162. data/spec/mongoid/clients/factory_spec.rb +3 -11
  163. data/spec/mongoid/clients/options_spec.rb +378 -96
  164. data/spec/mongoid/clients_spec.rb +207 -170
  165. data/spec/mongoid/composable_spec.rb +7 -0
  166. data/spec/mongoid/config_spec.rb +41 -21
  167. data/spec/mongoid/contextual/atomic_spec.rb +77 -343
  168. data/spec/mongoid/contextual/map_reduce_spec.rb +119 -111
  169. data/spec/mongoid/contextual/memory_spec.rb +56 -316
  170. data/spec/mongoid/contextual/mongo_spec.rb +104 -378
  171. data/spec/mongoid/copyable_spec.rb +8 -15
  172. data/spec/mongoid/criteria/modifiable_spec.rb +239 -7
  173. data/spec/mongoid/criteria/options_spec.rb +29 -0
  174. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  175. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  176. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  177. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  178. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  179. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  180. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  181. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  182. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  183. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  184. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  185. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  186. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  187. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  188. data/spec/mongoid/{extensions/origin/regexp_raw_spec.rb → criteria/queryable/extensions/regexp_spec.rb} +21 -20
  189. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  190. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  191. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  192. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  193. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  194. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  195. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  196. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  197. data/spec/mongoid/criteria/queryable/optional_spec.rb +1786 -0
  198. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  199. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  200. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  201. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4159 -0
  202. data/spec/mongoid/criteria/queryable/selector_spec.rb +778 -0
  203. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  204. data/spec/mongoid/criteria_spec.rb +45 -63
  205. data/spec/mongoid/document_spec.rb +21 -88
  206. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  207. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  208. data/spec/mongoid/extensions/big_decimal_spec.rb +320 -18
  209. data/spec/mongoid/extensions/date_spec.rb +2 -6
  210. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  211. data/spec/mongoid/extensions/float_spec.rb +8 -1
  212. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  213. data/spec/mongoid/extensions/object_spec.rb +11 -0
  214. data/spec/mongoid/extensions/string_spec.rb +21 -0
  215. data/spec/mongoid/extensions/time_spec.rb +4 -8
  216. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  217. data/spec/mongoid/fields/localized_spec.rb +0 -91
  218. data/spec/mongoid/findable_spec.rb +46 -1
  219. data/spec/mongoid/indexable_spec.rb +6 -46
  220. data/spec/mongoid/interceptable_spec.rb +49 -10
  221. data/spec/mongoid/matchable/gt_spec.rb +11 -0
  222. data/spec/mongoid/matchable/gte_spec.rb +10 -0
  223. data/spec/mongoid/matchable/lt_spec.rb +11 -0
  224. data/spec/mongoid/matchable/lte_spec.rb +11 -0
  225. data/spec/mongoid/matchable_spec.rb +1 -51
  226. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  227. data/spec/mongoid/persistable/deletable_spec.rb +1 -1
  228. data/spec/mongoid/persistable/destroyable_spec.rb +6 -2
  229. data/spec/mongoid/persistable/savable_spec.rb +30 -30
  230. data/spec/mongoid/persistable/settable_spec.rb +0 -185
  231. data/spec/mongoid/persistable/updatable_spec.rb +166 -5
  232. data/spec/mongoid/persistence_context_spec.rb +654 -0
  233. data/spec/mongoid/positional_spec.rb +10 -10
  234. data/spec/mongoid/query_cache_spec.rb +89 -65
  235. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  236. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  237. data/spec/mongoid/relations/builders_spec.rb +37 -10
  238. data/spec/mongoid/relations/counter_cache_spec.rb +64 -15
  239. data/spec/mongoid/relations/cyclic_spec.rb +0 -22
  240. data/spec/mongoid/relations/embedded/many_spec.rb +9 -41
  241. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  242. data/spec/mongoid/relations/macros_spec.rb +395 -7
  243. data/spec/mongoid/relations/proxy_spec.rb +3 -1
  244. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  245. data/spec/mongoid/relations/referenced/many_spec.rb +6 -29
  246. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +6 -29
  247. data/spec/mongoid/relations/reflections_spec.rb +9 -9
  248. data/spec/mongoid/reloadable_spec.rb +51 -0
  249. data/spec/mongoid/scopable_spec.rb +0 -12
  250. data/spec/mongoid/serializable_spec.rb +0 -50
  251. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  252. data/spec/mongoid/validatable/uniqueness_spec.rb +16 -9
  253. data/spec/mongoid/validatable_spec.rb +16 -0
  254. data/spec/spec_helper.rb +10 -10
  255. metadata +536 -479
  256. metadata.gz.sig +0 -0
  257. data/lib/mongoid/clients/thread_options.rb +0 -19
  258. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +0 -20
  259. data/lib/mongoid/extensions/decimal128.rb +0 -39
  260. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  261. data/lib/mongoid/matchable/regexp.rb +0 -27
  262. data/spec/app/models/post_genre.rb +0 -6
  263. data/spec/mongoid/extensions/decimal128_spec.rb +0 -44
  264. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
@@ -0,0 +1,778 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria::Queryable::Selector do
4
+
5
+ describe "merge!" do
6
+
7
+ let(:selector) do
8
+ described_class.new
9
+ end
10
+
11
+ context "when selector is nested" do
12
+
13
+ before do
14
+ selector[:field] = selection
15
+ selector.merge!(other)
16
+ end
17
+
18
+ let(:selection) do
19
+ { "$lt" => 50 }
20
+ end
21
+
22
+ context "when other contains same key with a hash" do
23
+
24
+ let(:other) do
25
+ { "field" => { "$gt" => 20 } }
26
+ end
27
+
28
+ it "deep merges" do
29
+ expect(selector['field']).to eq({"$lt"=>50, "$gt" => 20})
30
+ end
31
+ end
32
+
33
+ context "when other contains same key without hash" do
34
+
35
+ let(:other) do
36
+ { "field" => 10 }
37
+ end
38
+
39
+ it "merges" do
40
+ expect(selector['field']).to eq(10)
41
+ end
42
+ end
43
+ end
44
+
45
+ context "when selector contains a $nin" do
46
+
47
+ let(:initial) do
48
+ { "$nin" => ["foo"] }
49
+ end
50
+
51
+ before do
52
+ selector["field"] = initial
53
+ end
54
+
55
+ context "when merging in a new $nin" do
56
+
57
+ let(:other) do
58
+ { "field" => { "$nin" => ["bar"] } }
59
+ end
60
+
61
+ before do
62
+ selector.merge!(other)
63
+ end
64
+
65
+ it "combines the two $nin queries into one" do
66
+ expect(selector).to eq({
67
+ "field" => { "$nin" => ["foo", "bar"] }
68
+ })
69
+ end
70
+ end
71
+ end
72
+
73
+ context "when selector is not nested" do
74
+
75
+ before do
76
+ selector[:field] = selection
77
+ selector.merge!(other)
78
+ end
79
+
80
+ let(:selection) do
81
+ 50
82
+ end
83
+
84
+ let(:other) do
85
+ { "field" => { "$gt" => 20 } }
86
+ end
87
+
88
+ it "merges" do
89
+ expect(selector['field']).to eq({ "$gt" => 20 })
90
+ end
91
+ end
92
+
93
+ context "when the selector contains an $or" do
94
+
95
+ let(:initial) do
96
+ [{ "value" => 1 }]
97
+ end
98
+
99
+ before do
100
+ selector["$or"] = initial
101
+ end
102
+
103
+ context "when merging in a new $or" do
104
+
105
+ let(:other) do
106
+ [{ "value" => 2 }]
107
+ end
108
+
109
+ before do
110
+ selector.merge!({ "$or" => other })
111
+ end
112
+
113
+ it "combines the two $or queries into one" do
114
+ expect(selector).to eq({
115
+ "$or" => [{ "value" => 1 }, { "value" => 2 }]
116
+ })
117
+ end
118
+ end
119
+ end
120
+
121
+ context "when the selector contains an $and" do
122
+
123
+ let(:initial) do
124
+ [{ "value" => 1 }]
125
+ end
126
+
127
+ before do
128
+ selector["$and"] = initial
129
+ end
130
+
131
+ context "when merging in a new $and" do
132
+
133
+ let(:other) do
134
+ [{ "value" => 2 }]
135
+ end
136
+
137
+ before do
138
+ selector.merge!({ "$and" => other })
139
+ end
140
+
141
+ it "combines the two $and queries into one" do
142
+ expect(selector).to eq({
143
+ "$and" => [{ "value" => 1 }, { "value" => 2 }]
144
+ })
145
+ end
146
+ end
147
+ end
148
+
149
+ context "when the selector contains a $nor" do
150
+
151
+ let(:initial) do
152
+ [{ "value" => 1 }]
153
+ end
154
+
155
+ before do
156
+ selector["$nor"] = initial
157
+ end
158
+
159
+ context "when merging in a new $nor" do
160
+
161
+ let(:other) do
162
+ [{ "value" => 2 }]
163
+ end
164
+
165
+ before do
166
+ selector.merge!({ "$nor" => other })
167
+ end
168
+
169
+ it "combines the two $nor queries into one" do
170
+ expect(selector).to eq({
171
+ "$nor" => initial + other
172
+ })
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ describe "#__deep_copy__" do
179
+
180
+ let(:value) do
181
+ [ 1, 2, 3 ]
182
+ end
183
+
184
+ let(:selection) do
185
+ { "$in" => value }
186
+ end
187
+
188
+ let(:selector) do
189
+ described_class.new
190
+ end
191
+
192
+ before do
193
+ selector[:field] = selection
194
+ end
195
+
196
+ let(:cloned) do
197
+ selector.__deep_copy__
198
+ end
199
+
200
+ it "returns an equal copy" do
201
+ expect(cloned).to eq(selector)
202
+ end
203
+
204
+ it "performs a deep copy" do
205
+ expect(cloned["field"]).to_not equal(selection)
206
+ end
207
+
208
+ it "clones n levels deep" do
209
+ expect(cloned["field"]["$in"]).to_not equal(value)
210
+ end
211
+ end
212
+
213
+ [ :store, :[]= ].each do |method|
214
+
215
+ describe "##{method}" do
216
+
217
+ context "when aliases are provided" do
218
+
219
+ context "when the alias has no serializer" do
220
+
221
+ let(:selector) do
222
+ described_class.new({ "id" => "_id" })
223
+ end
224
+
225
+ before do
226
+ selector.send(method, "id", 1)
227
+ end
228
+
229
+ it "stores the field in the selector by database name" do
230
+ expect(selector["_id"]).to eq(1)
231
+ end
232
+ end
233
+
234
+ context "when the alias has a serializer" do
235
+
236
+ before(:all) do
237
+ class Field
238
+ def evolve(object)
239
+ Integer.evolve(object)
240
+ end
241
+
242
+ def localized?
243
+ false
244
+ end
245
+ end
246
+ end
247
+
248
+ after(:all) do
249
+ Object.send(:remove_const, :Field)
250
+ end
251
+
252
+ let(:selector) do
253
+ described_class.new(
254
+ { "id" => "_id" }, { "_id" => Field.new }
255
+ )
256
+ end
257
+
258
+ it "stores the serialized field in the selector by database name" do
259
+ selector.send(method, "id", "1")
260
+ expect(selector["_id"]).to eq(1)
261
+ end
262
+
263
+ it "stores the serialized field when selector is deeply nested" do
264
+ selector.send(method, "$or", [{'$and' => [{'_id' => '5'}]}])
265
+ expect(selector['$or'][0]['$and'][0]['_id']).to eq(5)
266
+ end
267
+ end
268
+ end
269
+
270
+ context "when no serializers are provided" do
271
+
272
+ let(:selector) do
273
+ described_class.new
274
+ end
275
+
276
+ context "when provided a standard object" do
277
+
278
+ context "when the keys are strings" do
279
+
280
+ it "does not serialize values" do
281
+ expect(selector.send(method, "key", "5")).to eq("5")
282
+ end
283
+ end
284
+
285
+ context "when the keys are symbols" do
286
+
287
+ it "does not serialize values" do
288
+ expect(selector.send(method, :key, "5")).to eq("5")
289
+ end
290
+ end
291
+ end
292
+
293
+ context "when provided a range" do
294
+
295
+ before do
296
+ selector.send(method, "key", 1..3)
297
+ end
298
+
299
+ it "serializes the range" do
300
+ expect(selector["key"]).to eq({ "$gte" => 1, "$lte" => 3 })
301
+ end
302
+ end
303
+
304
+ context "when providing an array" do
305
+
306
+ let(:big_one) do
307
+ BigDecimal.new("1.2321")
308
+ end
309
+
310
+ let(:big_two) do
311
+ BigDecimal.new("4.2222")
312
+ end
313
+
314
+ let(:array) do
315
+ [ big_one, big_two ]
316
+ end
317
+
318
+ before do
319
+ selector.send(method, "key", array)
320
+ end
321
+
322
+ it "serializes each element in the array" do
323
+ expect(selector["key"]).to eq([ big_one.to_s, big_two.to_s ])
324
+ end
325
+ end
326
+ end
327
+
328
+ context "when serializers are provided" do
329
+
330
+ context "when the serializer is not localized" do
331
+
332
+ before(:all) do
333
+ class Field
334
+ def evolve(object)
335
+ Integer.evolve(object)
336
+ end
337
+
338
+ def localized?
339
+ false
340
+ end
341
+ end
342
+ end
343
+
344
+ after(:all) do
345
+ Object.send(:remove_const, :Field)
346
+ end
347
+
348
+ let(:selector) do
349
+ described_class.new({}, { "key" => Field.new })
350
+ end
351
+
352
+ context "when the criterion is simple" do
353
+
354
+ context "when the key is a string" do
355
+
356
+ before do
357
+ selector.send(method, "key", "5")
358
+ end
359
+
360
+ it "serializes the value" do
361
+ expect(selector["key"]).to eq(5)
362
+ end
363
+ end
364
+
365
+ context "when the key is a symbol" do
366
+
367
+ before do
368
+ selector.send(method, :key, "5")
369
+ end
370
+
371
+ it "serializes the value" do
372
+ expect(selector["key"]).to eq(5)
373
+ end
374
+ end
375
+ end
376
+
377
+ context "when the criterion is complex" do
378
+
379
+ context "when the field name is the key" do
380
+
381
+ context "when the criterion is an array" do
382
+
383
+ context "when the key is a string" do
384
+
385
+ before do
386
+ selector.send(method, "key", [ "1", "2" ])
387
+ end
388
+
389
+ it "serializes the value" do
390
+ expect(selector["key"]).to eq([ 1, 2 ])
391
+ end
392
+ end
393
+
394
+ context "when the key is a symbol" do
395
+
396
+ before do
397
+ selector.send(method, :key, [ "1", "2" ])
398
+ end
399
+
400
+ it "serializes the value" do
401
+ expect(selector["key"]).to eq([ 1, 2 ])
402
+ end
403
+ end
404
+ end
405
+
406
+ context "when the criterion is a hash" do
407
+
408
+ context "when the value is non enumerable" do
409
+
410
+ context "when the key is a string" do
411
+
412
+ before do
413
+ selector.send(method, "key", { "$gt" => "5" })
414
+ end
415
+
416
+ it "serializes the value" do
417
+ expect(selector["key"]).to eq({ "$gt" => 5 })
418
+ end
419
+ end
420
+
421
+ context "when the key is a symbol" do
422
+
423
+ before do
424
+ selector.send(method, :key, { "$gt" => "5" })
425
+ end
426
+
427
+ it "serializes the value" do
428
+ expect(selector["key"]).to eq({ "$gt" => 5 })
429
+ end
430
+ end
431
+ end
432
+
433
+ context "when the value is enumerable" do
434
+
435
+ context "when the key is a string" do
436
+
437
+ before do
438
+ selector.send(method, "key", { "$in" => [ "1", "2" ] })
439
+ end
440
+
441
+ it "serializes the value" do
442
+ expect(selector["key"]).to eq({ "$in" => [ 1, 2 ] })
443
+ end
444
+ end
445
+
446
+ context "when the key is a symbol" do
447
+
448
+ before do
449
+ selector.send(method, :key, { "$in" => [ "1", "2" ] })
450
+ end
451
+
452
+ it "serializes the value" do
453
+ expect(selector["key"]).to eq({ "$in" => [ 1, 2 ] })
454
+ end
455
+ end
456
+ end
457
+
458
+ [ "$and", "$or" ].each do |operator|
459
+
460
+ context "when the criterion is a #{operator}" do
461
+
462
+ context "when the individual criteria are simple" do
463
+
464
+ context "when the keys are strings" do
465
+
466
+ before do
467
+ selector.send(method, operator, [{ "key" => "1" }])
468
+ end
469
+
470
+ it "serializes the values" do
471
+ expect(selector[operator]).to eq([{ "key" => 1 }])
472
+ end
473
+ end
474
+
475
+ context "when the keys are symbols" do
476
+
477
+ before do
478
+ selector.send(method, operator, [{ key: "1" }])
479
+ end
480
+
481
+ it "serializes the values" do
482
+ expect(selector[operator]).to eq([{ "key" => 1 }])
483
+ end
484
+ end
485
+ end
486
+
487
+ context "when the individual criteria are complex" do
488
+
489
+ context "when the keys are strings" do
490
+
491
+ before do
492
+ selector.send(
493
+ method,
494
+ operator,
495
+ [{ "field" => "1" }, { "key" => { "$gt" => "2" }}]
496
+ )
497
+ end
498
+
499
+ it "serializes the values" do
500
+ expect(selector[operator]).to eq(
501
+ [{ "field" => "1" }, { "key" => { "$gt" => 2 }}]
502
+ )
503
+ end
504
+ end
505
+
506
+ context "when the keys are symbols" do
507
+
508
+ before do
509
+ selector.send(
510
+ method,
511
+ operator,
512
+ [{ field: "1" }, { key: { "$gt" => "2" }}]
513
+ )
514
+ end
515
+
516
+ it "serializes the values" do
517
+ expect(selector[operator]).to eq(
518
+ [{ "field" => "1" }, { "key" => { "$gt" => 2 }}]
519
+ )
520
+ end
521
+ end
522
+ end
523
+ end
524
+ end
525
+ end
526
+ end
527
+ end
528
+ end
529
+
530
+ context "when the serializer is localized" do
531
+
532
+ before(:all) do
533
+ class Field
534
+ def evolve(object)
535
+ Integer.evolve(object)
536
+ end
537
+
538
+ def localized?
539
+ true
540
+ end
541
+ end
542
+ end
543
+
544
+ after(:all) do
545
+ Object.send(:remove_const, :Field)
546
+ ::I18n.locale = :en
547
+ end
548
+
549
+ let(:selector) do
550
+ described_class.new({}, { "key" => Field.new })
551
+ end
552
+
553
+ before do
554
+ ::I18n.locale = :de
555
+ end
556
+
557
+ context "when the criterion is simple" do
558
+
559
+ context "when the key is a string" do
560
+
561
+ before do
562
+ selector.send(method, "key", "5")
563
+ end
564
+
565
+ it "serializes the value" do
566
+ expect(selector["key.de"]).to eq(5)
567
+ end
568
+ end
569
+
570
+ context "when the key is a symbol" do
571
+
572
+ before do
573
+ selector.send(method, :key, "5")
574
+ end
575
+
576
+ it "serializes the value" do
577
+ expect(selector["key.de"]).to eq(5)
578
+ end
579
+ end
580
+ end
581
+
582
+ context "when the criterion is complex" do
583
+
584
+ context "when the field name is the key" do
585
+
586
+ context "when the criterion is an array" do
587
+
588
+ context "when the key is a string" do
589
+
590
+ before do
591
+ selector.send(method, "key", [ "1", "2" ])
592
+ end
593
+
594
+ it "serializes the value" do
595
+ expect(selector["key.de"]).to eq([ 1, 2 ])
596
+ end
597
+ end
598
+
599
+ context "when the key is a symbol" do
600
+
601
+ before do
602
+ selector.send(method, :key, [ "1", "2" ])
603
+ end
604
+
605
+ it "serializes the value" do
606
+ expect(selector["key.de"]).to eq([ 1, 2 ])
607
+ end
608
+ end
609
+ end
610
+
611
+ context "when the criterion is a hash" do
612
+
613
+ context "when the value is non enumerable" do
614
+
615
+ context "when the key is a string" do
616
+
617
+ let(:hash) do
618
+ { "$gt" => "5" }
619
+ end
620
+
621
+ before do
622
+ selector.send(method, "key", hash)
623
+ end
624
+
625
+ it "serializes the value" do
626
+ expect(selector["key.de"]).to eq({ "$gt" => 5 })
627
+ end
628
+
629
+ it "sets the same hash instance" do
630
+ expect(selector["key.de"]).to equal(hash)
631
+ end
632
+ end
633
+
634
+ context "when the key is a symbol" do
635
+
636
+ before do
637
+ selector.send(method, :key, { "$gt" => "5" })
638
+ end
639
+
640
+ it "serializes the value" do
641
+ expect(selector["key.de"]).to eq({ "$gt" => 5 })
642
+ end
643
+ end
644
+ end
645
+
646
+ context "when the value is enumerable" do
647
+
648
+ context "when the key is a string" do
649
+
650
+ before do
651
+ selector.send(method, "key", { "$in" => [ "1", "2" ] })
652
+ end
653
+
654
+ it "serializes the value" do
655
+ expect(selector["key.de"]).to eq({ "$in" => [ 1, 2 ] })
656
+ end
657
+ end
658
+
659
+ context "when the key is a symbol" do
660
+
661
+ before do
662
+ selector.send(method, :key, { "$in" => [ "1", "2" ] })
663
+ end
664
+
665
+ it "serializes the value" do
666
+ expect(selector["key.de"]).to eq({ "$in" => [ 1, 2 ] })
667
+ end
668
+ end
669
+ end
670
+
671
+ [ "$and", "$or" ].each do |operator|
672
+
673
+ context "when the criterion is a #{operator}" do
674
+
675
+ context "when the individual criteria are simple" do
676
+
677
+ context "when the keys are strings" do
678
+
679
+ before do
680
+ selector.send(method, operator, [{ "key" => "1" }])
681
+ end
682
+
683
+ it "serializes the values" do
684
+ expect(selector[operator]).to eq([{ "key.de" => 1 }])
685
+ end
686
+ end
687
+
688
+ context "when the keys are symbols" do
689
+
690
+ before do
691
+ selector.send(method, operator, [{ key: "1" }])
692
+ end
693
+
694
+ it "serializes the values" do
695
+ expect(selector[operator]).to eq([{ "key.de" => 1 }])
696
+ end
697
+ end
698
+ end
699
+
700
+ context "when the individual criteria are complex" do
701
+
702
+ context "when the keys are strings" do
703
+
704
+ before do
705
+ selector.send(
706
+ method,
707
+ operator,
708
+ [{ "field" => "1" }, { "key" => { "$gt" => "2" }}]
709
+ )
710
+ end
711
+
712
+ it "serializes the values" do
713
+ expect(selector[operator]).to eq(
714
+ [{ "field" => "1" }, { "key.de" => { "$gt" => 2 }}]
715
+ )
716
+ end
717
+ end
718
+
719
+ context "when the keys are symbols" do
720
+
721
+ before do
722
+ selector.send(
723
+ method,
724
+ operator,
725
+ [{ field: "1" }, { key: { "$gt" => "2" }}]
726
+ )
727
+ end
728
+
729
+ it "serializes the values" do
730
+ expect(selector[operator]).to eq(
731
+ [{ "field" => "1" }, { "key.de" => { "$gt" => 2 }}]
732
+ )
733
+ end
734
+ end
735
+ end
736
+ end
737
+ end
738
+ end
739
+ end
740
+ end
741
+ end
742
+ end
743
+ end
744
+ end
745
+
746
+ describe "#to_pipeline" do
747
+
748
+ let(:selector) do
749
+ described_class.new
750
+ end
751
+
752
+ context "when the selector is empty" do
753
+
754
+ let(:pipeline) do
755
+ selector.to_pipeline
756
+ end
757
+
758
+ it "returns an empty array" do
759
+ expect(pipeline).to be_empty
760
+ end
761
+ end
762
+
763
+ context "when the selector is not empty" do
764
+
765
+ before do
766
+ selector["name"] = "test"
767
+ end
768
+
769
+ let(:pipeline) do
770
+ selector.to_pipeline
771
+ end
772
+
773
+ it "returns the selector in a $match entry" do
774
+ expect(pipeline).to eq([{ "$match" => { "name" => "test" }}])
775
+ end
776
+ end
777
+ end
778
+ end