mongoid 5.4.0 → 6.4.8

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 (301) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/Rakefile +26 -0
  5. data/lib/config/locales/en.yml +40 -0
  6. data/lib/mongoid/atomic/modifiers.rb +2 -2
  7. data/lib/mongoid/atomic.rb +5 -5
  8. data/lib/mongoid/attributes/readonly.rb +22 -0
  9. data/lib/mongoid/attributes.rb +22 -21
  10. data/lib/mongoid/cacheable.rb +36 -0
  11. data/lib/mongoid/changeable.rb +36 -0
  12. data/lib/mongoid/clients/options.rb +55 -250
  13. data/lib/mongoid/clients/sessions.rb +113 -0
  14. data/lib/mongoid/clients/storage_options.rb +2 -69
  15. data/lib/mongoid/clients.rb +10 -63
  16. data/lib/mongoid/composable.rb +29 -2
  17. data/lib/mongoid/config.rb +1 -0
  18. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  19. data/lib/mongoid/contextual/atomic.rb +4 -4
  20. data/lib/mongoid/contextual/map_reduce.rb +7 -3
  21. data/lib/mongoid/contextual/memory.rb +9 -4
  22. data/lib/mongoid/contextual/mongo.rb +65 -30
  23. data/lib/mongoid/contextual/none.rb +12 -0
  24. data/lib/mongoid/copyable.rb +13 -6
  25. data/lib/mongoid/criteria/marshalable.rb +2 -2
  26. data/lib/mongoid/criteria/modifiable.rb +29 -3
  27. data/lib/mongoid/criteria/options.rb +25 -0
  28. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  29. data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
  30. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
  31. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
  32. data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
  33. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
  34. data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
  35. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
  36. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
  37. data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
  38. data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
  39. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +79 -0
  40. data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
  41. data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
  42. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
  43. data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
  44. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
  45. data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
  46. data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
  47. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  48. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  49. data/lib/mongoid/criteria/queryable/mergeable.rb +273 -0
  50. data/lib/mongoid/criteria/queryable/optional.rb +429 -0
  51. data/lib/mongoid/criteria/queryable/options.rb +153 -0
  52. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  53. data/lib/mongoid/criteria/queryable/selectable.rb +689 -0
  54. data/lib/mongoid/criteria/queryable/selector.rb +212 -0
  55. data/lib/mongoid/criteria/queryable/smash.rb +104 -0
  56. data/lib/mongoid/criteria/queryable.rb +87 -0
  57. data/lib/mongoid/criteria.rb +6 -2
  58. data/lib/mongoid/document.rb +34 -41
  59. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  60. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
  61. data/lib/mongoid/errors/invalid_field.rb +2 -2
  62. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  63. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  64. data/lib/mongoid/errors/invalid_session_use.rb +24 -0
  65. data/lib/mongoid/errors.rb +3 -0
  66. data/lib/mongoid/evolvable.rb +1 -1
  67. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  68. data/lib/mongoid/extensions/date.rb +4 -1
  69. data/lib/mongoid/extensions/decimal128.rb +3 -3
  70. data/lib/mongoid/extensions/hash.rb +1 -0
  71. data/lib/mongoid/extensions/regexp.rb +1 -0
  72. data/lib/mongoid/extensions/string.rb +6 -3
  73. data/lib/mongoid/extensions/time.rb +4 -1
  74. data/lib/mongoid/extensions.rb +0 -4
  75. data/lib/mongoid/factory.rb +2 -1
  76. data/lib/mongoid/fields/validators/macro.rb +18 -0
  77. data/lib/mongoid/findable.rb +2 -2
  78. data/lib/mongoid/indexable.rb +16 -14
  79. data/lib/mongoid/interceptable.rb +9 -22
  80. data/lib/mongoid/matchable/all.rb +2 -2
  81. data/lib/mongoid/matchable/and.rb +3 -3
  82. data/lib/mongoid/matchable/default.rb +2 -2
  83. data/lib/mongoid/matchable/elem_match.rb +28 -0
  84. data/lib/mongoid/matchable/exists.rb +2 -2
  85. data/lib/mongoid/matchable/gt.rb +4 -2
  86. data/lib/mongoid/matchable/gte.rb +4 -2
  87. data/lib/mongoid/matchable/in.rb +2 -2
  88. data/lib/mongoid/matchable/lt.rb +4 -2
  89. data/lib/mongoid/matchable/lte.rb +4 -2
  90. data/lib/mongoid/matchable/ne.rb +2 -2
  91. data/lib/mongoid/matchable/nin.rb +2 -2
  92. data/lib/mongoid/matchable/nor.rb +37 -0
  93. data/lib/mongoid/matchable/or.rb +3 -3
  94. data/lib/mongoid/matchable/regexp.rb +3 -3
  95. data/lib/mongoid/matchable/size.rb +2 -2
  96. data/lib/mongoid/matchable.rb +16 -7
  97. data/lib/mongoid/persistable/creatable.rb +5 -3
  98. data/lib/mongoid/persistable/deletable.rb +5 -3
  99. data/lib/mongoid/persistable/destroyable.rb +1 -5
  100. data/lib/mongoid/persistable/settable.rb +5 -5
  101. data/lib/mongoid/persistable/updatable.rb +7 -14
  102. data/lib/mongoid/persistable/upsertable.rb +2 -1
  103. data/lib/mongoid/persistable.rb +4 -6
  104. data/lib/mongoid/persistence_context.rb +220 -0
  105. data/lib/mongoid/query_cache.rb +67 -23
  106. data/lib/mongoid/railtie.rb +17 -1
  107. data/lib/mongoid/railties/controller_runtime.rb +86 -0
  108. data/lib/mongoid/relations/accessors.rb +3 -0
  109. data/lib/mongoid/relations/auto_save.rb +12 -4
  110. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
  111. data/lib/mongoid/relations/counter_cache.rb +15 -5
  112. data/lib/mongoid/relations/eager/base.rb +3 -3
  113. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
  114. data/lib/mongoid/relations/eager/has_many.rb +1 -1
  115. data/lib/mongoid/relations/eager.rb +6 -11
  116. data/lib/mongoid/relations/embedded/batchable.rb +20 -18
  117. data/lib/mongoid/relations/embedded/in.rb +13 -1
  118. data/lib/mongoid/relations/embedded/many.rb +51 -10
  119. data/lib/mongoid/relations/embedded/one.rb +14 -1
  120. data/lib/mongoid/relations/macros.rb +9 -1
  121. data/lib/mongoid/relations/many.rb +4 -0
  122. data/lib/mongoid/relations/metadata.rb +3 -3
  123. data/lib/mongoid/relations/options.rb +2 -2
  124. data/lib/mongoid/relations/proxy.rb +1 -31
  125. data/lib/mongoid/relations/referenced/in.rb +19 -10
  126. data/lib/mongoid/relations/referenced/many.rb +30 -26
  127. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  128. data/lib/mongoid/relations/referenced/one.rb +15 -1
  129. data/lib/mongoid/relations/synchronization.rb +12 -12
  130. data/lib/mongoid/relations/targets/enumerable.rb +24 -4
  131. data/lib/mongoid/relations/touchable.rb +7 -4
  132. data/lib/mongoid/reloadable.rb +2 -2
  133. data/lib/mongoid/scopable.rb +3 -3
  134. data/lib/mongoid/serializable.rb +1 -1
  135. data/lib/mongoid/stateful.rb +1 -0
  136. data/lib/mongoid/tasks/database.rb +3 -2
  137. data/lib/mongoid/threaded.rb +74 -0
  138. data/lib/mongoid/traversable.rb +1 -1
  139. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  140. data/lib/mongoid/version.rb +1 -1
  141. data/lib/mongoid.rb +6 -6
  142. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +18 -3
  143. data/spec/app/models/agent.rb +2 -0
  144. data/spec/app/models/album.rb +5 -1
  145. data/spec/app/models/array_field.rb +7 -0
  146. data/spec/app/models/artist.rb +21 -0
  147. data/spec/app/models/band.rb +3 -0
  148. data/spec/app/models/book.rb +2 -1
  149. data/spec/app/models/delegating_patient.rb +16 -0
  150. data/spec/app/models/dokument.rb +1 -0
  151. data/spec/app/models/ordered_post.rb +5 -0
  152. data/spec/app/models/oscar.rb +1 -2
  153. data/spec/app/models/page.rb +1 -1
  154. data/spec/app/models/person.rb +3 -3
  155. data/spec/app/models/princess.rb +2 -0
  156. data/spec/app/models/record.rb +1 -0
  157. data/spec/app/models/subscription.rb +1 -0
  158. data/spec/app/models/thing.rb +1 -1
  159. data/spec/config/mongoid.yml +15 -0
  160. data/spec/integration/document_spec.rb +22 -0
  161. data/spec/mongoid/atomic/modifiers_spec.rb +3 -3
  162. data/spec/mongoid/atomic_spec.rb +5 -5
  163. data/spec/mongoid/attributes/nested_spec.rb +18 -14
  164. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  165. data/spec/mongoid/attributes_spec.rb +90 -5
  166. data/spec/mongoid/cacheable_spec.rb +112 -0
  167. data/spec/mongoid/changeable_spec.rb +58 -0
  168. data/spec/mongoid/clients/factory_spec.rb +80 -28
  169. data/spec/mongoid/clients/options_spec.rb +396 -95
  170. data/spec/mongoid/clients/sessions_spec.rb +334 -0
  171. data/spec/mongoid/clients_spec.rb +243 -101
  172. data/spec/mongoid/composable_spec.rb +7 -0
  173. data/spec/mongoid/config_spec.rb +67 -11
  174. data/spec/mongoid/contextual/atomic_spec.rb +3 -3
  175. data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
  176. data/spec/mongoid/contextual/mongo_spec.rb +275 -22
  177. data/spec/mongoid/contextual/none_spec.rb +15 -0
  178. data/spec/mongoid/copyable_spec.rb +13 -4
  179. data/spec/mongoid/criteria/modifiable_spec.rb +297 -16
  180. data/spec/mongoid/criteria/options_spec.rb +29 -0
  181. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  182. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  183. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  184. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  185. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  186. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  187. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  188. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  189. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  190. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  191. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  192. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  193. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  194. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  195. data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
  196. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
  197. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  198. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  199. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  200. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  201. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  202. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  203. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  204. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  205. data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
  206. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  207. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  208. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  209. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4242 -0
  210. data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
  211. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  212. data/spec/mongoid/criteria/scopable_spec.rb +81 -0
  213. data/spec/mongoid/criteria_spec.rb +156 -22
  214. data/spec/mongoid/document_spec.rb +100 -90
  215. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  216. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  217. data/spec/mongoid/extensions/big_decimal_spec.rb +321 -19
  218. data/spec/mongoid/extensions/boolean_spec.rb +14 -0
  219. data/spec/mongoid/extensions/date_spec.rb +2 -6
  220. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  221. data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
  222. data/spec/mongoid/extensions/float_spec.rb +8 -1
  223. data/spec/mongoid/extensions/hash_spec.rb +15 -0
  224. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  225. data/spec/mongoid/extensions/object_spec.rb +11 -0
  226. data/spec/mongoid/extensions/regexp_spec.rb +23 -0
  227. data/spec/mongoid/extensions/string_spec.rb +53 -4
  228. data/spec/mongoid/extensions/time_spec.rb +2 -6
  229. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  230. data/spec/mongoid/factory_spec.rb +11 -0
  231. data/spec/mongoid/fields_spec.rb +1 -1
  232. data/spec/mongoid/findable_spec.rb +47 -2
  233. data/spec/mongoid/indexable_spec.rb +15 -3
  234. data/spec/mongoid/interceptable_spec.rb +85 -19
  235. data/spec/mongoid/matchable/all_spec.rb +4 -4
  236. data/spec/mongoid/matchable/and_spec.rb +10 -10
  237. data/spec/mongoid/matchable/default_spec.rb +12 -12
  238. data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
  239. data/spec/mongoid/matchable/exists_spec.rb +5 -5
  240. data/spec/mongoid/matchable/gt_spec.rb +18 -7
  241. data/spec/mongoid/matchable/gte_spec.rb +17 -7
  242. data/spec/mongoid/matchable/in_spec.rb +5 -5
  243. data/spec/mongoid/matchable/lt_spec.rb +18 -7
  244. data/spec/mongoid/matchable/lte_spec.rb +18 -7
  245. data/spec/mongoid/matchable/ne_spec.rb +5 -5
  246. data/spec/mongoid/matchable/nin_spec.rb +5 -5
  247. data/spec/mongoid/matchable/nor_spec.rb +209 -0
  248. data/spec/mongoid/matchable/or_spec.rb +7 -7
  249. data/spec/mongoid/matchable/regexp_spec.rb +5 -5
  250. data/spec/mongoid/matchable/size_spec.rb +3 -3
  251. data/spec/mongoid/matchable_spec.rb +199 -54
  252. data/spec/mongoid/persistable/creatable_spec.rb +7 -2
  253. data/spec/mongoid/persistable/deletable_spec.rb +35 -1
  254. data/spec/mongoid/persistable/destroyable_spec.rb +25 -2
  255. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  256. data/spec/mongoid/persistable/savable_spec.rb +34 -29
  257. data/spec/mongoid/persistable/settable_spec.rb +77 -27
  258. data/spec/mongoid/persistable/updatable_spec.rb +182 -3
  259. data/spec/mongoid/persistable_spec.rb +16 -16
  260. data/spec/mongoid/persistence_context_spec.rb +694 -0
  261. data/spec/mongoid/positional_spec.rb +1 -1
  262. data/spec/mongoid/query_cache_spec.rb +170 -12
  263. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  264. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  265. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
  266. data/spec/mongoid/relations/builders_spec.rb +37 -10
  267. data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
  268. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
  269. data/spec/mongoid/relations/eager_spec.rb +40 -0
  270. data/spec/mongoid/relations/embedded/many_spec.rb +305 -59
  271. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  272. data/spec/mongoid/relations/macros_spec.rb +415 -7
  273. data/spec/mongoid/relations/metadata_spec.rb +15 -1
  274. data/spec/mongoid/relations/proxy_spec.rb +27 -1
  275. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  276. data/spec/mongoid/relations/referenced/many_spec.rb +35 -25
  277. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
  278. data/spec/mongoid/relations/synchronization_spec.rb +48 -2
  279. data/spec/mongoid/relations/targets/enumerable_spec.rb +108 -0
  280. data/spec/mongoid/relations/touchable_spec.rb +40 -0
  281. data/spec/mongoid/reloadable_spec.rb +51 -0
  282. data/spec/mongoid/scopable_spec.rb +13 -0
  283. data/spec/mongoid/serializable_spec.rb +0 -50
  284. data/spec/mongoid/threaded_spec.rb +68 -0
  285. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  286. data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
  287. data/spec/mongoid/validatable_spec.rb +16 -0
  288. data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
  289. data/spec/spec_helper.rb +101 -8
  290. data/spec/support/cluster_config.rb +158 -0
  291. data/spec/support/constraints.rb +101 -0
  292. data/spec/support/macros.rb +20 -0
  293. data/spec/support/session_registry.rb +50 -0
  294. data/spec/support/spec_config.rb +42 -0
  295. data.tar.gz.sig +0 -0
  296. metadata +163 -61
  297. metadata.gz.sig +0 -0
  298. data/lib/mongoid/clients/thread_options.rb +0 -19
  299. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  300. data/lib/mongoid/railties/document.rb +0 -12
  301. data/spec/mongoid/railties/document_spec.rb +0 -24
@@ -0,0 +1,4242 @@
1
+ require "spec_helper"
2
+
3
+ describe Mongoid::Criteria::Queryable::Selectable do
4
+
5
+ let(:query) do
6
+ Mongoid::Query.new("id" => "_id")
7
+ end
8
+
9
+ shared_examples_for "a cloning selection" do
10
+
11
+ it "returns a cloned query" do
12
+ expect(selection).to_not equal(query)
13
+ end
14
+ end
15
+
16
+ describe "#all" do
17
+
18
+ context "when provided no criterion" do
19
+
20
+ let(:selection) do
21
+ query.all
22
+ end
23
+
24
+ it "does not add any criterion" do
25
+ expect(selection.selector).to eq({})
26
+ end
27
+
28
+ it "returns the query" do
29
+ expect(selection).to eq(query)
30
+ end
31
+
32
+ it "returns a cloned query" do
33
+ expect(selection).to_not equal(query)
34
+ end
35
+ end
36
+
37
+ context "when provided nil" do
38
+
39
+ let(:selection) do
40
+ query.all(nil)
41
+ end
42
+
43
+ it "does not add any criterion" do
44
+ expect(selection.selector).to eq({})
45
+ end
46
+
47
+ it "returns the query" do
48
+ expect(selection).to eq(query)
49
+ end
50
+
51
+ it "returns a cloned query" do
52
+ expect(selection).to_not equal(query)
53
+ end
54
+ end
55
+
56
+ context "when provided a single criterion" do
57
+
58
+ context "when no serializers are provided" do
59
+
60
+ context "when providing an array" do
61
+
62
+ let(:selection) do
63
+ query.all(field: [ 1, 2 ])
64
+ end
65
+
66
+ it "adds the $all selector" do
67
+ expect(selection.selector).to eq({
68
+ "field" => { "$all" => [ 1, 2 ] }
69
+ })
70
+ end
71
+
72
+ it "returns a cloned query" do
73
+ expect(selection).to_not equal(query)
74
+ end
75
+ end
76
+
77
+ context "when providing a range" do
78
+
79
+ let(:selection) do
80
+ query.all(field: 1..3)
81
+ end
82
+
83
+ it "adds the $all selector with converted range" do
84
+ expect(selection.selector).to eq({
85
+ "field" => { "$all" => [ 1, 2, 3 ] }
86
+ })
87
+ end
88
+
89
+ it "returns a cloned query" do
90
+ expect(selection).to_not equal(query)
91
+ end
92
+ end
93
+
94
+ context "when providing a single value" do
95
+
96
+ let(:selection) do
97
+ query.all(field: 1)
98
+ end
99
+
100
+ it "adds the $all selector with wrapped value" do
101
+ expect(selection.selector).to eq({
102
+ "field" => { "$all" => [ 1 ] }
103
+ })
104
+ end
105
+
106
+ it "returns a cloned query" do
107
+ expect(selection).to_not equal(query)
108
+ end
109
+ end
110
+ end
111
+
112
+ context "when serializers are provided" do
113
+
114
+ before(:all) do
115
+ class Field
116
+ def evolve(object)
117
+ Integer.evolve(object)
118
+ end
119
+ def localized?
120
+ false
121
+ end
122
+ end
123
+ end
124
+
125
+ after(:all) do
126
+ Object.send(:remove_const, :Field)
127
+ end
128
+
129
+ let!(:query) do
130
+ Mongoid::Query.new({}, { "field" => Field.new })
131
+ end
132
+
133
+ context "when providing an array" do
134
+
135
+ let(:selection) do
136
+ query.all(field: [ "1", "2" ])
137
+ end
138
+
139
+ it "adds the $all selector" do
140
+ expect(selection.selector).to eq({
141
+ "field" => { "$all" => [ 1, 2 ] }
142
+ })
143
+ end
144
+
145
+ it "returns a cloned query" do
146
+ expect(selection).to_not equal(query)
147
+ end
148
+ end
149
+
150
+ context "when providing a range" do
151
+
152
+ let(:selection) do
153
+ query.all(field: "1".."3")
154
+ end
155
+
156
+ it "adds the $all selector with converted range" do
157
+ expect(selection.selector).to eq({
158
+ "field" => { "$all" => [ 1, 2, 3 ] }
159
+ })
160
+ end
161
+
162
+ it "returns a cloned query" do
163
+ expect(selection).to_not equal(query)
164
+ end
165
+ end
166
+
167
+ context "when providing a single value" do
168
+
169
+ let(:selection) do
170
+ query.all(field: "1")
171
+ end
172
+
173
+ it "adds the $all selector with wrapped value" do
174
+ expect(selection.selector).to eq({
175
+ "field" => { "$all" => [ 1 ] }
176
+ })
177
+ end
178
+
179
+ it "returns a cloned query" do
180
+ expect(selection).to_not equal(query)
181
+ end
182
+ end
183
+ end
184
+ end
185
+
186
+ context "when provided multiple criterion" do
187
+
188
+ context "when the criterion are for different fields" do
189
+
190
+ let(:selection) do
191
+ query.all(first: [ 1, 2 ], second: [ 3, 4 ])
192
+ end
193
+
194
+ it "adds the $all selectors" do
195
+ expect(selection.selector).to eq({
196
+ "first" => { "$all" => [ 1, 2 ] },
197
+ "second" => { "$all" => [ 3, 4 ] }
198
+ })
199
+ end
200
+
201
+ it "returns a cloned query" do
202
+ expect(selection).to_not equal(query)
203
+ end
204
+ end
205
+ end
206
+
207
+ context "when chaining the criterion" do
208
+
209
+ context "when the criterion are for different fields" do
210
+
211
+ let(:selection) do
212
+ query.all(first: [ 1, 2 ]).all(second: [ 3, 4 ])
213
+ end
214
+
215
+ it "adds the $all selectors" do
216
+ expect(selection.selector).to eq({
217
+ "first" => { "$all" => [ 1, 2 ] },
218
+ "second" => { "$all" => [ 3, 4 ] }
219
+ })
220
+ end
221
+
222
+ it "returns a cloned query" do
223
+ expect(selection).to_not equal(query)
224
+ end
225
+ end
226
+
227
+ context "when the criterion are on the same field" do
228
+
229
+ context "when no serializers are provided" do
230
+
231
+ context "when the strategy is the default (union)" do
232
+
233
+ let(:selection) do
234
+ query.all(first: [ 1, 2 ]).all(first: [ 3, 4 ])
235
+ end
236
+
237
+ it "overwrites the first $all selector" do
238
+ expect(selection.selector).to eq({
239
+ "first" => { "$all" => [ 1, 2, 3, 4 ] }
240
+ })
241
+ end
242
+
243
+ it "returns a cloned query" do
244
+ expect(selection).to_not equal(query)
245
+ end
246
+ end
247
+
248
+ context "when the strategy is intersect" do
249
+
250
+ let(:selection) do
251
+ query.all(first: [ 1, 2 ]).intersect.all(first: [ 2, 3 ])
252
+ end
253
+
254
+ it "intersects the $all selectors" do
255
+ expect(selection.selector).to eq({
256
+ "first" => { "$all" => [ 2 ] }
257
+ })
258
+ end
259
+
260
+ it "returns a cloned query" do
261
+ expect(selection).to_not equal(query)
262
+ end
263
+ end
264
+
265
+ context "when the strategy is override" do
266
+
267
+ let(:selection) do
268
+ query.all(first: [ 1, 2 ]).override.all(first: [ 3, 4 ])
269
+ end
270
+
271
+ it "overwrites the first $all selector" do
272
+ expect(selection.selector).to eq({
273
+ "first" => { "$all" => [ 3, 4 ] }
274
+ })
275
+ end
276
+
277
+ it "returns a cloned query" do
278
+ expect(selection).to_not equal(query)
279
+ end
280
+ end
281
+
282
+ context "when the strategy is union" do
283
+
284
+ let(:selection) do
285
+ query.all(first: [ 1, 2 ]).union.all(first: [ 3, 4 ])
286
+ end
287
+
288
+ it "unions the $all selectors" do
289
+ expect(selection.selector).to eq({
290
+ "first" => { "$all" => [ 1, 2, 3, 4 ] }
291
+ })
292
+ end
293
+
294
+ it "returns a cloned query" do
295
+ expect(selection).to_not equal(query)
296
+ end
297
+ end
298
+ end
299
+
300
+ context "when serializers are provided" do
301
+
302
+ before(:all) do
303
+ class Field
304
+ def evolve(object)
305
+ Integer.evolve(object)
306
+ end
307
+ def localized?
308
+ false
309
+ end
310
+ end
311
+ end
312
+
313
+ after(:all) do
314
+ Object.send(:remove_const, :Field)
315
+ end
316
+
317
+ let!(:query) do
318
+ Mongoid::Query.new({}, { "field" => Field.new })
319
+ end
320
+
321
+ context "when the strategy is the default (union)" do
322
+
323
+ let(:selection) do
324
+ query.all(field: [ "1", "2" ]).all(field: [ "3", "4" ])
325
+ end
326
+
327
+ it "overwrites the field $all selector" do
328
+ expect(selection.selector).to eq({
329
+ "field" => { "$all" => [ 1, 2, 3, 4 ] }
330
+ })
331
+ end
332
+
333
+ it "returns a cloned query" do
334
+ expect(selection).to_not equal(query)
335
+ end
336
+ end
337
+
338
+ context "when the strategy is intersect" do
339
+
340
+ let(:selection) do
341
+ query.all(field: [ "1", "2" ]).intersect.all(field: [ "2", "3" ])
342
+ end
343
+
344
+ it "intersects the $all selectors" do
345
+ expect(selection.selector).to eq({
346
+ "field" => { "$all" => [ 2 ] }
347
+ })
348
+ end
349
+
350
+ it "returns a cloned query" do
351
+ expect(selection).to_not equal(query)
352
+ end
353
+ end
354
+
355
+ context "when the strategy is override" do
356
+
357
+ let(:selection) do
358
+ query.all(field: [ "1", "2" ]).override.all(field: [ "3", "4" ])
359
+ end
360
+
361
+ it "overwrites the field $all selector" do
362
+ expect(selection.selector).to eq({
363
+ "field" => { "$all" => [ 3, 4 ] }
364
+ })
365
+ end
366
+
367
+ it "returns a cloned query" do
368
+ expect(selection).to_not equal(query)
369
+ end
370
+ end
371
+
372
+ context "when the strategy is union" do
373
+
374
+ let(:selection) do
375
+ query.all(field: [ "1", "2" ]).union.all(field: [ "3", "4" ])
376
+ end
377
+
378
+ it "unions the $all selectors" do
379
+ expect(selection.selector).to eq({
380
+ "field" => { "$all" => [ 1, 2, 3, 4 ] }
381
+ })
382
+ end
383
+
384
+ it "returns a cloned query" do
385
+ expect(selection).to_not equal(query)
386
+ end
387
+ end
388
+ end
389
+ end
390
+ end
391
+ end
392
+
393
+ describe "#and" do
394
+
395
+ context "when provided no criterion" do
396
+
397
+ let(:selection) do
398
+ query.and
399
+ end
400
+
401
+ it "does not add any criterion" do
402
+ expect(selection.selector).to eq({})
403
+ end
404
+
405
+ it "returns the query" do
406
+ expect(selection).to eq(query)
407
+ end
408
+
409
+ it "returns a cloned query" do
410
+ expect(selection).to_not equal(query)
411
+ end
412
+ end
413
+
414
+ context "when provided nil" do
415
+
416
+ let(:selection) do
417
+ query.and(nil)
418
+ end
419
+
420
+ it "does not add any criterion" do
421
+ expect(selection.selector).to eq({})
422
+ end
423
+
424
+ it "returns the query" do
425
+ expect(selection).to eq(query)
426
+ end
427
+
428
+ it "returns a cloned query" do
429
+ expect(selection).to_not equal(query)
430
+ end
431
+ end
432
+
433
+ context "when provided a single criterion" do
434
+
435
+ let(:selection) do
436
+ query.and(field: [ 1, 2 ])
437
+ end
438
+
439
+ it "adds the $and selector" do
440
+ expect(selection.selector).to eq({
441
+ "$and" => [{ "field" => [ 1, 2 ] }]
442
+ })
443
+ end
444
+
445
+ it "returns a cloned query" do
446
+ expect(selection).to_not equal(query)
447
+ end
448
+ end
449
+
450
+ context "when provided a nested criterion" do
451
+
452
+ let(:selection) do
453
+ query.and(:test.elem_match => { :field.in => [ 1, 2 ] })
454
+ end
455
+
456
+ it "adds the $and selector" do
457
+ expect(selection.selector).to eq({
458
+ "$and" => [{ "test" => { "$elemMatch" => { "field" => { "$in" => [ 1, 2 ] }}}}]
459
+ })
460
+ end
461
+
462
+ it "returns a cloned query" do
463
+ expect(selection).to_not equal(query)
464
+ end
465
+ end
466
+
467
+ context "when provided multiple criterion" do
468
+
469
+ context "when the criterion is already included" do
470
+
471
+ let(:selection) do
472
+ query.and({ first: [ 1, 2 ] }).and({ first: [ 1, 2 ] })
473
+ end
474
+
475
+ it "does not duplicate the $and selector" do
476
+ expect(selection.selector).to eq({
477
+ "$and" => [
478
+ { "first" => [ 1, 2 ] }
479
+ ]
480
+ })
481
+ end
482
+
483
+ it "returns a cloned query" do
484
+ expect(selection).to_not equal(query)
485
+ end
486
+ end
487
+
488
+ context "when the criterion are for different fields" do
489
+
490
+ let(:selection) do
491
+ query.and({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
492
+ end
493
+
494
+ it "adds the $and selector" do
495
+ expect(selection.selector).to eq({
496
+ "$and" => [
497
+ { "first" => [ 1, 2 ] },
498
+ { "second" => [ 3, 4 ] }
499
+ ]
500
+ })
501
+ end
502
+
503
+ it "returns a cloned query" do
504
+ expect(selection).to_not equal(query)
505
+ end
506
+ end
507
+
508
+ context "when the criterion are on the same field" do
509
+
510
+ let(:selection) do
511
+ query.and({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
512
+ end
513
+
514
+ it "appends both $and expressions" do
515
+ expect(selection.selector).to eq({
516
+ "$and" => [
517
+ { "first" => [ 1, 2 ] },
518
+ { "first" => [ 3, 4 ] }
519
+ ]
520
+ })
521
+ end
522
+
523
+ it "returns a cloned query" do
524
+ expect(selection).to_not equal(query)
525
+ end
526
+ end
527
+ end
528
+
529
+ context "when chaining the criterion" do
530
+
531
+ context "when the criterion are for different fields" do
532
+
533
+ let(:selection) do
534
+ query.and(first: [ 1, 2 ]).and(second: [ 3, 4 ])
535
+ end
536
+
537
+ it "adds the $and selectors" do
538
+ expect(selection.selector).to eq({
539
+ "$and" => [
540
+ { "first" => [ 1, 2 ] },
541
+ { "second" => [ 3, 4 ] }
542
+ ]
543
+ })
544
+ end
545
+
546
+ it "returns a cloned query" do
547
+ expect(selection).to_not equal(query)
548
+ end
549
+ end
550
+
551
+ context "when the criterion are on the same field" do
552
+
553
+ let(:selection) do
554
+ query.and(first: [ 1, 2 ]).and(first: [ 3, 4 ])
555
+ end
556
+
557
+ it "appends both $and expressions" do
558
+ expect(selection.selector).to eq({
559
+ "$and" => [
560
+ { "first" => [ 1, 2 ] },
561
+ { "first" => [ 3, 4 ] }
562
+ ]
563
+ })
564
+ end
565
+
566
+ it "returns a cloned query" do
567
+ expect(selection).to_not equal(query)
568
+ end
569
+ end
570
+ end
571
+ end
572
+
573
+ describe "#between" do
574
+
575
+ context "when provided no criterion" do
576
+
577
+ let(:selection) do
578
+ query.between
579
+ end
580
+
581
+ it "does not add any criterion" do
582
+ expect(selection.selector).to eq({})
583
+ end
584
+
585
+ it "returns the query" do
586
+ expect(selection).to eq(query)
587
+ end
588
+
589
+ it "returns a cloned query" do
590
+ expect(selection).to_not equal(query)
591
+ end
592
+ end
593
+
594
+ context "when provided nil" do
595
+
596
+ let(:selection) do
597
+ query.between(nil)
598
+ end
599
+
600
+ it "does not add any criterion" do
601
+ expect(selection.selector).to eq({})
602
+ end
603
+
604
+ it "returns the query" do
605
+ expect(selection).to eq(query)
606
+ end
607
+
608
+ it "returns a cloned query" do
609
+ expect(selection).to_not equal(query)
610
+ end
611
+ end
612
+
613
+ context "when provided a single range" do
614
+
615
+ let(:selection) do
616
+ query.between(field: 1..10)
617
+ end
618
+
619
+ it "adds the $gte and $lte selectors" do
620
+ expect(selection.selector).to eq({
621
+ "field" => { "$gte" => 1, "$lte" => 10 }
622
+ })
623
+ end
624
+
625
+ it "returns a cloned query" do
626
+ expect(selection).to_not equal(query)
627
+ end
628
+ end
629
+
630
+ context "when provided multiple ranges" do
631
+
632
+ context "when the ranges are on different fields" do
633
+
634
+ let(:selection) do
635
+ query.between(field: 1..10, key: 5..7)
636
+ end
637
+
638
+ it "adds the $gte and $lte selectors" do
639
+ expect(selection.selector).to eq({
640
+ "field" => { "$gte" => 1, "$lte" => 10 },
641
+ "key" => { "$gte" => 5, "$lte" => 7 }
642
+ })
643
+ end
644
+
645
+ it "returns a cloned query" do
646
+ expect(selection).to_not equal(query)
647
+ end
648
+ end
649
+ end
650
+ end
651
+
652
+ describe "#elem_match" do
653
+
654
+ context "when provided no criterion" do
655
+
656
+ let(:selection) do
657
+ query.elem_match
658
+ end
659
+
660
+ it "does not add any criterion" do
661
+ expect(selection.selector).to eq({})
662
+ end
663
+
664
+ it "returns the query" do
665
+ expect(selection).to eq(query)
666
+ end
667
+
668
+ it "returns a cloned query" do
669
+ expect(selection).to_not equal(query)
670
+ end
671
+ end
672
+
673
+ context "when provided nil" do
674
+
675
+ let(:selection) do
676
+ query.elem_match(nil)
677
+ end
678
+
679
+ it "does not add any criterion" do
680
+ expect(selection.selector).to eq({})
681
+ end
682
+
683
+ it "returns the query" do
684
+ expect(selection).to eq(query)
685
+ end
686
+
687
+ it "returns a cloned query" do
688
+ expect(selection).to_not equal(query)
689
+ end
690
+ end
691
+
692
+ context "when provided a criterion" do
693
+
694
+ context "when there are no nested complex keys" do
695
+
696
+ let(:selection) do
697
+ query.elem_match(users: { name: "value" })
698
+ end
699
+
700
+ it "adds the $elemMatch expression" do
701
+ expect(selection.selector).to eq({
702
+ "users" => { "$elemMatch" => { name: "value" }}
703
+ })
704
+ end
705
+
706
+ it "returns a cloned query" do
707
+ expect(selection).to_not equal(query)
708
+ end
709
+ end
710
+
711
+ context "when there are nested complex keys" do
712
+
713
+ let(:time) do
714
+ Time.now
715
+ end
716
+
717
+ let(:selection) do
718
+ query.elem_match(users: { :time.gt => time })
719
+ end
720
+
721
+ it "adds the $elemMatch expression" do
722
+ expect(selection.selector).to eq({
723
+ "users" => { "$elemMatch" => { "time" => { "$gt" => time }}}
724
+ })
725
+ end
726
+
727
+ it "returns a cloned query" do
728
+ expect(selection).to_not equal(query)
729
+ end
730
+ end
731
+ end
732
+
733
+ context "when providing multiple criteria" do
734
+
735
+ context "when the fields differ" do
736
+
737
+ let(:selection) do
738
+ query.elem_match(
739
+ users: { name: "value" },
740
+ comments: { text: "value" }
741
+ )
742
+ end
743
+
744
+ it "adds the $elemMatch expression" do
745
+ expect(selection.selector).to eq({
746
+ "users" => { "$elemMatch" => { name: "value" }},
747
+ "comments" => { "$elemMatch" => { text: "value" }}
748
+ })
749
+ end
750
+
751
+ it "returns a cloned query" do
752
+ expect(selection).to_not equal(query)
753
+ end
754
+ end
755
+ end
756
+
757
+ context "when chaining multiple criteria" do
758
+
759
+ context "when the fields differ" do
760
+
761
+ let(:selection) do
762
+ query.
763
+ elem_match(users: { name: "value" }).
764
+ elem_match(comments: { text: "value" })
765
+ end
766
+
767
+ it "adds the $elemMatch expression" do
768
+ expect(selection.selector).to eq({
769
+ "users" => { "$elemMatch" => { name: "value" }},
770
+ "comments" => { "$elemMatch" => { text: "value" }}
771
+ })
772
+ end
773
+
774
+ it "returns a cloned query" do
775
+ expect(selection).to_not equal(query)
776
+ end
777
+ end
778
+
779
+ context "when the fields are the same" do
780
+
781
+ let(:selection) do
782
+ query.
783
+ elem_match(users: { name: "value" }).
784
+ elem_match(users: { state: "new" })
785
+ end
786
+
787
+ it "overrides the $elemMatch expression" do
788
+ expect(selection.selector).to eq({
789
+ "users" => { "$elemMatch" => { state: "new" }}
790
+ })
791
+ end
792
+
793
+ it "returns a cloned query" do
794
+ expect(selection).to_not equal(query)
795
+ end
796
+ end
797
+ end
798
+ end
799
+
800
+ describe "#exists" do
801
+
802
+ context "when provided no criterion" do
803
+
804
+ let(:selection) do
805
+ query.exists
806
+ end
807
+
808
+ it "does not add any criterion" do
809
+ expect(selection.selector).to eq({})
810
+ end
811
+
812
+ it "returns the query" do
813
+ expect(selection).to eq(query)
814
+ end
815
+
816
+ it "returns a cloned query" do
817
+ expect(selection).to_not equal(query)
818
+ end
819
+ end
820
+
821
+ context "when provided nil" do
822
+
823
+ let(:selection) do
824
+ query.exists(nil)
825
+ end
826
+
827
+ it "does not add any criterion" do
828
+ expect(selection.selector).to eq({})
829
+ end
830
+
831
+ it "returns the query" do
832
+ expect(selection).to eq(query)
833
+ end
834
+
835
+ it "returns a cloned query" do
836
+ expect(selection).to_not equal(query)
837
+ end
838
+ end
839
+
840
+ context "when provided a criterion" do
841
+
842
+ context "when provided a boolean" do
843
+
844
+ let(:selection) do
845
+ query.exists(users: true)
846
+ end
847
+
848
+ it "adds the $exists expression" do
849
+ expect(selection.selector).to eq({
850
+ "users" => { "$exists" => true }
851
+ })
852
+ end
853
+
854
+ it "returns a cloned query" do
855
+ expect(selection).to_not equal(query)
856
+ end
857
+ end
858
+
859
+ context "when provided a string" do
860
+
861
+ let(:selection) do
862
+ query.exists(users: "yes")
863
+ end
864
+
865
+ it "adds the $exists expression" do
866
+ expect(selection.selector).to eq({
867
+ "users" => { "$exists" => true }
868
+ })
869
+ end
870
+
871
+ it "returns a cloned query" do
872
+ expect(selection).to_not equal(query)
873
+ end
874
+ end
875
+ end
876
+
877
+ context "when providing multiple criteria" do
878
+
879
+ context "when the fields differ" do
880
+
881
+ context "when providing boolean values" do
882
+
883
+ let(:selection) do
884
+ query.exists(
885
+ users: true,
886
+ comments: true
887
+ )
888
+ end
889
+
890
+ it "adds the $exists expression" do
891
+ expect(selection.selector).to eq({
892
+ "users" => { "$exists" => true },
893
+ "comments" => { "$exists" => true }
894
+ })
895
+ end
896
+
897
+ it "returns a cloned query" do
898
+ expect(selection).to_not equal(query)
899
+ end
900
+ end
901
+
902
+ context "when providing string values" do
903
+
904
+ let(:selection) do
905
+ query.exists(
906
+ users: "y",
907
+ comments: "true"
908
+ )
909
+ end
910
+
911
+ it "adds the $exists expression" do
912
+ expect(selection.selector).to eq({
913
+ "users" => { "$exists" => true },
914
+ "comments" => { "$exists" => true }
915
+ })
916
+ end
917
+
918
+ it "returns a cloned query" do
919
+ expect(selection).to_not equal(query)
920
+ end
921
+ end
922
+ end
923
+ end
924
+
925
+ context "when chaining multiple criteria" do
926
+
927
+ context "when the fields differ" do
928
+
929
+ let(:selection) do
930
+ query.
931
+ exists(users: true).
932
+ exists(comments: true)
933
+ end
934
+
935
+ it "adds the $exists expression" do
936
+ expect(selection.selector).to eq({
937
+ "users" => { "$exists" => true },
938
+ "comments" => { "$exists" => true }
939
+ })
940
+ end
941
+
942
+ it "returns a cloned query" do
943
+ expect(selection).to_not equal(query)
944
+ end
945
+ end
946
+ end
947
+ end
948
+
949
+ describe "#geo_spacial" do
950
+
951
+ context "when provided no criterion" do
952
+
953
+ let(:selection) do
954
+ query.geo_spacial
955
+ end
956
+
957
+ it "does not add any criterion" do
958
+ expect(selection.selector).to be_empty
959
+ end
960
+
961
+ it "returns the query" do
962
+ expect(selection).to eq(query)
963
+ end
964
+
965
+ it_behaves_like "a cloning selection"
966
+ end
967
+
968
+ context "when provided nil" do
969
+
970
+ let(:selection) do
971
+ query.geo_spacial(nil)
972
+ end
973
+
974
+ it "does not add any criterion" do
975
+ expect(selection.selector).to be_empty
976
+ end
977
+
978
+ it "returns the query" do
979
+ expect(selection).to eq(query)
980
+ end
981
+
982
+ it_behaves_like "a cloning selection"
983
+ end
984
+
985
+ context "when provided a criterion" do
986
+
987
+ context "when the geometry is a point intersection" do
988
+
989
+ let(:selection) do
990
+ query.geo_spacial(:location.intersects_point => [ 1, 10 ])
991
+ end
992
+
993
+ it "adds the $geoIntersects expression" do
994
+ expect(selection.selector).to eq({
995
+ "location" => {
996
+ "$geoIntersects" => {
997
+ "$geometry" => {
998
+ "type" => "Point",
999
+ "coordinates" => [ 1, 10 ]
1000
+ }
1001
+ }
1002
+ }
1003
+ })
1004
+ end
1005
+
1006
+ it_behaves_like "a cloning selection"
1007
+ end
1008
+
1009
+ context "when the geometry is a line intersection" do
1010
+
1011
+ let(:selection) do
1012
+ query.geo_spacial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
1013
+ end
1014
+
1015
+ it "adds the $geoIntersects expression" do
1016
+ expect(selection.selector).to eq({
1017
+ "location" => {
1018
+ "$geoIntersects" => {
1019
+ "$geometry" => {
1020
+ "type" => "LineString",
1021
+ "coordinates" => [[ 1, 10 ], [ 2, 10 ]]
1022
+ }
1023
+ }
1024
+ }
1025
+ })
1026
+ end
1027
+
1028
+ it_behaves_like "a cloning selection"
1029
+ end
1030
+
1031
+ context "when the geometry is a polygon intersection" do
1032
+
1033
+ let(:selection) do
1034
+ query.geo_spacial(
1035
+ :location.intersects_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1036
+ )
1037
+ end
1038
+
1039
+ it "adds the $geoIntersects expression" do
1040
+ expect(selection.selector).to eq({
1041
+ "location" => {
1042
+ "$geoIntersects" => {
1043
+ "$geometry" => {
1044
+ "type" => "Polygon",
1045
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1046
+ }
1047
+ }
1048
+ }
1049
+ })
1050
+ end
1051
+
1052
+ it_behaves_like "a cloning selection"
1053
+ end
1054
+
1055
+ context "when the geometry is within a polygon" do
1056
+
1057
+ let(:selection) do
1058
+ query.geo_spacial(
1059
+ :location.within_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1060
+ )
1061
+ end
1062
+
1063
+ it "adds the $geoIntersects expression" do
1064
+ expect(selection.selector).to eq({
1065
+ "location" => {
1066
+ "$geoWithin" => {
1067
+ "$geometry" => {
1068
+ "type" => "Polygon",
1069
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1070
+ }
1071
+ }
1072
+ }
1073
+ })
1074
+ end
1075
+
1076
+ context "when used with the $box operator ($geoWithin query) " do
1077
+ let(:selection) do
1078
+ query.geo_spacial(
1079
+ :location.within_box => [[ 1, 10 ], [ 2, 10 ]]
1080
+ )
1081
+ end
1082
+
1083
+ it "adds the $geoIntersects expression" do
1084
+ expect(selection.selector).to eq({
1085
+ "location" => {
1086
+ "$geoWithin" => {
1087
+ "$box" => [
1088
+ [ 1, 10 ], [ 2, 10 ]
1089
+ ]
1090
+ }
1091
+ }
1092
+ })
1093
+ end
1094
+ end
1095
+
1096
+ it_behaves_like "a cloning selection"
1097
+ end
1098
+ end
1099
+ end
1100
+
1101
+ describe "#gt" do
1102
+
1103
+ context "when provided no criterion" do
1104
+
1105
+ let(:selection) do
1106
+ query.gt
1107
+ end
1108
+
1109
+ it "does not add any criterion" do
1110
+ expect(selection.selector).to eq({})
1111
+ end
1112
+
1113
+ it "returns the query" do
1114
+ expect(selection).to eq(query)
1115
+ end
1116
+
1117
+ it "returns a cloned query" do
1118
+ expect(selection).to_not equal(query)
1119
+ end
1120
+ end
1121
+
1122
+ context "when provided nil" do
1123
+
1124
+ let(:selection) do
1125
+ query.gt(nil)
1126
+ end
1127
+
1128
+ it "does not add any criterion" do
1129
+ expect(selection.selector).to eq({})
1130
+ end
1131
+
1132
+ it "returns the query" do
1133
+ expect(selection).to eq(query)
1134
+ end
1135
+
1136
+ it "returns a cloned query" do
1137
+ expect(selection).to_not equal(query)
1138
+ end
1139
+ end
1140
+
1141
+ context "when provided a single criterion" do
1142
+
1143
+ let(:selection) do
1144
+ query.gt(field: 10)
1145
+ end
1146
+
1147
+ it "adds the $gt selector" do
1148
+ expect(selection.selector).to eq({
1149
+ "field" => { "$gt" => 10 }
1150
+ })
1151
+ end
1152
+
1153
+ it "returns a cloned query" do
1154
+ expect(selection).to_not equal(query)
1155
+ end
1156
+ end
1157
+
1158
+ context "when provided multiple criterion" do
1159
+
1160
+ context "when the criterion are for different fields" do
1161
+
1162
+ let(:selection) do
1163
+ query.gt(first: 10, second: 15)
1164
+ end
1165
+
1166
+ it "adds the $gt selectors" do
1167
+ expect(selection.selector).to eq({
1168
+ "first" => { "$gt" => 10 },
1169
+ "second" => { "$gt" => 15 }
1170
+ })
1171
+ end
1172
+
1173
+ it "returns a cloned query" do
1174
+ expect(selection).to_not equal(query)
1175
+ end
1176
+ end
1177
+ end
1178
+
1179
+ context "when chaining the criterion" do
1180
+
1181
+ context "when the criterion are for different fields" do
1182
+
1183
+ let(:selection) do
1184
+ query.gt(first: 10).gt(second: 15)
1185
+ end
1186
+
1187
+ it "adds the $gt selectors" do
1188
+ expect(selection.selector).to eq({
1189
+ "first" => { "$gt" => 10 },
1190
+ "second" => { "$gt" => 15 }
1191
+ })
1192
+ end
1193
+
1194
+ it "returns a cloned query" do
1195
+ expect(selection).to_not equal(query)
1196
+ end
1197
+ end
1198
+
1199
+ context "when the criterion are on the same field" do
1200
+
1201
+ let(:selection) do
1202
+ query.gt(first: 10).gt(first: 15)
1203
+ end
1204
+
1205
+ it "overwrites the first $gt selector" do
1206
+ expect(selection.selector).to eq({
1207
+ "first" => { "$gt" => 15 }
1208
+ })
1209
+ end
1210
+
1211
+ it "returns a cloned query" do
1212
+ expect(selection).to_not equal(query)
1213
+ end
1214
+ end
1215
+ end
1216
+ end
1217
+
1218
+ describe "#gte" do
1219
+
1220
+ context "when provided no criterion" do
1221
+
1222
+ let(:selection) do
1223
+ query.gte
1224
+ end
1225
+
1226
+ it "does not add any criterion" do
1227
+ expect(selection.selector).to eq({})
1228
+ end
1229
+
1230
+ it "returns the query" do
1231
+ expect(selection).to eq(query)
1232
+ end
1233
+
1234
+ it "returns a cloned query" do
1235
+ expect(selection).to_not equal(query)
1236
+ end
1237
+ end
1238
+
1239
+ context "when provided nil" do
1240
+
1241
+ let(:selection) do
1242
+ query.gte(nil)
1243
+ end
1244
+
1245
+ it "does not add any criterion" do
1246
+ expect(selection.selector).to eq({})
1247
+ end
1248
+
1249
+ it "returns the query" do
1250
+ expect(selection).to eq(query)
1251
+ end
1252
+
1253
+ it "returns a cloned query" do
1254
+ expect(selection).to_not equal(query)
1255
+ end
1256
+ end
1257
+
1258
+ context "when provided a single criterion" do
1259
+
1260
+ let(:selection) do
1261
+ query.gte(field: 10)
1262
+ end
1263
+
1264
+ it "adds the $gte selector" do
1265
+ expect(selection.selector).to eq({
1266
+ "field" => { "$gte" => 10 }
1267
+ })
1268
+ end
1269
+
1270
+ it "returns a cloned query" do
1271
+ expect(selection).to_not equal(query)
1272
+ end
1273
+ end
1274
+
1275
+ context "when provided multiple criterion" do
1276
+
1277
+ context "when the criterion are for different fields" do
1278
+
1279
+ let(:selection) do
1280
+ query.gte(first: 10, second: 15)
1281
+ end
1282
+
1283
+ it "adds the $gte selectors" do
1284
+ expect(selection.selector).to eq({
1285
+ "first" => { "$gte" => 10 },
1286
+ "second" => { "$gte" => 15 }
1287
+ })
1288
+ end
1289
+
1290
+ it "returns a cloned query" do
1291
+ expect(selection).to_not equal(query)
1292
+ end
1293
+ end
1294
+ end
1295
+
1296
+ context "when chaining the criterion" do
1297
+
1298
+ context "when the criterion are for different fields" do
1299
+
1300
+ let(:selection) do
1301
+ query.gte(first: 10).gte(second: 15)
1302
+ end
1303
+
1304
+ it "adds the $gte selectors" do
1305
+ expect(selection.selector).to eq({
1306
+ "first" => { "$gte" => 10 },
1307
+ "second" => { "$gte" => 15 }
1308
+ })
1309
+ end
1310
+
1311
+ it "returns a cloned query" do
1312
+ expect(selection).to_not equal(query)
1313
+ end
1314
+ end
1315
+
1316
+ context "when the criterion are on the same field" do
1317
+
1318
+ let(:selection) do
1319
+ query.gte(first: 10).gte(first: 15)
1320
+ end
1321
+
1322
+ it "overwrites the first $gte selector" do
1323
+ expect(selection.selector).to eq({
1324
+ "first" => { "$gte" => 15 }
1325
+ })
1326
+ end
1327
+
1328
+ it "returns a cloned query" do
1329
+ expect(selection).to_not equal(query)
1330
+ end
1331
+ end
1332
+ end
1333
+ end
1334
+
1335
+ describe "#in" do
1336
+
1337
+ context "when provided no criterion" do
1338
+
1339
+ let(:selection) do
1340
+ query.in
1341
+ end
1342
+
1343
+ it "does not add any criterion" do
1344
+ expect(selection.selector).to eq({})
1345
+ end
1346
+
1347
+ it "returns the query" do
1348
+ expect(selection).to eq(query)
1349
+ end
1350
+
1351
+ it "returns a cloned query" do
1352
+ expect(selection).to_not equal(query)
1353
+ end
1354
+ end
1355
+
1356
+ context "when provided nil" do
1357
+
1358
+ let(:selection) do
1359
+ query.in(nil)
1360
+ end
1361
+
1362
+ it "does not add any criterion" do
1363
+ expect(selection.selector).to eq({})
1364
+ end
1365
+
1366
+ it "returns the query" do
1367
+ expect(selection).to eq(query)
1368
+ end
1369
+
1370
+ it "returns a cloned query" do
1371
+ expect(selection).to_not equal(query)
1372
+ end
1373
+ end
1374
+
1375
+ context "when provided a single criterion" do
1376
+
1377
+ context "when providing an array" do
1378
+
1379
+ let(:selection) do
1380
+ query.in(field: [ 1, 2 ])
1381
+ end
1382
+
1383
+ it "adds the $in selector" do
1384
+ expect(selection.selector).to eq({
1385
+ "field" => { "$in" => [ 1, 2 ] }
1386
+ })
1387
+ end
1388
+
1389
+ it "returns a cloned query" do
1390
+ expect(selection).to_not equal(query)
1391
+ end
1392
+ end
1393
+
1394
+ context "when providing a range" do
1395
+
1396
+ let(:selection) do
1397
+ query.in(field: 1..3)
1398
+ end
1399
+
1400
+ it "adds the $in selector with converted range" do
1401
+ expect(selection.selector).to eq({
1402
+ "field" => { "$in" => [ 1, 2, 3 ] }
1403
+ })
1404
+ end
1405
+
1406
+ it "returns a cloned query" do
1407
+ expect(selection).to_not equal(query)
1408
+ end
1409
+ end
1410
+
1411
+ context "when providing a single value" do
1412
+
1413
+ let(:selection) do
1414
+ query.in(field: 1)
1415
+ end
1416
+
1417
+ it "adds the $in selector with wrapped value" do
1418
+ expect(selection.selector).to eq({
1419
+ "field" => { "$in" => [ 1 ] }
1420
+ })
1421
+ end
1422
+
1423
+ it "returns a cloned query" do
1424
+ expect(selection).to_not equal(query)
1425
+ end
1426
+ end
1427
+ end
1428
+
1429
+ context "when provided multiple criterion" do
1430
+
1431
+ context "when the criterion are for different fields" do
1432
+
1433
+ let(:selection) do
1434
+ query.in(first: [ 1, 2 ], second: 3..4)
1435
+ end
1436
+
1437
+ it "adds the $in selectors" do
1438
+ expect(selection.selector).to eq({
1439
+ "first" => { "$in" => [ 1, 2 ] },
1440
+ "second" => { "$in" => [ 3, 4 ] }
1441
+ })
1442
+ end
1443
+
1444
+ it "returns a cloned query" do
1445
+ expect(selection).to_not equal(query)
1446
+ end
1447
+ end
1448
+ end
1449
+
1450
+ context "when chaining the criterion" do
1451
+
1452
+ context "when the criterion are for different fields" do
1453
+
1454
+ let(:selection) do
1455
+ query.in(first: [ 1, 2 ]).in(second: [ 3, 4 ])
1456
+ end
1457
+
1458
+ it "adds the $in selectors" do
1459
+ expect(selection.selector).to eq({
1460
+ "first" => { "$in" => [ 1, 2 ] },
1461
+ "second" => { "$in" => [ 3, 4 ] }
1462
+ })
1463
+ end
1464
+
1465
+ it "returns a cloned query" do
1466
+ expect(selection).to_not equal(query)
1467
+ end
1468
+ end
1469
+
1470
+ context "when the criterion are on the same field" do
1471
+
1472
+ context "when the strategy is the default (intersection)" do
1473
+
1474
+ let(:selection) do
1475
+ query.in(first: [ 1, 2 ].freeze).in(first: [ 2, 3 ])
1476
+ end
1477
+
1478
+ it "intersects the $in selectors" do
1479
+ expect(selection.selector).to eq({
1480
+ "first" => { "$in" => [ 2 ] }
1481
+ })
1482
+ end
1483
+
1484
+ it "returns a cloned query" do
1485
+ expect(selection).to_not equal(query)
1486
+ end
1487
+ end
1488
+
1489
+ context 'when the field is aliased' do
1490
+
1491
+ before(:all) do
1492
+ class TestModel
1493
+ include Mongoid::Document
1494
+ end
1495
+ end
1496
+
1497
+ after(:all) do
1498
+ Object.send(:remove_const, :TestModel)
1499
+ end
1500
+
1501
+ let(:bson_object_id) do
1502
+ BSON::ObjectId.new
1503
+ end
1504
+
1505
+ let(:selection) do
1506
+ TestModel.in(id: [bson_object_id.to_s]).in(id: [bson_object_id.to_s])
1507
+ end
1508
+
1509
+ it "intersects the $in selectors" do
1510
+ expect(selection.selector).to eq("_id" => { "$in" => [ bson_object_id ] })
1511
+ end
1512
+
1513
+ it "returns a cloned query" do
1514
+ expect(selection).to_not equal(query)
1515
+ end
1516
+ end
1517
+
1518
+ context "when the stretegy is intersect" do
1519
+
1520
+ let(:selection) do
1521
+ query.in(first: [ 1, 2 ]).intersect.in(first: [ 2, 3 ])
1522
+ end
1523
+
1524
+ it "intersects the $in selectors" do
1525
+ expect(selection.selector).to eq({
1526
+ "first" => { "$in" => [ 2 ] }
1527
+ })
1528
+ end
1529
+
1530
+ it "returns a cloned query" do
1531
+ expect(selection).to_not equal(query)
1532
+ end
1533
+ end
1534
+
1535
+ context "when the strategy is override" do
1536
+
1537
+ let(:selection) do
1538
+ query.in(first: [ 1, 2 ]).override.in(first: [ 3, 4 ])
1539
+ end
1540
+
1541
+ it "overwrites the first $in selector" do
1542
+ expect(selection.selector).to eq({
1543
+ "first" => { "$in" => [ 3, 4 ] }
1544
+ })
1545
+ end
1546
+
1547
+ it "returns a cloned query" do
1548
+ expect(selection).to_not equal(query)
1549
+ end
1550
+ end
1551
+
1552
+ context "when the strategy is union" do
1553
+
1554
+ let(:selection) do
1555
+ query.in(first: [ 1, 2 ]).union.in(first: [ 3, 4 ])
1556
+ end
1557
+
1558
+ it "unions the $in selectors" do
1559
+ expect(selection.selector).to eq({
1560
+ "first" => { "$in" => [ 1, 2, 3, 4 ] }
1561
+ })
1562
+ end
1563
+
1564
+ it "returns a cloned query" do
1565
+ expect(selection).to_not equal(query)
1566
+ end
1567
+ end
1568
+ end
1569
+ end
1570
+ end
1571
+
1572
+ describe "#lt" do
1573
+
1574
+ context "when provided no criterion" do
1575
+
1576
+ let(:selection) do
1577
+ query.lt
1578
+ end
1579
+
1580
+ it "does not add any criterion" do
1581
+ expect(selection.selector).to eq({})
1582
+ end
1583
+
1584
+ it "returns the query" do
1585
+ expect(selection).to eq(query)
1586
+ end
1587
+
1588
+ it "returns a cloned query" do
1589
+ expect(selection).to_not equal(query)
1590
+ end
1591
+ end
1592
+
1593
+ context "when provided nil" do
1594
+
1595
+ let(:selection) do
1596
+ query.lt(nil)
1597
+ end
1598
+
1599
+ it "does not add any criterion" do
1600
+ expect(selection.selector).to eq({})
1601
+ end
1602
+
1603
+ it "returns the query" do
1604
+ expect(selection).to eq(query)
1605
+ end
1606
+
1607
+ it "returns a cloned query" do
1608
+ expect(selection).to_not equal(query)
1609
+ end
1610
+ end
1611
+
1612
+ context "when provided a single criterion" do
1613
+
1614
+ let(:selection) do
1615
+ query.lt(field: 10)
1616
+ end
1617
+
1618
+ it "adds the $lt selector" do
1619
+ expect(selection.selector).to eq({
1620
+ "field" => { "$lt" => 10 }
1621
+ })
1622
+ end
1623
+
1624
+ it "returns a cloned query" do
1625
+ expect(selection).to_not equal(query)
1626
+ end
1627
+ end
1628
+
1629
+ context "when provided multiple criterion" do
1630
+
1631
+ context "when the criterion are for different fields" do
1632
+
1633
+ let(:selection) do
1634
+ query.lt(first: 10, second: 15)
1635
+ end
1636
+
1637
+ it "adds the $lt selectors" do
1638
+ expect(selection.selector).to eq({
1639
+ "first" => { "$lt" => 10 },
1640
+ "second" => { "$lt" => 15 }
1641
+ })
1642
+ end
1643
+
1644
+ it "returns a cloned query" do
1645
+ expect(selection).to_not equal(query)
1646
+ end
1647
+ end
1648
+ end
1649
+
1650
+ context "when chaining the criterion" do
1651
+
1652
+ context "when the criterion are for different fields" do
1653
+
1654
+ let(:selection) do
1655
+ query.lt(first: 10).lt(second: 15)
1656
+ end
1657
+
1658
+ it "adds the $lt selectors" do
1659
+ expect(selection.selector).to eq({
1660
+ "first" => { "$lt" => 10 },
1661
+ "second" => { "$lt" => 15 }
1662
+ })
1663
+ end
1664
+
1665
+ it "returns a cloned query" do
1666
+ expect(selection).to_not equal(query)
1667
+ end
1668
+ end
1669
+
1670
+ context "when the criterion are on the same field" do
1671
+
1672
+ let(:selection) do
1673
+ query.lt(first: 10).lt(first: 15)
1674
+ end
1675
+
1676
+ it "overwrites the first $lt selector" do
1677
+ expect(selection.selector).to eq({
1678
+ "first" => { "$lt" => 15 }
1679
+ })
1680
+ end
1681
+
1682
+ it "returns a cloned query" do
1683
+ expect(selection).to_not equal(query)
1684
+ end
1685
+ end
1686
+ end
1687
+ end
1688
+
1689
+ describe "#lte" do
1690
+
1691
+ context "when provided no criterion" do
1692
+
1693
+ let(:selection) do
1694
+ query.lte
1695
+ end
1696
+
1697
+ it "does not add any criterion" do
1698
+ expect(selection.selector).to eq({})
1699
+ end
1700
+
1701
+ it "returns the query" do
1702
+ expect(selection).to eq(query)
1703
+ end
1704
+
1705
+ it "returns a cloned query" do
1706
+ expect(selection).to_not equal(query)
1707
+ end
1708
+ end
1709
+
1710
+ context "when provided nil" do
1711
+
1712
+ let(:selection) do
1713
+ query.lte(nil)
1714
+ end
1715
+
1716
+ it "does not add any criterion" do
1717
+ expect(selection.selector).to eq({})
1718
+ end
1719
+
1720
+ it "returns the query" do
1721
+ expect(selection).to eq(query)
1722
+ end
1723
+
1724
+ it "returns a cloned query" do
1725
+ expect(selection).to_not equal(query)
1726
+ end
1727
+ end
1728
+
1729
+ context "when provided a single criterion" do
1730
+
1731
+ let(:selection) do
1732
+ query.lte(field: 10)
1733
+ end
1734
+
1735
+ it "adds the $lte selector" do
1736
+ expect(selection.selector).to eq({
1737
+ "field" => { "$lte" => 10 }
1738
+ })
1739
+ end
1740
+
1741
+ it "returns a cloned query" do
1742
+ expect(selection).to_not equal(query)
1743
+ end
1744
+ end
1745
+
1746
+ context "when provided multiple criterion" do
1747
+
1748
+ context "when the criterion are for different fields" do
1749
+
1750
+ let(:selection) do
1751
+ query.lte(first: 10, second: 15)
1752
+ end
1753
+
1754
+ it "adds the $lte selectors" do
1755
+ expect(selection.selector).to eq({
1756
+ "first" => { "$lte" => 10 },
1757
+ "second" => { "$lte" => 15 }
1758
+ })
1759
+ end
1760
+
1761
+ it "returns a cloned query" do
1762
+ expect(selection).to_not equal(query)
1763
+ end
1764
+ end
1765
+ end
1766
+
1767
+ context "when chaining the criterion" do
1768
+
1769
+ context "when the criterion are for different fields" do
1770
+
1771
+ let(:selection) do
1772
+ query.lte(first: 10).lte(second: 15)
1773
+ end
1774
+
1775
+ it "adds the $lte selectors" do
1776
+ expect(selection.selector).to eq({
1777
+ "first" => { "$lte" => 10 },
1778
+ "second" => { "$lte" => 15 }
1779
+ })
1780
+ end
1781
+
1782
+ it "returns a cloned query" do
1783
+ expect(selection).to_not equal(query)
1784
+ end
1785
+ end
1786
+
1787
+ context "when the criterion are on the same field" do
1788
+
1789
+ let(:selection) do
1790
+ query.lte(first: 10).lte(first: 15)
1791
+ end
1792
+
1793
+ it "overwrites the first $lte selector" do
1794
+ expect(selection.selector).to eq({
1795
+ "first" => { "$lte" => 15 }
1796
+ })
1797
+ end
1798
+
1799
+ it "returns a cloned query" do
1800
+ expect(selection).to_not equal(query)
1801
+ end
1802
+ end
1803
+ end
1804
+ end
1805
+
1806
+ describe "#max_distance" do
1807
+
1808
+ context "when provided no criterion" do
1809
+
1810
+ let(:selection) do
1811
+ query.max_distance
1812
+ end
1813
+
1814
+ it "does not add any criterion" do
1815
+ expect(selection.selector).to eq({})
1816
+ end
1817
+
1818
+ it "returns the query" do
1819
+ expect(selection).to eq(query)
1820
+ end
1821
+
1822
+ it "returns a cloned query" do
1823
+ expect(selection).to_not equal(query)
1824
+ end
1825
+ end
1826
+
1827
+ context "when provided nil" do
1828
+
1829
+ let(:selection) do
1830
+ query.max_distance(nil)
1831
+ end
1832
+
1833
+ it "does not add any criterion" do
1834
+ expect(selection.selector).to eq({})
1835
+ end
1836
+
1837
+ it "returns the query" do
1838
+ expect(selection).to eq(query)
1839
+ end
1840
+
1841
+ it "returns a cloned query" do
1842
+ expect(selection).to_not equal(query)
1843
+ end
1844
+ end
1845
+
1846
+ context "when provided a criterion" do
1847
+
1848
+ context "when a $near criterion exists on the same field" do
1849
+
1850
+ let(:selection) do
1851
+ query.near(location: [ 1, 1 ]).max_distance(location: 50)
1852
+ end
1853
+
1854
+ it "adds the $maxDistance expression" do
1855
+ expect(selection.selector).to eq({
1856
+ "location" => { "$near" => [ 1, 1 ], "$maxDistance" => 50 }
1857
+ })
1858
+ end
1859
+
1860
+ it "returns a cloned query" do
1861
+ expect(selection).to_not equal(query)
1862
+ end
1863
+ end
1864
+ end
1865
+ end
1866
+
1867
+ describe "#mod" do
1868
+
1869
+ context "when provided no criterion" do
1870
+
1871
+ let(:selection) do
1872
+ query.mod
1873
+ end
1874
+
1875
+ it "does not add any criterion" do
1876
+ expect(selection.selector).to eq({})
1877
+ end
1878
+
1879
+ it "returns the query" do
1880
+ expect(selection).to eq(query)
1881
+ end
1882
+
1883
+ it "returns a cloned query" do
1884
+ expect(selection).to_not equal(query)
1885
+ end
1886
+ end
1887
+
1888
+ context "when provided nil" do
1889
+
1890
+ let(:selection) do
1891
+ query.mod(nil)
1892
+ end
1893
+
1894
+ it "does not add any criterion" do
1895
+ expect(selection.selector).to eq({})
1896
+ end
1897
+
1898
+ it "returns the query" do
1899
+ expect(selection).to eq(query)
1900
+ end
1901
+
1902
+ it "returns a cloned query" do
1903
+ expect(selection).to_not equal(query)
1904
+ end
1905
+ end
1906
+
1907
+ context "when provided a criterion" do
1908
+
1909
+ let(:selection) do
1910
+ query.mod(value: [ 10, 1 ])
1911
+ end
1912
+
1913
+ it "adds the $mod expression" do
1914
+ expect(selection.selector).to eq({
1915
+ "value" => { "$mod" => [ 10, 1 ] }
1916
+ })
1917
+ end
1918
+
1919
+ it "returns a cloned query" do
1920
+ expect(selection).to_not equal(query)
1921
+ end
1922
+ end
1923
+
1924
+ context "when providing multiple criteria" do
1925
+
1926
+ context "when the fields differ" do
1927
+
1928
+ let(:selection) do
1929
+ query.mod(
1930
+ value: [ 10, 1 ],
1931
+ comments: [ 10, 1 ]
1932
+ )
1933
+ end
1934
+
1935
+ it "adds the $mod expression" do
1936
+ expect(selection.selector).to eq({
1937
+ "value" => { "$mod" => [ 10, 1 ] },
1938
+ "comments" => { "$mod" => [ 10, 1 ] }
1939
+ })
1940
+ end
1941
+
1942
+ it "returns a cloned query" do
1943
+ expect(selection).to_not equal(query)
1944
+ end
1945
+ end
1946
+ end
1947
+
1948
+ context "when chaining multiple criteria" do
1949
+
1950
+ context "when the fields differ" do
1951
+
1952
+ let(:selection) do
1953
+ query.
1954
+ mod(value: [ 10, 1 ]).
1955
+ mod(result: [ 10, 1 ])
1956
+ end
1957
+
1958
+ it "adds the $mod expression" do
1959
+ expect(selection.selector).to eq({
1960
+ "value" => { "$mod" => [ 10, 1 ] },
1961
+ "result" => { "$mod" => [ 10, 1 ] }
1962
+ })
1963
+ end
1964
+
1965
+ it "returns a cloned query" do
1966
+ expect(selection).to_not equal(query)
1967
+ end
1968
+ end
1969
+ end
1970
+ end
1971
+
1972
+ describe "#ne" do
1973
+
1974
+ context "when provided no criterion" do
1975
+
1976
+ let(:selection) do
1977
+ query.ne
1978
+ end
1979
+
1980
+ it "does not add any criterion" do
1981
+ expect(selection.selector).to eq({})
1982
+ end
1983
+
1984
+ it "returns the query" do
1985
+ expect(selection).to eq(query)
1986
+ end
1987
+
1988
+ it "returns a cloned query" do
1989
+ expect(selection).to_not equal(query)
1990
+ end
1991
+ end
1992
+
1993
+ context "when provided nil" do
1994
+
1995
+ let(:selection) do
1996
+ query.ne(nil)
1997
+ end
1998
+
1999
+ it "does not add any criterion" do
2000
+ expect(selection.selector).to eq({})
2001
+ end
2002
+
2003
+ it "returns the query" do
2004
+ expect(selection).to eq(query)
2005
+ end
2006
+
2007
+ it "returns a cloned query" do
2008
+ expect(selection).to_not equal(query)
2009
+ end
2010
+ end
2011
+
2012
+ context "when provided a criterion" do
2013
+
2014
+ let(:selection) do
2015
+ query.ne(value: 10)
2016
+ end
2017
+
2018
+ it "adds the $ne expression" do
2019
+ expect(selection.selector).to eq({
2020
+ "value" => { "$ne" => 10 }
2021
+ })
2022
+ end
2023
+
2024
+ it "returns a cloned query" do
2025
+ expect(selection).to_not equal(query)
2026
+ end
2027
+ end
2028
+
2029
+ context "when providing multiple criteria" do
2030
+
2031
+ context "when the fields differ" do
2032
+
2033
+ let(:selection) do
2034
+ query.ne(
2035
+ value: 10,
2036
+ comments: 10
2037
+ )
2038
+ end
2039
+
2040
+ it "adds the $ne expression" do
2041
+ expect(selection.selector).to eq({
2042
+ "value" => { "$ne" => 10 },
2043
+ "comments" => { "$ne" => 10 }
2044
+ })
2045
+ end
2046
+
2047
+ it "returns a cloned query" do
2048
+ expect(selection).to_not equal(query)
2049
+ end
2050
+ end
2051
+ end
2052
+
2053
+ context "when chaining multiple criteria" do
2054
+
2055
+ context "when the fields differ" do
2056
+
2057
+ let(:selection) do
2058
+ query.
2059
+ ne(value: 10).
2060
+ ne(result: 10)
2061
+ end
2062
+
2063
+ it "adds the $ne expression" do
2064
+ expect(selection.selector).to eq({
2065
+ "value" => { "$ne" => 10 },
2066
+ "result" => { "$ne" => 10 }
2067
+ })
2068
+ end
2069
+
2070
+ it "returns a cloned query" do
2071
+ expect(selection).to_not equal(query)
2072
+ end
2073
+ end
2074
+ end
2075
+ end
2076
+
2077
+ describe "#near" do
2078
+
2079
+ context "when provided no criterion" do
2080
+
2081
+ let(:selection) do
2082
+ query.near
2083
+ end
2084
+
2085
+ it "does not add any criterion" do
2086
+ expect(selection.selector).to eq({})
2087
+ end
2088
+
2089
+ it "returns the query" do
2090
+ expect(selection).to eq(query)
2091
+ end
2092
+
2093
+ it "returns a cloned query" do
2094
+ expect(selection).to_not equal(query)
2095
+ end
2096
+ end
2097
+
2098
+ context "when provided nil" do
2099
+
2100
+ let(:selection) do
2101
+ query.near(nil)
2102
+ end
2103
+
2104
+ it "does not add any criterion" do
2105
+ expect(selection.selector).to eq({})
2106
+ end
2107
+
2108
+ it "returns the query" do
2109
+ expect(selection).to eq(query)
2110
+ end
2111
+
2112
+ it "returns a cloned query" do
2113
+ expect(selection).to_not equal(query)
2114
+ end
2115
+ end
2116
+
2117
+ context "when provided a criterion" do
2118
+
2119
+ let(:selection) do
2120
+ query.near(location: [ 20, 21 ])
2121
+ end
2122
+
2123
+ it "adds the $near expression" do
2124
+ expect(selection.selector).to eq({
2125
+ "location" => { "$near" => [ 20, 21 ] }
2126
+ })
2127
+ end
2128
+
2129
+ it "returns a cloned query" do
2130
+ expect(selection).to_not equal(query)
2131
+ end
2132
+ end
2133
+
2134
+ context "when providing multiple criteria" do
2135
+
2136
+ context "when the fields differ" do
2137
+
2138
+ let(:selection) do
2139
+ query.near(
2140
+ location: [ 20, 21 ],
2141
+ comments: [ 20, 21 ]
2142
+ )
2143
+ end
2144
+
2145
+ it "adds the $near expression" do
2146
+ expect(selection.selector).to eq({
2147
+ "location" => { "$near" => [ 20, 21 ] },
2148
+ "comments" => { "$near" => [ 20, 21 ] }
2149
+ })
2150
+ end
2151
+
2152
+ it "returns a cloned query" do
2153
+ expect(selection).to_not equal(query)
2154
+ end
2155
+ end
2156
+ end
2157
+
2158
+ context "when chaining multiple criteria" do
2159
+
2160
+ context "when the fields differ" do
2161
+
2162
+ let(:selection) do
2163
+ query.
2164
+ near(location: [ 20, 21 ]).
2165
+ near(comments: [ 20, 21 ])
2166
+ end
2167
+
2168
+ it "adds the $near expression" do
2169
+ expect(selection.selector).to eq({
2170
+ "location" => { "$near" => [ 20, 21 ] },
2171
+ "comments" => { "$near" => [ 20, 21 ] }
2172
+ })
2173
+ end
2174
+
2175
+ it "returns a cloned query" do
2176
+ expect(selection).to_not equal(query)
2177
+ end
2178
+ end
2179
+ end
2180
+ end
2181
+
2182
+ describe "#near_sphere" do
2183
+
2184
+ context "when provided no criterion" do
2185
+
2186
+ let(:selection) do
2187
+ query.near_sphere
2188
+ end
2189
+
2190
+ it "does not add any criterion" do
2191
+ expect(selection.selector).to eq({})
2192
+ end
2193
+
2194
+ it "returns the query" do
2195
+ expect(selection).to eq(query)
2196
+ end
2197
+
2198
+ it "returns a cloned query" do
2199
+ expect(selection).to_not equal(query)
2200
+ end
2201
+ end
2202
+
2203
+ context "when provided nil" do
2204
+
2205
+ let(:selection) do
2206
+ query.near_sphere(nil)
2207
+ end
2208
+
2209
+ it "does not add any criterion" do
2210
+ expect(selection.selector).to eq({})
2211
+ end
2212
+
2213
+ it "returns the query" do
2214
+ expect(selection).to eq(query)
2215
+ end
2216
+
2217
+ it "returns a cloned query" do
2218
+ expect(selection).to_not equal(query)
2219
+ end
2220
+ end
2221
+
2222
+ context "when provided a criterion" do
2223
+
2224
+ let(:selection) do
2225
+ query.near_sphere(location: [ 20, 21 ])
2226
+ end
2227
+
2228
+ it "adds the $nearSphere expression" do
2229
+ expect(selection.selector).to eq({
2230
+ "location" => { "$nearSphere" => [ 20, 21 ] }
2231
+ })
2232
+ end
2233
+
2234
+ it "returns a cloned query" do
2235
+ expect(selection).to_not equal(query)
2236
+ end
2237
+ end
2238
+
2239
+ context "when providing multiple criteria" do
2240
+
2241
+ context "when the fields differ" do
2242
+
2243
+ let(:selection) do
2244
+ query.near_sphere(
2245
+ location: [ 20, 21 ],
2246
+ comments: [ 20, 21 ]
2247
+ )
2248
+ end
2249
+
2250
+ it "adds the $nearSphere expression" do
2251
+ expect(selection.selector).to eq({
2252
+ "location" => { "$nearSphere" => [ 20, 21 ] },
2253
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
2254
+ })
2255
+ end
2256
+
2257
+ it "returns a cloned query" do
2258
+ expect(selection).to_not equal(query)
2259
+ end
2260
+ end
2261
+ end
2262
+
2263
+ context "when chaining multiple criteria" do
2264
+
2265
+ context "when the fields differ" do
2266
+
2267
+ let(:selection) do
2268
+ query.
2269
+ near_sphere(location: [ 20, 21 ]).
2270
+ near_sphere(comments: [ 20, 21 ])
2271
+ end
2272
+
2273
+ it "adds the $nearSphere expression" do
2274
+ expect(selection.selector).to eq({
2275
+ "location" => { "$nearSphere" => [ 20, 21 ] },
2276
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
2277
+ })
2278
+ end
2279
+
2280
+ it "returns a cloned query" do
2281
+ expect(selection).to_not equal(query)
2282
+ end
2283
+ end
2284
+ end
2285
+ end
2286
+
2287
+ describe "#nin" do
2288
+
2289
+ context "when provided no criterion" do
2290
+
2291
+ let(:selection) do
2292
+ query.nin
2293
+ end
2294
+
2295
+ it "does not add any criterion" do
2296
+ expect(selection.selector).to eq({})
2297
+ end
2298
+
2299
+ it "returns the query" do
2300
+ expect(selection).to eq(query)
2301
+ end
2302
+
2303
+ it "returns a cloned query" do
2304
+ expect(selection).to_not equal(query)
2305
+ end
2306
+ end
2307
+
2308
+ context "when provided nil" do
2309
+
2310
+ let(:selection) do
2311
+ query.nin(nil)
2312
+ end
2313
+
2314
+ it "does not add any criterion" do
2315
+ expect(selection.selector).to eq({})
2316
+ end
2317
+
2318
+ it "returns the query" do
2319
+ expect(selection).to eq(query)
2320
+ end
2321
+
2322
+ it "returns a cloned query" do
2323
+ expect(selection).to_not equal(query)
2324
+ end
2325
+ end
2326
+
2327
+ context "when provided a single criterion" do
2328
+
2329
+ context "when providing an array" do
2330
+
2331
+ let(:selection) do
2332
+ query.nin(field: [ 1, 2 ])
2333
+ end
2334
+
2335
+ it "adds the $nin selector" do
2336
+ expect(selection.selector).to eq({
2337
+ "field" => { "$nin" => [ 1, 2 ] }
2338
+ })
2339
+ end
2340
+
2341
+ it "returns a cloned query" do
2342
+ expect(selection).to_not equal(query)
2343
+ end
2344
+ end
2345
+
2346
+ context "when providing a range" do
2347
+
2348
+ let(:selection) do
2349
+ query.nin(field: 1..3)
2350
+ end
2351
+
2352
+ it "adds the $nin selector with converted range" do
2353
+ expect(selection.selector).to eq({
2354
+ "field" => { "$nin" => [ 1, 2, 3 ] }
2355
+ })
2356
+ end
2357
+
2358
+ it "returns a cloned query" do
2359
+ expect(selection).to_not equal(query)
2360
+ end
2361
+ end
2362
+
2363
+ context "when providing a single value" do
2364
+
2365
+ let(:selection) do
2366
+ query.nin(field: 1)
2367
+ end
2368
+
2369
+ it "adds the $nin selector with wrapped value" do
2370
+ expect(selection.selector).to eq({
2371
+ "field" => { "$nin" => [ 1 ] }
2372
+ })
2373
+ end
2374
+
2375
+ it "returns a cloned query" do
2376
+ expect(selection).to_not equal(query)
2377
+ end
2378
+ end
2379
+ end
2380
+
2381
+ context "when unioning on the same field" do
2382
+
2383
+ context "when the field is not aliased" do
2384
+
2385
+ let(:selection) do
2386
+ query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
2387
+ end
2388
+
2389
+ it "unions the selection on the field" do
2390
+ expect(selection.selector).to eq(
2391
+ { "first" => { "$nin" => [ 1, 2, 3, 4 ]}}
2392
+ )
2393
+ end
2394
+ end
2395
+
2396
+ context "when the field is aliased" do
2397
+
2398
+ let(:selection) do
2399
+ query.nin(id: [ 1, 2 ]).union.nin(id: [ 3, 4 ])
2400
+ end
2401
+
2402
+ it "unions the selection on the field" do
2403
+ expect(selection.selector).to eq(
2404
+ { "_id" => { "$nin" => [ 1, 2, 3, 4 ]}}
2405
+ )
2406
+ end
2407
+ end
2408
+ end
2409
+
2410
+ context "when provided multiple criterion" do
2411
+
2412
+ context "when the criterion are for different fields" do
2413
+
2414
+ let(:selection) do
2415
+ query.nin(first: [ 1, 2 ], second: [ 3, 4 ])
2416
+ end
2417
+
2418
+ it "adds the $nin selectors" do
2419
+ expect(selection.selector).to eq({
2420
+ "first" => { "$nin" => [ 1, 2 ] },
2421
+ "second" => { "$nin" => [ 3, 4 ] }
2422
+ })
2423
+ end
2424
+
2425
+ it "returns a cloned query" do
2426
+ expect(selection).to_not equal(query)
2427
+ end
2428
+ end
2429
+ end
2430
+
2431
+ context "when chaninning the criterion" do
2432
+
2433
+ context "when the criterion are for different fields" do
2434
+
2435
+ let(:selection) do
2436
+ query.nin(first: [ 1, 2 ]).nin(second: [ 3, 4 ])
2437
+ end
2438
+
2439
+ it "adds the $nin selectors" do
2440
+ expect(selection.selector).to eq({
2441
+ "first" => { "$nin" => [ 1, 2 ] },
2442
+ "second" => { "$nin" => [ 3, 4 ] }
2443
+ })
2444
+ end
2445
+
2446
+ it "returns a cloned query" do
2447
+ expect(selection).to_not equal(query)
2448
+ end
2449
+ end
2450
+
2451
+ context "when the criterion are on the same field" do
2452
+
2453
+ context "when the stretegy is the default (intersection)" do
2454
+
2455
+ let(:selection) do
2456
+ query.nin(first: [ 1, 2 ]).nin(first: [ 2, 3 ])
2457
+ end
2458
+
2459
+ it "intersects the $nin selectors" do
2460
+ expect(selection.selector).to eq({
2461
+ "first" => { "$nin" => [ 2 ] }
2462
+ })
2463
+ end
2464
+
2465
+ it "returns a cloned query" do
2466
+ expect(selection).to_not equal(query)
2467
+ end
2468
+ end
2469
+
2470
+ context "when the stretegy is intersect" do
2471
+
2472
+ let(:selection) do
2473
+ query.nin(first: [ 1, 2 ]).intersect.nin(first: [ 2, 3 ])
2474
+ end
2475
+
2476
+ it "intersects the $nin selectors" do
2477
+ expect(selection.selector).to eq({
2478
+ "first" => { "$nin" => [ 2 ] }
2479
+ })
2480
+ end
2481
+
2482
+ it "returns a cloned query" do
2483
+ expect(selection).to_not equal(query)
2484
+ end
2485
+ end
2486
+
2487
+ context "when the stretegy is override" do
2488
+
2489
+ let(:selection) do
2490
+ query.nin(first: [ 1, 2 ]).override.nin(first: [ 3, 4 ])
2491
+ end
2492
+
2493
+ it "overwrites the first $nin selector" do
2494
+ expect(selection.selector).to eq({
2495
+ "first" => { "$nin" => [ 3, 4 ] }
2496
+ })
2497
+ end
2498
+
2499
+ it "returns a cloned query" do
2500
+ expect(selection).to_not equal(query)
2501
+ end
2502
+ end
2503
+
2504
+ context "when the stretegy is union" do
2505
+
2506
+ let(:selection) do
2507
+ query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
2508
+ end
2509
+
2510
+ it "unions the $nin selectors" do
2511
+ expect(selection.selector).to eq({
2512
+ "first" => { "$nin" => [ 1, 2, 3, 4 ] }
2513
+ })
2514
+ end
2515
+
2516
+ it "returns a cloned query" do
2517
+ expect(selection).to_not equal(query)
2518
+ end
2519
+ end
2520
+ end
2521
+ end
2522
+ end
2523
+
2524
+ describe "#nor" do
2525
+
2526
+ context "when provided no criterion" do
2527
+
2528
+ let(:selection) do
2529
+ query.nor
2530
+ end
2531
+
2532
+ it "does not add any criterion" do
2533
+ expect(selection.selector).to eq({})
2534
+ end
2535
+
2536
+ it "returns the query" do
2537
+ expect(selection).to eq(query)
2538
+ end
2539
+
2540
+ it "returns a cloned query" do
2541
+ expect(selection).to_not equal(query)
2542
+ end
2543
+ end
2544
+
2545
+ context "when provided nil" do
2546
+
2547
+ let(:selection) do
2548
+ query.nor(nil)
2549
+ end
2550
+
2551
+ it "does not add any criterion" do
2552
+ expect(selection.selector).to eq({})
2553
+ end
2554
+
2555
+ it "returns the query" do
2556
+ expect(selection).to eq(query)
2557
+ end
2558
+
2559
+ it "returns a cloned query" do
2560
+ expect(selection).to_not equal(query)
2561
+ end
2562
+ end
2563
+
2564
+ context "when provided a single criterion" do
2565
+
2566
+ let(:selection) do
2567
+ query.nor(field: [ 1, 2 ])
2568
+ end
2569
+
2570
+ it "adds the $nor selector" do
2571
+ expect(selection.selector).to eq({
2572
+ "$nor" => [{"field" => [ 1, 2 ] }]
2573
+ })
2574
+ end
2575
+
2576
+ it "returns a cloned query" do
2577
+ expect(selection).to_not equal(query)
2578
+ end
2579
+ end
2580
+
2581
+ context "when provided multiple criterion" do
2582
+
2583
+ context "when the criterion are fnor different fields" do
2584
+
2585
+ let(:selection) do
2586
+ query.nor({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
2587
+ end
2588
+
2589
+ it "adds the $nor selector" do
2590
+ expect(selection.selector).to eq({
2591
+ "$nor" => [
2592
+ { "first" => [ 1, 2 ] },
2593
+ { "second" => [ 3, 4 ] }
2594
+ ]
2595
+ })
2596
+ end
2597
+
2598
+ it "returns a cloned query" do
2599
+ expect(selection).to_not equal(query)
2600
+ end
2601
+ end
2602
+
2603
+ context "when the criterion are on the same field" do
2604
+
2605
+ let(:selection) do
2606
+ query.nor({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
2607
+ end
2608
+
2609
+ it "appends both $nor expressions" do
2610
+ expect(selection.selector).to eq({
2611
+ "$nor" => [
2612
+ { "first" => [ 1, 2 ] },
2613
+ { "first" => [ 3, 4 ] }
2614
+ ]
2615
+ })
2616
+ end
2617
+
2618
+ it "returns a cloned query" do
2619
+ expect(selection).to_not equal(query)
2620
+ end
2621
+ end
2622
+ end
2623
+
2624
+ context "when chaining the criterion" do
2625
+
2626
+ context "when the criterion are fnor different fields" do
2627
+
2628
+ let(:selection) do
2629
+ query.nor(first: [ 1, 2 ]).nor(second: [ 3, 4 ])
2630
+ end
2631
+
2632
+ it "adds the $nor selectors" do
2633
+ expect(selection.selector).to eq({
2634
+ "$nor" => [
2635
+ { "first" => [ 1, 2 ] },
2636
+ { "second" => [ 3, 4 ] }
2637
+ ]
2638
+ })
2639
+ end
2640
+
2641
+ it "returns a cloned query" do
2642
+ expect(selection).to_not equal(query)
2643
+ end
2644
+ end
2645
+
2646
+ context "when the criterion are on the same field" do
2647
+
2648
+ let(:selection) do
2649
+ query.nor(first: [ 1, 2 ]).nor(first: [ 3, 4 ])
2650
+ end
2651
+
2652
+ it "appends both $nor expressions" do
2653
+ expect(selection.selector).to eq({
2654
+ "$nor" => [
2655
+ { "first" => [ 1, 2 ] },
2656
+ { "first" => [ 3, 4 ] }
2657
+ ]
2658
+ })
2659
+ end
2660
+
2661
+ it "returns a cloned query" do
2662
+ expect(selection).to_not equal(query)
2663
+ end
2664
+ end
2665
+ end
2666
+ end
2667
+
2668
+ describe "#not" do
2669
+
2670
+ context "when provided no criterion" do
2671
+
2672
+ let(:selection) do
2673
+ query.not
2674
+ end
2675
+
2676
+ it "does not add any criterion" do
2677
+ expect(selection.selector).to eq({})
2678
+ end
2679
+
2680
+ it "returns the query" do
2681
+ expect(selection).to eq(query)
2682
+ end
2683
+
2684
+ it "returns a non cloned query" do
2685
+ expect(selection).to equal(query)
2686
+ end
2687
+
2688
+ context "when the following criteria is a query method" do
2689
+
2690
+ let(:selection) do
2691
+ query.not.all(field: [ 1, 2 ])
2692
+ end
2693
+
2694
+ it "negates the all selection" do
2695
+ expect(selection.selector).to eq(
2696
+ { "field" => { "$not" => { "$all" => [ 1, 2 ] }}}
2697
+ )
2698
+ end
2699
+
2700
+ it "returns a cloned query" do
2701
+ expect(selection).to_not equal(query)
2702
+ end
2703
+
2704
+ it "removes the negation on the clone" do
2705
+ expect(selection).to_not be_negating
2706
+ end
2707
+ end
2708
+
2709
+ context "when the following criteria is a gt method" do
2710
+
2711
+ let(:selection) do
2712
+ query.not.gt(age: 50)
2713
+ end
2714
+
2715
+ it "negates the gt selection" do
2716
+ expect(selection.selector).to eq(
2717
+ { "age" => { "$not" => { "$gt" => 50 }}}
2718
+ )
2719
+ end
2720
+
2721
+ it "returns a coned query" do
2722
+ expect(selection).to_not eq(query)
2723
+ end
2724
+
2725
+ it "removes the negation on the clone" do
2726
+ expect(selection).to_not be_negating
2727
+ end
2728
+ end
2729
+
2730
+ context "when the following criteria is a where" do
2731
+
2732
+ let(:selection) do
2733
+ query.not.where(field: 1, :other.in => [ 1, 2 ])
2734
+ end
2735
+
2736
+ it "negates the selection with an operator" do
2737
+ expect(selection.selector).to eq(
2738
+ { "field" => { "$ne" => 1 }, "other" => { "$not" => { "$in" => [ 1, 2 ] }}}
2739
+ )
2740
+ end
2741
+
2742
+ it "returns a cloned query" do
2743
+ expect(selection).to_not equal(query)
2744
+ end
2745
+
2746
+ it "removes the negation on the clone" do
2747
+ expect(selection).to_not be_negating
2748
+ end
2749
+ end
2750
+
2751
+ context "when the following criteria is a where with a regexp" do
2752
+
2753
+ let(:selection) do
2754
+ query.not.where(field: 1, other: /test/)
2755
+ end
2756
+
2757
+ it "negates the selection with an operator" do
2758
+ expect(selection.selector).to eq(
2759
+ { "field" => { "$ne" => 1 }, "other" => { "$not" => /test/ } }
2760
+ )
2761
+ end
2762
+
2763
+ it "returns a cloned query" do
2764
+ expect(selection).to_not equal(query)
2765
+ end
2766
+
2767
+ it "removes the negation on the clone" do
2768
+ expect(selection).to_not be_negating
2769
+ end
2770
+
2771
+ end
2772
+ end
2773
+
2774
+ context "when provided nil" do
2775
+
2776
+ let(:selection) do
2777
+ query.not(nil)
2778
+ end
2779
+
2780
+ it "does not add any criterion" do
2781
+ expect(selection.selector).to eq({})
2782
+ end
2783
+
2784
+ it "returns the query" do
2785
+ expect(selection).to eq(query)
2786
+ end
2787
+
2788
+ it "returns a cloned query" do
2789
+ expect(selection).to_not equal(query)
2790
+ end
2791
+ end
2792
+
2793
+ context "when provided a single criterion" do
2794
+
2795
+ let(:selection) do
2796
+ query.not(field: /test/)
2797
+ end
2798
+
2799
+ it "adds the $not selector" do
2800
+ expect(selection.selector).to eq({
2801
+ "field" => { "$not" => /test/ }
2802
+ })
2803
+ end
2804
+
2805
+ it "returns a cloned query" do
2806
+ expect(selection).to_not equal(query)
2807
+ end
2808
+ end
2809
+
2810
+ context "when provided multiple criterion" do
2811
+
2812
+ context "when the criterion are for different fields" do
2813
+
2814
+ let(:selection) do
2815
+ query.not(first: /1/, second: /2/)
2816
+ end
2817
+
2818
+ it "adds the $not selectors" do
2819
+ expect(selection.selector).to eq({
2820
+ "first" => { "$not" => /1/ },
2821
+ "second" => { "$not" => /2/ }
2822
+ })
2823
+ end
2824
+
2825
+ it "returns a cloned query" do
2826
+ expect(selection).to_not equal(query)
2827
+ end
2828
+ end
2829
+ end
2830
+
2831
+ context "when chaining the criterion" do
2832
+
2833
+ context "when the criterion are for different fields" do
2834
+
2835
+ let(:selection) do
2836
+ query.not(first: /1/).not(second: /2/)
2837
+ end
2838
+
2839
+ it "adds the $not selectors" do
2840
+ expect(selection.selector).to eq({
2841
+ "first" => { "$not" => /1/ },
2842
+ "second" => { "$not" => /2/ }
2843
+ })
2844
+ end
2845
+
2846
+ it "returns a cloned query" do
2847
+ expect(selection).to_not equal(query)
2848
+ end
2849
+ end
2850
+
2851
+ context "when the criterion are on the same field" do
2852
+
2853
+ let(:selection) do
2854
+ query.not(first: /1/).not(first: /2/)
2855
+ end
2856
+
2857
+ it "overwrites the first $not selector" do
2858
+ expect(selection.selector).to eq({
2859
+ "first" => { "$not" => /2/ }
2860
+ })
2861
+ end
2862
+
2863
+ it "returns a cloned query" do
2864
+ expect(selection).to_not equal(query)
2865
+ end
2866
+ end
2867
+
2868
+ context "when the criterion are a double negative" do
2869
+
2870
+ let(:selection) do
2871
+ query.not.where(:first.not => /1/)
2872
+ end
2873
+
2874
+ it "does not double the $not selector" do
2875
+ expect(selection.selector).to eq({
2876
+ "first" => { "$not" => /1/ }
2877
+ })
2878
+ end
2879
+
2880
+ it "returns a cloned query" do
2881
+ expect(selection).to_not equal(query)
2882
+ end
2883
+ end
2884
+ end
2885
+ end
2886
+
2887
+ describe "#or" do
2888
+
2889
+ context "when provided no criterion" do
2890
+
2891
+ let(:selection) do
2892
+ query.or
2893
+ end
2894
+
2895
+ it "does not add any criterion" do
2896
+ expect(selection.selector).to eq({})
2897
+ end
2898
+
2899
+ it "returns the query" do
2900
+ expect(selection).to eq(query)
2901
+ end
2902
+
2903
+ it "returns a cloned query" do
2904
+ expect(selection).to_not equal(query)
2905
+ end
2906
+ end
2907
+
2908
+ context "when provided nil" do
2909
+
2910
+ let(:selection) do
2911
+ query.or(nil)
2912
+ end
2913
+
2914
+ it "does not add any criterion" do
2915
+ expect(selection.selector).to eq({})
2916
+ end
2917
+
2918
+ it "returns the query" do
2919
+ expect(selection).to eq(query)
2920
+ end
2921
+
2922
+ it "returns a cloned query" do
2923
+ expect(selection).to_not equal(query)
2924
+ end
2925
+ end
2926
+
2927
+ context "when provided a single criterion" do
2928
+
2929
+ let(:selection) do
2930
+ query.or(field: [ 1, 2 ])
2931
+ end
2932
+
2933
+ it "adds the $or selector" do
2934
+ expect(selection.selector).to eq({
2935
+ "$or" => [{ "field" => [ 1, 2 ] }]
2936
+ })
2937
+ end
2938
+
2939
+ it "returns a cloned query" do
2940
+ expect(selection).to_not equal(query)
2941
+ end
2942
+ end
2943
+
2944
+ context "when provided multiple criterion" do
2945
+
2946
+ context "when the criterion are for different fields" do
2947
+
2948
+ let(:selection) do
2949
+ query.or({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
2950
+ end
2951
+
2952
+ it "adds the $or selector" do
2953
+ expect(selection.selector).to eq({
2954
+ "$or" => [
2955
+ { "first" => [ 1, 2 ] },
2956
+ { "second" => [ 3, 4 ] }
2957
+ ]
2958
+ })
2959
+ end
2960
+
2961
+ it "returns a cloned query" do
2962
+ expect(selection).to_not equal(query)
2963
+ end
2964
+ end
2965
+
2966
+ context "when a criterion has a selectable key" do
2967
+
2968
+ let(:selection) do
2969
+ query.or({ first: [ 1, 2 ] }, { :second.gt => 3 })
2970
+ end
2971
+
2972
+ it "adds the $or selector" do
2973
+ expect(selection.selector).to eq({
2974
+ "$or" => [
2975
+ { "first" => [ 1, 2 ] },
2976
+ { "second" => { "$gt" => 3 }}
2977
+ ]
2978
+ })
2979
+ end
2980
+
2981
+ it "returns a cloned query" do
2982
+ expect(selection).to_not equal(query)
2983
+ end
2984
+ end
2985
+
2986
+ context "when the criterion has an aliased field" do
2987
+
2988
+ let(:selection) do
2989
+ query.or({ id: 1 })
2990
+ end
2991
+
2992
+ it "adds the $or selector and aliases the field" do
2993
+ expect(selection.selector).to eq({
2994
+ "$or" => [ { "_id" => 1 } ]
2995
+ })
2996
+ end
2997
+
2998
+ it "returns a cloned query" do
2999
+ expect(selection).to_not equal(query)
3000
+ end
3001
+ end
3002
+
3003
+ context "when a criterion is wrapped in an array" do
3004
+
3005
+ let(:selection) do
3006
+ query.or([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
3007
+ end
3008
+
3009
+ it "adds the $or selector" do
3010
+ expect(selection.selector).to eq({
3011
+ "$or" => [
3012
+ { "first" => [ 1, 2 ] },
3013
+ { "second" => { "$gt" => 3 }}
3014
+ ]
3015
+ })
3016
+ end
3017
+
3018
+ it "returns a cloned query" do
3019
+ expect(selection).to_not equal(query)
3020
+ end
3021
+ end
3022
+
3023
+ context "when the criterion are on the same field" do
3024
+
3025
+ let(:selection) do
3026
+ query.or({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
3027
+ end
3028
+
3029
+ it "appends both $or expressions" do
3030
+ expect(selection.selector).to eq({
3031
+ "$or" => [
3032
+ { "first" => [ 1, 2 ] },
3033
+ { "first" => [ 3, 4 ] }
3034
+ ]
3035
+ })
3036
+ end
3037
+
3038
+ it "returns a cloned query" do
3039
+ expect(selection).to_not equal(query)
3040
+ end
3041
+ end
3042
+ end
3043
+
3044
+ context "when chaining the criterion" do
3045
+
3046
+ context "when the criterion are for different fields" do
3047
+
3048
+ let(:selection) do
3049
+ query.or(first: [ 1, 2 ]).or(second: [ 3, 4 ])
3050
+ end
3051
+
3052
+ it "adds the $or selectors" do
3053
+ expect(selection.selector).to eq({
3054
+ "$or" => [
3055
+ { "first" => [ 1, 2 ] },
3056
+ { "second" => [ 3, 4 ] }
3057
+ ]
3058
+ })
3059
+ end
3060
+
3061
+ it "returns a cloned query" do
3062
+ expect(selection).to_not equal(query)
3063
+ end
3064
+ end
3065
+
3066
+ context "when the criterion are on the same field" do
3067
+
3068
+ let(:selection) do
3069
+ query.or(first: [ 1, 2 ]).or(first: [ 3, 4 ])
3070
+ end
3071
+
3072
+ it "appends both $or expressions" do
3073
+ expect(selection.selector).to eq({
3074
+ "$or" => [
3075
+ { "first" => [ 1, 2 ] },
3076
+ { "first" => [ 3, 4 ] }
3077
+ ]
3078
+ })
3079
+ end
3080
+
3081
+ it "returns a cloned query" do
3082
+ expect(selection).to_not equal(query)
3083
+ end
3084
+ end
3085
+ end
3086
+ end
3087
+
3088
+ describe "#with_size" do
3089
+
3090
+ context "when provided no criterion" do
3091
+
3092
+ let(:selection) do
3093
+ query.with_size
3094
+ end
3095
+
3096
+ it "does not add any criterion" do
3097
+ expect(selection.selector).to eq({})
3098
+ end
3099
+
3100
+ it "returns the query" do
3101
+ expect(selection).to eq(query)
3102
+ end
3103
+
3104
+ it "returns a cloned query" do
3105
+ expect(selection).to_not equal(query)
3106
+ end
3107
+ end
3108
+
3109
+ context "when provided nil" do
3110
+
3111
+ let(:selection) do
3112
+ query.with_size(nil)
3113
+ end
3114
+
3115
+ it "does not add any criterion" do
3116
+ expect(selection.selector).to eq({})
3117
+ end
3118
+
3119
+ it "returns the query" do
3120
+ expect(selection).to eq(query)
3121
+ end
3122
+
3123
+ it "returns a cloned query" do
3124
+ expect(selection).to_not equal(query)
3125
+ end
3126
+ end
3127
+
3128
+ context "when provided a single criterion" do
3129
+
3130
+ context "when provided an integer" do
3131
+
3132
+ let(:selection) do
3133
+ query.with_size(field: 10)
3134
+ end
3135
+
3136
+ it "adds the $size selector" do
3137
+ expect(selection.selector).to eq({
3138
+ "field" => { "$size" => 10 }
3139
+ })
3140
+ end
3141
+
3142
+ it "returns a cloned query" do
3143
+ expect(selection).to_not equal(query)
3144
+ end
3145
+ end
3146
+
3147
+ context "when provided a string" do
3148
+
3149
+ let(:selection) do
3150
+ query.with_size(field: "10")
3151
+ end
3152
+
3153
+ it "adds the $size selector with an integer" do
3154
+ expect(selection.selector).to eq({
3155
+ "field" => { "$size" => 10 }
3156
+ })
3157
+ end
3158
+
3159
+ it "returns a cloned query" do
3160
+ expect(selection).to_not equal(query)
3161
+ end
3162
+ end
3163
+ end
3164
+
3165
+ context "when provided multiple criterion" do
3166
+
3167
+ context "when the criterion are for different fields" do
3168
+
3169
+ context "when provided integers" do
3170
+
3171
+ let(:selection) do
3172
+ query.with_size(first: 10, second: 15)
3173
+ end
3174
+
3175
+ it "adds the $size selectors" do
3176
+ expect(selection.selector).to eq({
3177
+ "first" => { "$size" => 10 },
3178
+ "second" => { "$size" => 15 }
3179
+ })
3180
+ end
3181
+
3182
+ it "returns a cloned query" do
3183
+ expect(selection).to_not equal(query)
3184
+ end
3185
+ end
3186
+
3187
+ context "when provided strings" do
3188
+
3189
+ let(:selection) do
3190
+ query.with_size(first: "10", second: "15")
3191
+ end
3192
+
3193
+ it "adds the $size selectors" do
3194
+ expect(selection.selector).to eq({
3195
+ "first" => { "$size" => 10 },
3196
+ "second" => { "$size" => 15 }
3197
+ })
3198
+ end
3199
+
3200
+ it "returns a cloned query" do
3201
+ expect(selection).to_not equal(query)
3202
+ end
3203
+ end
3204
+ end
3205
+ end
3206
+
3207
+ context "when chaining the criterion" do
3208
+
3209
+ context "when the criterion are for different fields" do
3210
+
3211
+ let(:selection) do
3212
+ query.with_size(first: 10).with_size(second: 15)
3213
+ end
3214
+
3215
+ it "adds the $size selectors" do
3216
+ expect(selection.selector).to eq({
3217
+ "first" => { "$size" => 10 },
3218
+ "second" => { "$size" => 15 }
3219
+ })
3220
+ end
3221
+
3222
+ it "returns a cloned query" do
3223
+ expect(selection).to_not equal(query)
3224
+ end
3225
+ end
3226
+
3227
+ context "when the criterion are on the same field" do
3228
+
3229
+ let(:selection) do
3230
+ query.with_size(first: 10).with_size(first: 15)
3231
+ end
3232
+
3233
+ it "overwrites the first $size selector" do
3234
+ expect(selection.selector).to eq({
3235
+ "first" => { "$size" => 15 }
3236
+ })
3237
+ end
3238
+
3239
+ it "returns a cloned query" do
3240
+ expect(selection).to_not equal(query)
3241
+ end
3242
+ end
3243
+ end
3244
+ end
3245
+
3246
+ describe "#type" do
3247
+
3248
+ context "when provided no criterion" do
3249
+
3250
+ let(:selection) do
3251
+ query.with_type
3252
+ end
3253
+
3254
+ it "does not add any criterion" do
3255
+ expect(selection.selector).to eq({})
3256
+ end
3257
+
3258
+ it "returns the query" do
3259
+ expect(selection).to eq(query)
3260
+ end
3261
+
3262
+ it "returns a cloned query" do
3263
+ expect(selection).to_not equal(query)
3264
+ end
3265
+ end
3266
+
3267
+ context "when provided nil" do
3268
+
3269
+ let(:selection) do
3270
+ query.with_type(nil)
3271
+ end
3272
+
3273
+ it "does not add any criterion" do
3274
+ expect(selection.selector).to eq({})
3275
+ end
3276
+
3277
+ it "returns the query" do
3278
+ expect(selection).to eq(query)
3279
+ end
3280
+
3281
+ it "returns a cloned query" do
3282
+ expect(selection).to_not equal(query)
3283
+ end
3284
+ end
3285
+
3286
+ context "when provided a single criterion" do
3287
+
3288
+ context "when provided an integer" do
3289
+
3290
+ let(:selection) do
3291
+ query.with_type(field: 10)
3292
+ end
3293
+
3294
+ it "adds the $type selector" do
3295
+ expect(selection.selector).to eq({
3296
+ "field" => { "$type" => 10 }
3297
+ })
3298
+ end
3299
+
3300
+ it "returns a cloned query" do
3301
+ expect(selection).to_not equal(query)
3302
+ end
3303
+ end
3304
+
3305
+ context "when provided a string" do
3306
+
3307
+ let(:selection) do
3308
+ query.with_type(field: "10")
3309
+ end
3310
+
3311
+ it "adds the $type selector" do
3312
+ expect(selection.selector).to eq({
3313
+ "field" => { "$type" => 10 }
3314
+ })
3315
+ end
3316
+
3317
+ it "returns a cloned query" do
3318
+ expect(selection).to_not equal(query)
3319
+ end
3320
+ end
3321
+ end
3322
+
3323
+ context "when provided multiple criterion" do
3324
+
3325
+ context "when the criterion are for different fields" do
3326
+
3327
+ let(:selection) do
3328
+ query.with_type(first: 10, second: 15)
3329
+ end
3330
+
3331
+ it "adds the $type selectors" do
3332
+ expect(selection.selector).to eq({
3333
+ "first" => { "$type" => 10 },
3334
+ "second" => { "$type" => 15 }
3335
+ })
3336
+ end
3337
+
3338
+ it "returns a cloned query" do
3339
+ expect(selection).to_not equal(query)
3340
+ end
3341
+ end
3342
+ end
3343
+
3344
+ context "when chaining the criterion" do
3345
+
3346
+ context "when the criterion are for different fields" do
3347
+
3348
+ let(:selection) do
3349
+ query.with_type(first: 10).with_type(second: 15)
3350
+ end
3351
+
3352
+ it "adds the $type selectors" do
3353
+ expect(selection.selector).to eq({
3354
+ "first" => { "$type" => 10 },
3355
+ "second" => { "$type" => 15 }
3356
+ })
3357
+ end
3358
+
3359
+ it "returns a cloned query" do
3360
+ expect(selection).to_not equal(query)
3361
+ end
3362
+ end
3363
+
3364
+ context "when the criterion are on the same field" do
3365
+
3366
+ let(:selection) do
3367
+ query.with_type(first: 10).with_type(first: 15)
3368
+ end
3369
+
3370
+ it "overwrites the first $type selector" do
3371
+ expect(selection.selector).to eq({
3372
+ "first" => { "$type" => 15 }
3373
+ })
3374
+ end
3375
+
3376
+ it "returns a cloned query" do
3377
+ expect(selection).to_not equal(query)
3378
+ end
3379
+ end
3380
+ end
3381
+ end
3382
+
3383
+ describe "#text_search" do
3384
+
3385
+ context "when providing a search string" do
3386
+
3387
+ let(:selection) do
3388
+ query.text_search("testing")
3389
+ end
3390
+
3391
+ it "constructs a text search document" do
3392
+ expect(selection.selector).to eq({ '$text' => { '$search' => "testing" }})
3393
+ end
3394
+
3395
+ it "returns the cloned selectable" do
3396
+ expect(selection).to be_a(Mongoid::Criteria::Queryable::Selectable)
3397
+ end
3398
+
3399
+ context "when providing text search options" do
3400
+
3401
+ let(:selection) do
3402
+ query.text_search("essais", { :$language => "fr" })
3403
+ end
3404
+
3405
+ it "constructs a text search document" do
3406
+ expect(selection.selector['$text']['$search']).to eq("essais")
3407
+ end
3408
+
3409
+ it "add the options to the text search document" do
3410
+ expect(selection.selector['$text'][:$language]).to eq("fr")
3411
+ end
3412
+
3413
+ it_behaves_like "a cloning selection"
3414
+ end
3415
+ end
3416
+
3417
+ context 'when given more than once' do
3418
+ let(:selection) do
3419
+ query.text_search("one").text_search('two')
3420
+ end
3421
+
3422
+ # MongoDB server can only handle one text expression at a time,
3423
+ # per https://docs.mongodb.com/manual/reference/operator/query/text/.
3424
+ # Nonetheless we test that the query is built correctly when
3425
+ # a user supplies more than one text condition.
3426
+ it 'merges conditions' do
3427
+ expect(Mongoid.logger).to receive(:warn)
3428
+ expect(selection.selector).to eq('$and' => [
3429
+ {'$text' => {'$search' => 'one'}}
3430
+ ],
3431
+ '$text' => {'$search' => 'two'},
3432
+ )
3433
+ end
3434
+ end
3435
+ end
3436
+
3437
+ describe "#where" do
3438
+
3439
+ context "when provided no criterion" do
3440
+
3441
+ let(:selection) do
3442
+ query.where
3443
+ end
3444
+
3445
+ it "does not add any criterion" do
3446
+ expect(selection.selector).to eq({})
3447
+ end
3448
+
3449
+ it "returns the query" do
3450
+ expect(selection).to eq(query)
3451
+ end
3452
+
3453
+ it "returns a cloned query" do
3454
+ expect(selection).to_not equal(query)
3455
+ end
3456
+ end
3457
+
3458
+ context "when provided nil" do
3459
+
3460
+ let(:selection) do
3461
+ query.where(nil)
3462
+ end
3463
+
3464
+ it "does not add any criterion" do
3465
+ expect(selection.selector).to eq({})
3466
+ end
3467
+
3468
+ it "returns the query" do
3469
+ expect(selection).to eq(query)
3470
+ end
3471
+
3472
+ it "returns a cloned query" do
3473
+ expect(selection).to_not equal(query)
3474
+ end
3475
+ end
3476
+
3477
+ context "when provided a string" do
3478
+
3479
+ let(:selection) do
3480
+ query.where("this.value = 10")
3481
+ end
3482
+
3483
+ it "adds the $where criterion" do
3484
+ expect(selection.selector).to eq({ "$where" => "this.value = 10" })
3485
+ end
3486
+
3487
+ it "returns a cloned query" do
3488
+ expect(selection).to_not equal(query)
3489
+ end
3490
+ end
3491
+
3492
+ context "when provided a single criterion" do
3493
+
3494
+ context "when the value needs no evolution" do
3495
+
3496
+ let(:selection) do
3497
+ query.where(name: "Syd")
3498
+ end
3499
+
3500
+ it "adds the criterion to the selection" do
3501
+ expect(selection.selector).to eq({ "name" => "Syd" })
3502
+ end
3503
+ end
3504
+
3505
+ context "when the value must be evolved" do
3506
+
3507
+ before(:all) do
3508
+ class Document
3509
+ def id
3510
+ 13
3511
+ end
3512
+ def self.evolve(object)
3513
+ object.id
3514
+ end
3515
+ end
3516
+ end
3517
+
3518
+ after(:all) do
3519
+ Object.send(:remove_const, :Document)
3520
+ end
3521
+
3522
+ context "when the key needs evolution" do
3523
+
3524
+ let(:query) do
3525
+ Mongoid::Query.new({ "user" => "user_id" })
3526
+ end
3527
+
3528
+ let(:document) do
3529
+ Document.new
3530
+ end
3531
+
3532
+ let(:selection) do
3533
+ query.where(user: document)
3534
+ end
3535
+
3536
+ it "alters the key and value" do
3537
+ expect(selection.selector).to eq({ "user_id" => document.id })
3538
+ end
3539
+ end
3540
+
3541
+ context 'when the field is a String and the value is a BSON::Regexp::Raw' do
3542
+
3543
+ let(:raw_regexp) do
3544
+ BSON::Regexp::Raw.new('^Em')
3545
+ end
3546
+
3547
+ let(:selection) do
3548
+ Login.where(_id: raw_regexp)
3549
+ end
3550
+
3551
+ it 'does not convert the bson raw regexp object to a String' do
3552
+ expect(selection.selector).to eq({ "_id" => raw_regexp })
3553
+ end
3554
+ end
3555
+ end
3556
+ end
3557
+
3558
+ context "when provided complex criterion" do
3559
+
3560
+ context "when performing an $all" do
3561
+
3562
+ context "when performing a single query" do
3563
+
3564
+ let(:selection) do
3565
+ query.where(:field.all => [ 1, 2 ])
3566
+ end
3567
+
3568
+ it "adds the $all criterion" do
3569
+ expect(selection.selector).to eq({ "field" => { "$all" => [ 1, 2 ] }})
3570
+ end
3571
+
3572
+ it "returns a cloned query" do
3573
+ expect(selection).to_not eq(query)
3574
+ end
3575
+ end
3576
+ end
3577
+
3578
+ context "when performing an $elemMatch" do
3579
+
3580
+ context "when the value is not complex" do
3581
+
3582
+ let(:selection) do
3583
+ query.where(:field.elem_match => { key: 1 })
3584
+ end
3585
+
3586
+ it "adds the $elemMatch criterion" do
3587
+ expect(selection.selector).to eq(
3588
+ { "field" => { "$elemMatch" => { key: 1 } }}
3589
+ )
3590
+ end
3591
+
3592
+ it "returns a cloned query" do
3593
+ expect(selection).to_not eq(query)
3594
+ end
3595
+ end
3596
+
3597
+ context "when the value is complex" do
3598
+
3599
+ let(:selection) do
3600
+ query.where(:field.elem_match => { :key.gt => 1 })
3601
+ end
3602
+
3603
+ it "adds the $elemMatch criterion" do
3604
+ expect(selection.selector).to eq(
3605
+ { "field" => { "$elemMatch" => { "key" => { "$gt" => 1 }}}}
3606
+ )
3607
+ end
3608
+
3609
+ it "returns a cloned query" do
3610
+ expect(selection).to_not eq(query)
3611
+ end
3612
+ end
3613
+ end
3614
+
3615
+ context "when performing an $exists" do
3616
+
3617
+ context "when providing boolean values" do
3618
+
3619
+ let(:selection) do
3620
+ query.where(:field.exists => true)
3621
+ end
3622
+
3623
+ it "adds the $exists criterion" do
3624
+ expect(selection.selector).to eq(
3625
+ { "field" => { "$exists" => true }}
3626
+ )
3627
+ end
3628
+
3629
+ it "returns a cloned query" do
3630
+ expect(selection).to_not eq(query)
3631
+ end
3632
+ end
3633
+
3634
+ context "when providing string values" do
3635
+
3636
+ let(:selection) do
3637
+ query.where(:field.exists => "t")
3638
+ end
3639
+
3640
+ it "adds the $exists criterion" do
3641
+ expect(selection.selector).to eq(
3642
+ { "field" => { "$exists" => true }}
3643
+ )
3644
+ end
3645
+
3646
+ it "returns a cloned query" do
3647
+ expect(selection).to_not eq(query)
3648
+ end
3649
+ end
3650
+ end
3651
+
3652
+ context "when performing a $gt" do
3653
+
3654
+ let(:selection) do
3655
+ query.where(:field.gt => 10)
3656
+ end
3657
+
3658
+ it "adds the $gt criterion" do
3659
+ expect(selection.selector).to eq(
3660
+ { "field" => { "$gt" => 10 }}
3661
+ )
3662
+ end
3663
+
3664
+ it "returns a cloned query" do
3665
+ expect(selection).to_not eq(query)
3666
+ end
3667
+ end
3668
+
3669
+ context "when performing a $gte" do
3670
+
3671
+ let(:selection) do
3672
+ query.where(:field.gte => 10)
3673
+ end
3674
+
3675
+ it "adds the $gte criterion" do
3676
+ expect(selection.selector).to eq(
3677
+ { "field" => { "$gte" => 10 }}
3678
+ )
3679
+ end
3680
+
3681
+ it "returns a cloned query" do
3682
+ expect(selection).to_not eq(query)
3683
+ end
3684
+ end
3685
+
3686
+ context "when performing an $in" do
3687
+
3688
+ let(:selection) do
3689
+ query.where(:field.in => [ 1, 2 ])
3690
+ end
3691
+
3692
+ it "adds the $in criterion" do
3693
+ expect(selection.selector).to eq({ "field" => { "$in" => [ 1, 2 ] }})
3694
+ end
3695
+
3696
+ it "returns a cloned query" do
3697
+ expect(selection).to_not eq(query)
3698
+ end
3699
+ end
3700
+
3701
+ context "when performing a $lt" do
3702
+
3703
+ let(:selection) do
3704
+ query.where(:field.lt => 10)
3705
+ end
3706
+
3707
+ it "adds the $lt criterion" do
3708
+ expect(selection.selector).to eq(
3709
+ { "field" => { "$lt" => 10 }}
3710
+ )
3711
+ end
3712
+
3713
+ it "returns a cloned query" do
3714
+ expect(selection).to_not eq(query)
3715
+ end
3716
+ end
3717
+
3718
+ context "when performing a $lte" do
3719
+
3720
+ let(:selection) do
3721
+ query.where(:field.lte => 10)
3722
+ end
3723
+
3724
+ it "adds the $lte criterion" do
3725
+ expect(selection.selector).to eq(
3726
+ { "field" => { "$lte" => 10 }}
3727
+ )
3728
+ end
3729
+
3730
+ it "returns a cloned query" do
3731
+ expect(selection).to_not eq(query)
3732
+ end
3733
+ end
3734
+
3735
+ context "when performing a $mod" do
3736
+
3737
+ let(:selection) do
3738
+ query.where(:field.mod => [ 10, 1 ])
3739
+ end
3740
+
3741
+ it "adds the $lte criterion" do
3742
+ expect(selection.selector).to eq(
3743
+ { "field" => { "$mod" => [ 10, 1 ]}}
3744
+ )
3745
+ end
3746
+
3747
+ it "returns a cloned query" do
3748
+ expect(selection).to_not eq(query)
3749
+ end
3750
+ end
3751
+
3752
+ context "when performing a $ne" do
3753
+
3754
+ let(:selection) do
3755
+ query.where(:field.ne => 10)
3756
+ end
3757
+
3758
+ it "adds the $ne criterion" do
3759
+ expect(selection.selector).to eq(
3760
+ { "field" => { "$ne" => 10 }}
3761
+ )
3762
+ end
3763
+
3764
+ it "returns a cloned query" do
3765
+ expect(selection).to_not eq(query)
3766
+ end
3767
+ end
3768
+
3769
+ context "when performing a $near" do
3770
+
3771
+ let(:selection) do
3772
+ query.where(:field.near => [ 1, 1 ])
3773
+ end
3774
+
3775
+ it "adds the $near criterion" do
3776
+ expect(selection.selector).to eq(
3777
+ { "field" => { "$near" => [ 1, 1 ] }}
3778
+ )
3779
+ end
3780
+
3781
+ it "returns a cloned query" do
3782
+ expect(selection).to_not eq(query)
3783
+ end
3784
+ end
3785
+
3786
+ context "when performing a $nearSphere" do
3787
+
3788
+ let(:selection) do
3789
+ query.where(:field.near_sphere => [ 1, 1 ])
3790
+ end
3791
+
3792
+ it "adds the $nearSphere criterion" do
3793
+ expect(selection.selector).to eq(
3794
+ { "field" => { "$nearSphere" => [ 1, 1 ] }}
3795
+ )
3796
+ end
3797
+
3798
+ it "returns a cloned query" do
3799
+ expect(selection).to_not eq(query)
3800
+ end
3801
+ end
3802
+
3803
+ context "when performing a $nin" do
3804
+
3805
+ let(:selection) do
3806
+ query.where(:field.nin => [ 1, 2 ])
3807
+ end
3808
+
3809
+ it "adds the $nin criterion" do
3810
+ expect(selection.selector).to eq({ "field" => { "$nin" => [ 1, 2 ] }})
3811
+ end
3812
+
3813
+ it "returns a cloned query" do
3814
+ expect(selection).to_not eq(query)
3815
+ end
3816
+ end
3817
+
3818
+ context "when performing a $not" do
3819
+
3820
+ let(:selection) do
3821
+ query.where(:field.not => /test/)
3822
+ end
3823
+
3824
+ it "adds the $not criterion" do
3825
+ expect(selection.selector).to eq({ "field" => { "$not" => /test/ }})
3826
+ end
3827
+
3828
+ it "returns a cloned query" do
3829
+ expect(selection).to_not eq(query)
3830
+ end
3831
+ end
3832
+
3833
+ context "when performing a $size" do
3834
+
3835
+ context "when providing an integer" do
3836
+
3837
+ let(:selection) do
3838
+ query.where(:field.with_size => 10)
3839
+ end
3840
+
3841
+ it "adds the $size criterion" do
3842
+ expect(selection.selector).to eq(
3843
+ { "field" => { "$size" => 10 }}
3844
+ )
3845
+ end
3846
+
3847
+ it "returns a cloned query" do
3848
+ expect(selection).to_not eq(query)
3849
+ end
3850
+ end
3851
+
3852
+ context "when providing a string" do
3853
+
3854
+ let(:selection) do
3855
+ query.where(:field.with_size => "10")
3856
+ end
3857
+
3858
+ it "adds the $size criterion" do
3859
+ expect(selection.selector).to eq(
3860
+ { "field" => { "$size" => 10 }}
3861
+ )
3862
+ end
3863
+
3864
+ it "returns a cloned query" do
3865
+ expect(selection).to_not eq(query)
3866
+ end
3867
+ end
3868
+ end
3869
+
3870
+ context "when performing a $type" do
3871
+
3872
+ let(:selection) do
3873
+ query.where(:field.with_type => 10)
3874
+ end
3875
+
3876
+ it "adds the $type criterion" do
3877
+ expect(selection.selector).to eq(
3878
+ { "field" => { "$type" => 10 }}
3879
+ )
3880
+ end
3881
+
3882
+ it "returns a cloned query" do
3883
+ expect(selection).to_not eq(query)
3884
+ end
3885
+ end
3886
+ end
3887
+ end
3888
+
3889
+ describe Symbol do
3890
+
3891
+ describe "#all" do
3892
+
3893
+ let(:key) do
3894
+ :field.all
3895
+ end
3896
+
3897
+ it "returns a selecton key" do
3898
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3899
+ end
3900
+
3901
+ it "sets the name as the key" do
3902
+ expect(key.name).to eq(:field)
3903
+ end
3904
+
3905
+ it "sets the operator as $all" do
3906
+ expect(key.operator).to eq("$all")
3907
+ end
3908
+ end
3909
+
3910
+ describe "#elem_match" do
3911
+
3912
+ let(:key) do
3913
+ :field.elem_match
3914
+ end
3915
+
3916
+ it "returns a selecton key" do
3917
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3918
+ end
3919
+
3920
+ it "sets the name as the key" do
3921
+ expect(key.name).to eq(:field)
3922
+ end
3923
+
3924
+ it "sets the operator as $elemMatch" do
3925
+ expect(key.operator).to eq("$elemMatch")
3926
+ end
3927
+ end
3928
+
3929
+ describe "#exists" do
3930
+
3931
+ let(:key) do
3932
+ :field.exists
3933
+ end
3934
+
3935
+ it "returns a selecton key" do
3936
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3937
+ end
3938
+
3939
+ it "sets the name as the key" do
3940
+ expect(key.name).to eq(:field)
3941
+ end
3942
+
3943
+ it "sets the operator as $exists" do
3944
+ expect(key.operator).to eq("$exists")
3945
+ end
3946
+ end
3947
+
3948
+ describe "#gt" do
3949
+
3950
+ let(:key) do
3951
+ :field.gt
3952
+ end
3953
+
3954
+ it "returns a selecton key" do
3955
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3956
+ end
3957
+
3958
+ it "sets the name as the key" do
3959
+ expect(key.name).to eq(:field)
3960
+ end
3961
+
3962
+ it "sets the operator as $gt" do
3963
+ expect(key.operator).to eq("$gt")
3964
+ end
3965
+ end
3966
+
3967
+ describe "#gte" do
3968
+
3969
+ let(:key) do
3970
+ :field.gte
3971
+ end
3972
+
3973
+ it "returns a selecton key" do
3974
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3975
+ end
3976
+
3977
+ it "sets the name as the key" do
3978
+ expect(key.name).to eq(:field)
3979
+ end
3980
+
3981
+ it "sets the operator as $gte" do
3982
+ expect(key.operator).to eq("$gte")
3983
+ end
3984
+ end
3985
+
3986
+ describe "#in" do
3987
+
3988
+ let(:key) do
3989
+ :field.in
3990
+ end
3991
+
3992
+ it "returns a selecton key" do
3993
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3994
+ end
3995
+
3996
+ it "sets the name as the key" do
3997
+ expect(key.name).to eq(:field)
3998
+ end
3999
+
4000
+ it "sets the operator as $in" do
4001
+ expect(key.operator).to eq("$in")
4002
+ end
4003
+ end
4004
+
4005
+ describe "#lt" do
4006
+
4007
+ let(:key) do
4008
+ :field.lt
4009
+ end
4010
+
4011
+ it "returns a selecton key" do
4012
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4013
+ end
4014
+
4015
+ it "sets the name as the key" do
4016
+ expect(key.name).to eq(:field)
4017
+ end
4018
+
4019
+ it "sets the operator as $lt" do
4020
+ expect(key.operator).to eq("$lt")
4021
+ end
4022
+ end
4023
+
4024
+ describe "#lte" do
4025
+
4026
+ let(:key) do
4027
+ :field.lte
4028
+ end
4029
+
4030
+ it "returns a selecton key" do
4031
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4032
+ end
4033
+
4034
+ it "sets the name as the key" do
4035
+ expect(key.name).to eq(:field)
4036
+ end
4037
+
4038
+ it "sets the operator as $lte" do
4039
+ expect(key.operator).to eq("$lte")
4040
+ end
4041
+ end
4042
+
4043
+ describe "#mod" do
4044
+
4045
+ let(:key) do
4046
+ :field.mod
4047
+ end
4048
+
4049
+ it "returns a selecton key" do
4050
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4051
+ end
4052
+
4053
+ it "sets the name as the key" do
4054
+ expect(key.name).to eq(:field)
4055
+ end
4056
+
4057
+ it "sets the operator as $mod" do
4058
+ expect(key.operator).to eq("$mod")
4059
+ end
4060
+ end
4061
+
4062
+ describe "#ne" do
4063
+
4064
+ let(:key) do
4065
+ :field.ne
4066
+ end
4067
+
4068
+ it "returns a selecton key" do
4069
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4070
+ end
4071
+
4072
+ it "sets the name as the key" do
4073
+ expect(key.name).to eq(:field)
4074
+ end
4075
+
4076
+ it "sets the operator as $ne" do
4077
+ expect(key.operator).to eq("$ne")
4078
+ end
4079
+ end
4080
+
4081
+ describe "#near" do
4082
+
4083
+ let(:key) do
4084
+ :field.near
4085
+ end
4086
+
4087
+ it "returns a selecton key" do
4088
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4089
+ end
4090
+
4091
+ it "sets the name as the key" do
4092
+ expect(key.name).to eq(:field)
4093
+ end
4094
+
4095
+ it "sets the operator as $near" do
4096
+ expect(key.operator).to eq("$near")
4097
+ end
4098
+ end
4099
+
4100
+ describe "#near_sphere" do
4101
+
4102
+ let(:key) do
4103
+ :field.near_sphere
4104
+ end
4105
+
4106
+ it "returns a selecton key" do
4107
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4108
+ end
4109
+
4110
+ it "sets the name as the key" do
4111
+ expect(key.name).to eq(:field)
4112
+ end
4113
+
4114
+ it "sets the operator as $nearSphere" do
4115
+ expect(key.operator).to eq("$nearSphere")
4116
+ end
4117
+ end
4118
+
4119
+ describe "#nin" do
4120
+
4121
+ let(:key) do
4122
+ :field.nin
4123
+ end
4124
+
4125
+ it "returns a selecton key" do
4126
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4127
+ end
4128
+
4129
+ it "sets the name as the key" do
4130
+ expect(key.name).to eq(:field)
4131
+ end
4132
+
4133
+ it "sets the operator as $nin" do
4134
+ expect(key.operator).to eq("$nin")
4135
+ end
4136
+ end
4137
+
4138
+ describe "#not" do
4139
+
4140
+ let(:key) do
4141
+ :field.not
4142
+ end
4143
+
4144
+ it "returns a selection key" do
4145
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4146
+ end
4147
+
4148
+ it "sets the name as the key" do
4149
+ expect(key.name).to eq(:field)
4150
+ end
4151
+
4152
+ it "sets the operator as $not" do
4153
+ expect(key.operator).to eq("$not")
4154
+ end
4155
+
4156
+ end
4157
+
4158
+ describe "#with_size" do
4159
+
4160
+ let(:key) do
4161
+ :field.with_size
4162
+ end
4163
+
4164
+ it "returns a selecton key" do
4165
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4166
+ end
4167
+
4168
+ it "sets the name as the key" do
4169
+ expect(key.name).to eq(:field)
4170
+ end
4171
+
4172
+ it "sets the operator as $size" do
4173
+ expect(key.operator).to eq("$size")
4174
+ end
4175
+ end
4176
+
4177
+ describe "#with_type" do
4178
+
4179
+ let(:key) do
4180
+ :field.with_type
4181
+ end
4182
+
4183
+ it "returns a selecton key" do
4184
+ expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4185
+ end
4186
+
4187
+ it "sets the name as the key" do
4188
+ expect(key.name).to eq(:field)
4189
+ end
4190
+
4191
+ it "sets the operator as $type" do
4192
+ expect(key.operator).to eq("$type")
4193
+ end
4194
+ end
4195
+ end
4196
+
4197
+ context "when using multiple strategies on the same field" do
4198
+
4199
+ context "when using the strategies via methods" do
4200
+
4201
+ context "when the values are a hash" do
4202
+
4203
+ let(:selection) do
4204
+ query.gt(field: 5).lt(field: 10).ne(field: 7)
4205
+ end
4206
+
4207
+ it "merges the strategies on the same field" do
4208
+ expect(selection.selector).to eq(
4209
+ { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
4210
+ )
4211
+ end
4212
+ end
4213
+
4214
+ context "when the values are not hashes" do
4215
+
4216
+ let(:selection) do
4217
+ query.where(field: 5).where(field: 10)
4218
+ end
4219
+
4220
+ it "overrides the previous field" do
4221
+ expect(selection.selector).to eq({ "field" => 10 })
4222
+ end
4223
+ end
4224
+ end
4225
+
4226
+ context "when using the strategies via #where" do
4227
+
4228
+ context "when the values are a hash" do
4229
+
4230
+ let(:selection) do
4231
+ query.where(:field.gt => 5, :field.lt => 10, :field.ne => 7)
4232
+ end
4233
+
4234
+ it "merges the strategies on the same field" do
4235
+ expect(selection.selector).to eq(
4236
+ { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
4237
+ )
4238
+ end
4239
+ end
4240
+ end
4241
+ end
4242
+ end