mongoid 5.4.0 → 6.4.8

Sign up to get free protection for your applications and to get access to all the features.
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