mongoid 7.0.5 → 8.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1107) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +33 -33
  4. data/LICENSE +1 -0
  5. data/README.md +34 -20
  6. data/Rakefile +63 -5
  7. data/lib/config/locales/en.yml +220 -105
  8. data/lib/mongoid/association/accessors.rb +176 -84
  9. data/lib/mongoid/association/bindable.rb +57 -28
  10. data/lib/mongoid/association/builders.rb +9 -15
  11. data/lib/mongoid/association/constrainable.rb +5 -7
  12. data/lib/mongoid/association/depending.rb +9 -18
  13. data/lib/mongoid/association/eager_loadable.rb +31 -10
  14. data/lib/mongoid/association/embedded/batchable.rb +68 -54
  15. data/lib/mongoid/association/embedded/cyclic.rb +10 -17
  16. data/lib/mongoid/association/embedded/embedded_in/binding.rb +27 -9
  17. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +9 -6
  18. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +16 -25
  19. data/lib/mongoid/association/embedded/embedded_in.rb +9 -28
  20. data/lib/mongoid/association/embedded/embeds_many/binding.rb +5 -8
  21. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +10 -6
  22. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +156 -135
  23. data/lib/mongoid/association/embedded/embeds_many.rb +10 -37
  24. data/lib/mongoid/association/embedded/embeds_one/binding.rb +4 -8
  25. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +27 -10
  26. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +64 -30
  27. data/lib/mongoid/association/embedded/embeds_one.rb +11 -34
  28. data/lib/mongoid/association/embedded.rb +2 -0
  29. data/lib/mongoid/association/macros.rb +65 -41
  30. data/lib/mongoid/association/many.rb +25 -35
  31. data/lib/mongoid/association/marshalable.rb +3 -6
  32. data/lib/mongoid/association/nested/many.rb +22 -30
  33. data/lib/mongoid/association/nested/nested_buildable.rb +9 -15
  34. data/lib/mongoid/association/nested/one.rb +57 -30
  35. data/lib/mongoid/association/nested.rb +3 -3
  36. data/lib/mongoid/association/one.rb +5 -12
  37. data/lib/mongoid/association/options.rb +16 -46
  38. data/lib/mongoid/association/proxy.rb +52 -40
  39. data/lib/mongoid/association/referenced/auto_save.rb +9 -14
  40. data/lib/mongoid/association/referenced/belongs_to/binding.rb +5 -9
  41. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +11 -9
  42. data/lib/mongoid/association/referenced/belongs_to/eager.rb +40 -3
  43. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +19 -31
  44. data/lib/mongoid/association/referenced/belongs_to.rb +16 -38
  45. data/lib/mongoid/association/referenced/counter_cache.rb +14 -25
  46. data/lib/mongoid/association/referenced/eager.rb +41 -40
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +12 -11
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +5 -5
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +2 -1
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +105 -68
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +29 -46
  52. data/lib/mongoid/association/referenced/has_many/binding.rb +3 -6
  53. data/lib/mongoid/association/referenced/has_many/buildable.rb +5 -5
  54. data/lib/mongoid/association/referenced/has_many/eager.rb +2 -1
  55. data/lib/mongoid/association/referenced/has_many/enumerable.rb +440 -456
  56. data/lib/mongoid/association/referenced/has_many/proxy.rb +102 -125
  57. data/lib/mongoid/association/referenced/has_many.rb +21 -45
  58. data/lib/mongoid/association/referenced/has_one/binding.rb +4 -9
  59. data/lib/mongoid/association/referenced/has_one/buildable.rb +20 -6
  60. data/lib/mongoid/association/referenced/has_one/eager.rb +2 -1
  61. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +16 -29
  62. data/lib/mongoid/association/referenced/has_one/proxy.rb +25 -30
  63. data/lib/mongoid/association/referenced/has_one.rb +16 -36
  64. data/lib/mongoid/association/referenced/syncable.rb +11 -26
  65. data/lib/mongoid/association/referenced.rb +2 -0
  66. data/lib/mongoid/association/reflections.rb +7 -6
  67. data/lib/mongoid/association/relatable.rb +62 -84
  68. data/lib/mongoid/association.rb +13 -27
  69. data/lib/mongoid/atomic/modifiers.rb +29 -53
  70. data/lib/mongoid/atomic/paths/embedded/many.rb +23 -7
  71. data/lib/mongoid/atomic/paths/embedded/one.rb +4 -7
  72. data/lib/mongoid/atomic/paths/embedded.rb +2 -3
  73. data/lib/mongoid/atomic/paths/root.rb +4 -7
  74. data/lib/mongoid/atomic/paths.rb +2 -1
  75. data/lib/mongoid/atomic.rb +42 -47
  76. data/lib/mongoid/attributes/dynamic.rb +22 -36
  77. data/lib/mongoid/attributes/nested.rb +12 -15
  78. data/lib/mongoid/attributes/processing.rb +19 -27
  79. data/lib/mongoid/attributes/projector.rb +119 -0
  80. data/lib/mongoid/attributes/readonly.rb +6 -9
  81. data/lib/mongoid/attributes.rb +103 -100
  82. data/lib/mongoid/cacheable.rb +7 -10
  83. data/lib/mongoid/changeable.rb +151 -70
  84. data/lib/mongoid/clients/factory.rb +42 -17
  85. data/lib/mongoid/clients/options.rb +15 -14
  86. data/lib/mongoid/clients/sessions.rb +10 -10
  87. data/lib/mongoid/clients/storage_options.rb +9 -17
  88. data/lib/mongoid/clients/validators/storage.rb +5 -24
  89. data/lib/mongoid/clients/validators.rb +2 -1
  90. data/lib/mongoid/clients.rb +3 -10
  91. data/lib/mongoid/collection_configurable.rb +58 -0
  92. data/lib/mongoid/composable.rb +7 -9
  93. data/lib/mongoid/config/defaults.rb +60 -0
  94. data/lib/mongoid/config/environment.rb +51 -13
  95. data/lib/mongoid/config/options.rb +20 -23
  96. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  97. data/lib/mongoid/config/validators/client.rb +8 -23
  98. data/lib/mongoid/config/validators/option.rb +2 -3
  99. data/lib/mongoid/config/validators.rb +3 -1
  100. data/lib/mongoid/config.rb +235 -48
  101. data/lib/mongoid/contextual/aggregable/memory.rb +40 -27
  102. data/lib/mongoid/contextual/aggregable/mongo.rb +32 -33
  103. data/lib/mongoid/contextual/aggregable/none.rb +65 -0
  104. data/lib/mongoid/contextual/aggregable.rb +17 -0
  105. data/lib/mongoid/contextual/atomic.rb +29 -31
  106. data/lib/mongoid/contextual/command.rb +2 -5
  107. data/lib/mongoid/contextual/geo_near.rb +13 -44
  108. data/lib/mongoid/contextual/map_reduce.rb +7 -35
  109. data/lib/mongoid/contextual/memory.rb +387 -81
  110. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  111. data/lib/mongoid/contextual/mongo.rb +641 -283
  112. data/lib/mongoid/contextual/none.rb +264 -31
  113. data/lib/mongoid/contextual/queryable.rb +3 -4
  114. data/lib/mongoid/contextual.rb +21 -11
  115. data/lib/mongoid/copyable.rb +42 -17
  116. data/lib/mongoid/criteria/findable.rb +20 -20
  117. data/lib/mongoid/criteria/includable.rb +32 -34
  118. data/lib/mongoid/criteria/inspectable.rb +2 -3
  119. data/lib/mongoid/criteria/marshalable.rb +12 -7
  120. data/lib/mongoid/criteria/modifiable.rb +4 -20
  121. data/lib/mongoid/criteria/options.rb +2 -3
  122. data/lib/mongoid/criteria/permission.rb +3 -2
  123. data/lib/mongoid/criteria/queryable/aggregable.rb +4 -15
  124. data/lib/mongoid/criteria/queryable/expandable.rb +68 -0
  125. data/lib/mongoid/criteria/queryable/extensions/array.rb +7 -41
  126. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +28 -8
  127. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +5 -6
  128. data/lib/mongoid/criteria/queryable/extensions/date.rb +9 -9
  129. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +11 -12
  130. data/lib/mongoid/criteria/queryable/extensions/hash.rb +4 -41
  131. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +3 -14
  132. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +4 -21
  133. data/lib/mongoid/criteria/queryable/extensions/object.rb +6 -30
  134. data/lib/mongoid/criteria/queryable/extensions/range.rb +49 -17
  135. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +12 -19
  136. data/lib/mongoid/criteria/queryable/extensions/set.rb +4 -5
  137. data/lib/mongoid/criteria/queryable/extensions/string.rb +7 -32
  138. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +7 -22
  139. data/lib/mongoid/criteria/queryable/extensions/time.rb +10 -10
  140. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +19 -7
  141. data/lib/mongoid/criteria/queryable/extensions.rb +1 -4
  142. data/lib/mongoid/criteria/queryable/key.rb +40 -25
  143. data/lib/mongoid/criteria/queryable/macroable.rb +3 -4
  144. data/lib/mongoid/criteria/queryable/mergeable.rb +205 -44
  145. data/lib/mongoid/criteria/queryable/optional.rb +16 -65
  146. data/lib/mongoid/criteria/queryable/options.rb +4 -21
  147. data/lib/mongoid/criteria/queryable/pipeline.rb +5 -15
  148. data/lib/mongoid/criteria/queryable/selectable.rb +453 -177
  149. data/lib/mongoid/criteria/queryable/selector.rb +126 -29
  150. data/lib/mongoid/criteria/queryable/smash.rb +42 -18
  151. data/lib/mongoid/criteria/queryable/storable.rb +237 -0
  152. data/lib/mongoid/criteria/queryable.rb +18 -15
  153. data/lib/mongoid/criteria/scopable.rb +29 -21
  154. data/lib/mongoid/criteria/translator.rb +45 -0
  155. data/lib/mongoid/criteria.rb +106 -111
  156. data/lib/mongoid/deprecable.rb +36 -0
  157. data/lib/mongoid/deprecation.rb +25 -0
  158. data/lib/mongoid/document.rb +151 -99
  159. data/lib/mongoid/equality.rb +35 -18
  160. data/lib/mongoid/errors/ambiguous_relationship.rb +4 -5
  161. data/lib/mongoid/errors/callback.rb +2 -3
  162. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  163. data/lib/mongoid/errors/criteria_argument_required.rb +18 -0
  164. data/lib/mongoid/errors/delete_restriction.rb +10 -13
  165. data/lib/mongoid/errors/document_not_destroyed.rb +4 -7
  166. data/lib/mongoid/errors/document_not_found.rb +35 -21
  167. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  168. data/lib/mongoid/errors/empty_config_file.rb +25 -0
  169. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  170. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -3
  171. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  172. data/lib/mongoid/errors/invalid_collection.rb +2 -1
  173. data/lib/mongoid/errors/invalid_config_file.rb +25 -0
  174. data/lib/mongoid/errors/invalid_config_option.rb +3 -4
  175. data/lib/mongoid/errors/invalid_dependent_strategy.rb +3 -4
  176. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +24 -0
  177. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  178. data/lib/mongoid/errors/invalid_elem_match_operator.rb +32 -0
  179. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +25 -0
  180. data/lib/mongoid/errors/invalid_expression_operator.rb +27 -0
  181. data/lib/mongoid/errors/invalid_field.rb +8 -7
  182. data/lib/mongoid/errors/invalid_field_operator.rb +32 -0
  183. data/lib/mongoid/errors/invalid_field_option.rb +2 -3
  184. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  185. data/lib/mongoid/errors/invalid_find.rb +2 -3
  186. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  187. data/lib/mongoid/errors/invalid_includes.rb +2 -3
  188. data/lib/mongoid/errors/invalid_index.rb +2 -3
  189. data/lib/mongoid/errors/invalid_options.rb +4 -5
  190. data/lib/mongoid/errors/invalid_path.rb +2 -3
  191. data/lib/mongoid/errors/invalid_persistence_option.rb +2 -5
  192. data/lib/mongoid/errors/invalid_query.rb +40 -0
  193. data/lib/mongoid/errors/invalid_relation.rb +5 -10
  194. data/lib/mongoid/errors/invalid_relation_option.rb +4 -5
  195. data/lib/mongoid/errors/invalid_scope.rb +2 -3
  196. data/lib/mongoid/errors/invalid_session_use.rb +3 -6
  197. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -5
  198. data/lib/mongoid/errors/invalid_storage_options.rb +3 -4
  199. data/lib/mongoid/errors/invalid_storage_parent.rb +4 -3
  200. data/lib/mongoid/errors/invalid_time.rb +2 -3
  201. data/lib/mongoid/errors/inverse_not_found.rb +3 -4
  202. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -3
  203. data/lib/mongoid/errors/mixed_relations.rb +2 -3
  204. data/lib/mongoid/errors/mongoid_error.rb +6 -13
  205. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -4
  206. data/lib/mongoid/errors/no_client_config.rb +4 -5
  207. data/lib/mongoid/errors/no_client_database.rb +3 -4
  208. data/lib/mongoid/errors/no_client_hosts.rb +3 -4
  209. data/lib/mongoid/errors/no_clients_config.rb +2 -3
  210. data/lib/mongoid/errors/no_default_client.rb +3 -4
  211. data/lib/mongoid/errors/no_environment.rb +2 -3
  212. data/lib/mongoid/errors/no_map_reduce_output.rb +2 -3
  213. data/lib/mongoid/errors/no_metadata.rb +2 -3
  214. data/lib/mongoid/errors/no_parent.rb +2 -3
  215. data/lib/mongoid/errors/readonly_attribute.rb +3 -4
  216. data/lib/mongoid/errors/readonly_document.rb +3 -6
  217. data/lib/mongoid/errors/scope_overwrite.rb +2 -1
  218. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +3 -1
  219. data/lib/mongoid/errors/unknown_attribute.rb +3 -4
  220. data/lib/mongoid/errors/unknown_model.rb +2 -3
  221. data/lib/mongoid/errors/unsaved_document.rb +3 -2
  222. data/lib/mongoid/errors/unsupported_javascript.rb +2 -3
  223. data/lib/mongoid/errors/validations.rb +2 -1
  224. data/lib/mongoid/errors.rb +18 -4
  225. data/lib/mongoid/evolvable.rb +4 -5
  226. data/lib/mongoid/extensions/array.rb +37 -44
  227. data/lib/mongoid/extensions/big_decimal.rb +35 -21
  228. data/lib/mongoid/extensions/binary.rb +42 -0
  229. data/lib/mongoid/extensions/boolean.rb +10 -6
  230. data/lib/mongoid/extensions/date.rb +32 -25
  231. data/lib/mongoid/extensions/date_time.rb +5 -13
  232. data/lib/mongoid/extensions/decimal128.rb +2 -5
  233. data/lib/mongoid/extensions/false_class.rb +5 -8
  234. data/lib/mongoid/extensions/float.rb +12 -14
  235. data/lib/mongoid/extensions/hash.rb +64 -42
  236. data/lib/mongoid/extensions/integer.rb +12 -16
  237. data/lib/mongoid/extensions/module.rb +3 -4
  238. data/lib/mongoid/extensions/nil_class.rb +2 -5
  239. data/lib/mongoid/extensions/object.rb +27 -52
  240. data/lib/mongoid/extensions/object_id.rb +2 -7
  241. data/lib/mongoid/extensions/range.rb +42 -20
  242. data/lib/mongoid/extensions/regexp.rb +14 -8
  243. data/lib/mongoid/extensions/set.rb +13 -11
  244. data/lib/mongoid/extensions/string.rb +30 -61
  245. data/lib/mongoid/extensions/symbol.rb +6 -22
  246. data/lib/mongoid/extensions/time.rb +38 -22
  247. data/lib/mongoid/extensions/time_with_zone.rb +26 -9
  248. data/lib/mongoid/extensions/true_class.rb +5 -8
  249. data/lib/mongoid/extensions.rb +19 -3
  250. data/lib/mongoid/factory.rb +104 -17
  251. data/lib/mongoid/fields/foreign_key.rb +14 -26
  252. data/lib/mongoid/fields/localized.rb +21 -15
  253. data/lib/mongoid/fields/standard.rb +23 -43
  254. data/lib/mongoid/fields/validators/macro.rb +32 -20
  255. data/lib/mongoid/fields/validators.rb +2 -1
  256. data/lib/mongoid/fields.rb +349 -76
  257. data/lib/mongoid/findable.rb +115 -34
  258. data/lib/mongoid/indexable/specification.rb +5 -18
  259. data/lib/mongoid/indexable/validators/options.rb +8 -9
  260. data/lib/mongoid/indexable.rb +6 -21
  261. data/lib/mongoid/inspectable.rb +4 -11
  262. data/lib/mongoid/interceptable.rb +85 -41
  263. data/lib/mongoid/loggable.rb +13 -16
  264. data/lib/mongoid/matchable.rb +4 -156
  265. data/lib/mongoid/matcher/all.rb +22 -0
  266. data/lib/mongoid/matcher/and.rb +21 -0
  267. data/lib/mongoid/matcher/bits.rb +41 -0
  268. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  269. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  270. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  271. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  272. data/lib/mongoid/matcher/elem_match.rb +36 -0
  273. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  274. data/lib/mongoid/matcher/eq.rb +11 -0
  275. data/lib/mongoid/matcher/eq_impl.rb +67 -0
  276. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +26 -0
  277. data/lib/mongoid/matcher/exists.rb +15 -0
  278. data/lib/mongoid/matcher/expression.rb +35 -0
  279. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  280. data/lib/mongoid/matcher/field_expression.rb +62 -0
  281. data/lib/mongoid/matcher/field_operator.rb +54 -0
  282. data/lib/mongoid/matcher/gt.rb +17 -0
  283. data/lib/mongoid/matcher/gte.rb +17 -0
  284. data/lib/mongoid/matcher/in.rb +25 -0
  285. data/lib/mongoid/matcher/lt.rb +17 -0
  286. data/lib/mongoid/matcher/lte.rb +17 -0
  287. data/lib/mongoid/matcher/mod.rb +17 -0
  288. data/lib/mongoid/matcher/ne.rb +16 -0
  289. data/lib/mongoid/matcher/nin.rb +11 -0
  290. data/lib/mongoid/matcher/nor.rb +25 -0
  291. data/lib/mongoid/matcher/not.rb +29 -0
  292. data/lib/mongoid/matcher/or.rb +21 -0
  293. data/lib/mongoid/matcher/regex.rb +41 -0
  294. data/lib/mongoid/matcher/size.rb +26 -0
  295. data/lib/mongoid/matcher/type.rb +99 -0
  296. data/lib/mongoid/matcher.rb +130 -0
  297. data/lib/mongoid/persistable/creatable.rb +23 -30
  298. data/lib/mongoid/persistable/deletable.rb +7 -23
  299. data/lib/mongoid/persistable/destroyable.rb +12 -11
  300. data/lib/mongoid/persistable/incrementable.rb +6 -7
  301. data/lib/mongoid/persistable/logical.rb +4 -6
  302. data/lib/mongoid/persistable/poppable.rb +3 -6
  303. data/lib/mongoid/persistable/pullable.rb +3 -8
  304. data/lib/mongoid/persistable/pushable.rb +14 -10
  305. data/lib/mongoid/persistable/renamable.rb +10 -8
  306. data/lib/mongoid/persistable/savable.rb +16 -9
  307. data/lib/mongoid/persistable/settable.rb +3 -6
  308. data/lib/mongoid/persistable/unsettable.rb +10 -10
  309. data/lib/mongoid/persistable/updatable.rb +99 -30
  310. data/lib/mongoid/persistable/upsertable.rb +23 -9
  311. data/lib/mongoid/persistable.rb +138 -40
  312. data/lib/mongoid/persistence_context.rb +91 -51
  313. data/lib/mongoid/positional.rb +2 -5
  314. data/lib/mongoid/query_cache.rb +18 -238
  315. data/lib/mongoid/railtie.rb +3 -16
  316. data/lib/mongoid/railties/controller_runtime.rb +4 -2
  317. data/lib/mongoid/railties/database.rake +16 -2
  318. data/lib/mongoid/reloadable.rb +21 -22
  319. data/lib/mongoid/scopable.rb +34 -57
  320. data/lib/mongoid/selectable.rb +8 -18
  321. data/lib/mongoid/serializable.rb +33 -34
  322. data/lib/mongoid/shardable.rb +108 -21
  323. data/lib/mongoid/stateful.rb +60 -20
  324. data/lib/mongoid/stringified_symbol.rb +52 -0
  325. data/lib/mongoid/tasks/database.rake +24 -5
  326. data/lib/mongoid/tasks/database.rb +105 -7
  327. data/lib/mongoid/threaded/lifecycle.rb +7 -26
  328. data/lib/mongoid/threaded.rb +44 -67
  329. data/lib/mongoid/timestamps/created/short.rb +2 -1
  330. data/lib/mongoid/timestamps/created.rb +4 -3
  331. data/lib/mongoid/timestamps/short.rb +2 -1
  332. data/lib/mongoid/timestamps/timeless.rb +6 -9
  333. data/lib/mongoid/timestamps/updated/short.rb +2 -1
  334. data/lib/mongoid/timestamps/updated.rb +5 -6
  335. data/lib/mongoid/timestamps.rb +3 -2
  336. data/lib/mongoid/touchable.rb +54 -25
  337. data/lib/mongoid/traversable.rb +185 -61
  338. data/lib/mongoid/utils.rb +22 -0
  339. data/lib/mongoid/validatable/associated.rb +5 -6
  340. data/lib/mongoid/validatable/format.rb +2 -1
  341. data/lib/mongoid/validatable/length.rb +2 -1
  342. data/lib/mongoid/validatable/localizable.rb +3 -4
  343. data/lib/mongoid/validatable/macros.rb +7 -14
  344. data/lib/mongoid/validatable/presence.rb +10 -15
  345. data/lib/mongoid/validatable/queryable.rb +2 -3
  346. data/lib/mongoid/validatable/uniqueness.rb +30 -42
  347. data/lib/mongoid/validatable.rb +16 -32
  348. data/lib/mongoid/version.rb +3 -2
  349. data/lib/mongoid/warnings.rb +44 -0
  350. data/lib/mongoid.rb +50 -17
  351. data/lib/rails/generators/mongoid/config/config_generator.rb +10 -2
  352. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +53 -32
  353. data/lib/rails/generators/mongoid/model/model_generator.rb +3 -2
  354. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  355. data/lib/rails/generators/mongoid_generator.rb +2 -1
  356. data/lib/rails/mongoid.rb +4 -5
  357. data/spec/README.md +19 -4
  358. data/spec/config/mongoid.yml +17 -0
  359. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  360. data/spec/integration/app_spec.rb +345 -0
  361. data/spec/integration/associations/belongs_to_spec.rb +20 -0
  362. data/spec/integration/associations/embedded_dirty_spec.rb +57 -0
  363. data/spec/integration/associations/embedded_spec.rb +283 -0
  364. data/spec/integration/associations/embeds_many_spec.rb +219 -0
  365. data/spec/integration/associations/embeds_one_spec.rb +41 -0
  366. data/spec/integration/associations/foreign_key_spec.rb +107 -0
  367. data/spec/integration/associations/foreign_key_spec_models.rb +64 -0
  368. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  369. data/spec/integration/associations/has_many_spec.rb +128 -0
  370. data/spec/integration/associations/has_one_spec.rb +272 -0
  371. data/spec/integration/associations/nested_attributes_assignment_spec.rb +115 -0
  372. data/spec/integration/associations/reverse_population_spec.rb +34 -0
  373. data/spec/integration/associations/reverse_population_spec_models.rb +36 -0
  374. data/spec/integration/associations/scope_option_spec.rb +101 -0
  375. data/spec/integration/atomic/modifiers_spec.rb +116 -0
  376. data/spec/integration/bson_regexp_raw_spec.rb +19 -0
  377. data/spec/integration/callbacks_models.rb +192 -0
  378. data/spec/integration/callbacks_spec.rb +584 -0
  379. data/spec/integration/contextual/empty_spec.rb +141 -0
  380. data/spec/integration/criteria/alias_query_spec.rb +161 -0
  381. data/spec/integration/criteria/date_field_spec.rb +40 -0
  382. data/spec/integration/criteria/default_scope_spec.rb +72 -0
  383. data/spec/integration/criteria/logical_spec.rb +124 -0
  384. data/spec/integration/criteria/range_spec.rb +359 -0
  385. data/spec/integration/criteria/time_with_zone_spec.rb +142 -0
  386. data/spec/integration/discriminator_key_spec.rb +391 -0
  387. data/spec/integration/discriminator_value_spec.rb +206 -0
  388. data/spec/integration/document_spec.rb +51 -0
  389. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  390. data/spec/integration/i18n_fallbacks_spec.rb +74 -0
  391. data/spec/integration/matcher_examples_spec.rb +765 -0
  392. data/spec/integration/matcher_operator_data/all.yml +140 -0
  393. data/spec/integration/matcher_operator_data/and.yml +93 -0
  394. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  395. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  396. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  397. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  398. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  399. data/spec/integration/matcher_operator_data/elem_match.yml +409 -0
  400. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  401. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  402. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  403. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  404. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  405. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  406. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  407. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  408. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  409. data/spec/integration/matcher_operator_data/implicit_traversal.yml +112 -0
  410. data/spec/integration/matcher_operator_data/in.yml +210 -0
  411. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  412. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  413. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  414. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  415. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  416. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  417. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  418. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  419. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  420. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  421. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  422. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  423. data/spec/integration/matcher_operator_data/not.yml +196 -0
  424. data/spec/integration/matcher_operator_data/or.yml +137 -0
  425. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  426. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  427. data/spec/integration/matcher_operator_data/size.yml +174 -0
  428. data/spec/integration/matcher_operator_data/type.yml +70 -0
  429. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  430. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  431. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  432. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  433. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  434. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  435. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  436. data/spec/integration/matcher_operator_data/type_decimal.yml +41 -0
  437. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  438. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  439. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  440. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  441. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  442. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  443. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  444. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  445. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  446. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  447. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  448. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  449. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  450. data/spec/integration/matcher_operator_spec.rb +122 -0
  451. data/spec/integration/matcher_spec.rb +283 -0
  452. data/spec/integration/persistence/range_field_spec.rb +350 -0
  453. data/spec/integration/server_query_spec.rb +141 -0
  454. data/spec/integration/shardable_spec.rb +148 -0
  455. data/spec/integration/stringified_symbol_field_spec.rb +203 -0
  456. data/spec/lite_spec_helper.rb +35 -8
  457. data/spec/mongoid/association/accessors_spec.rb +284 -77
  458. data/spec/mongoid/association/auto_save_spec.rb +74 -33
  459. data/spec/mongoid/association/builders_spec.rb +3 -1
  460. data/spec/mongoid/association/constrainable_spec.rb +2 -0
  461. data/spec/mongoid/association/counter_cache_spec.rb +35 -33
  462. data/spec/mongoid/association/depending_spec.rb +431 -338
  463. data/spec/mongoid/association/eager_spec.rb +8 -5
  464. data/spec/mongoid/association/embedded/cyclic_spec.rb +4 -2
  465. data/spec/mongoid/association/embedded/dirty_spec.rb +4 -2
  466. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +4 -1
  467. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +56 -0
  468. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +152 -13
  469. data/spec/mongoid/association/embedded/embedded_in_spec.rb +3 -1
  470. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +2 -0
  471. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +114 -0
  472. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +706 -197
  473. data/spec/mongoid/association/embedded/embeds_many_models.rb +227 -0
  474. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +63 -0
  475. data/spec/mongoid/association/embedded/embeds_many_spec.rb +81 -1
  476. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +2 -0
  477. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +27 -0
  478. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +38 -23
  479. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +2 -0
  480. data/spec/mongoid/association/embedded/embeds_one_models.rb +22 -0
  481. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
  482. data/spec/mongoid/association/embedded/embeds_one_spec.rb +31 -3
  483. data/spec/mongoid/association/macros_spec.rb +11 -9
  484. data/spec/mongoid/association/nested/many_spec.rb +2 -0
  485. data/spec/mongoid/association/nested/one_spec.rb +18 -12
  486. data/spec/mongoid/association/options_spec.rb +2 -0
  487. data/spec/mongoid/association/polymorphic_spec.rb +2 -0
  488. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +4 -1
  489. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +111 -16
  490. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +242 -12
  491. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +114 -58
  492. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  493. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +57 -0
  494. data/spec/mongoid/association/referenced/belongs_to_spec.rb +28 -21
  495. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +3 -1
  496. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +28 -1
  497. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +46 -2
  498. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +25 -5
  499. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +559 -385
  500. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +68 -2
  501. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +39 -0
  502. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +81 -4
  503. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +3 -1
  504. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +132 -0
  505. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +40 -9
  506. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +415 -129
  507. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +859 -502
  508. data/spec/mongoid/association/referenced/has_many_models.rb +61 -1
  509. data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
  510. data/spec/mongoid/association/referenced/has_many_spec.rb +48 -0
  511. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +2 -0
  512. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +55 -9
  513. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +34 -4
  514. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +135 -27
  515. data/spec/mongoid/association/referenced/has_one_models.rb +65 -0
  516. data/spec/mongoid/association/referenced/has_one_query_spec.rb +37 -0
  517. data/spec/mongoid/association/referenced/has_one_spec.rb +24 -1
  518. data/spec/mongoid/association/reflections_spec.rb +2 -0
  519. data/spec/mongoid/association/syncable_spec.rb +48 -32
  520. data/spec/mongoid/association_spec.rb +2 -0
  521. data/spec/mongoid/atomic/modifiers_spec.rb +49 -0
  522. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +2 -0
  523. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +2 -0
  524. data/spec/mongoid/atomic/paths/root_spec.rb +2 -0
  525. data/spec/mongoid/atomic/paths_spec.rb +93 -12
  526. data/spec/mongoid/atomic_spec.rb +53 -6
  527. data/spec/mongoid/attributes/dynamic_spec.rb +152 -0
  528. data/spec/mongoid/attributes/nested_spec.rb +149 -78
  529. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  530. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  531. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  532. data/spec/mongoid/attributes/projector_spec.rb +40 -0
  533. data/spec/mongoid/attributes/readonly_spec.rb +24 -22
  534. data/spec/mongoid/attributes_spec.rb +895 -54
  535. data/spec/mongoid/cacheable_spec.rb +6 -4
  536. data/spec/mongoid/changeable_spec.rb +484 -67
  537. data/spec/mongoid/clients/factory_spec.rb +128 -28
  538. data/spec/mongoid/clients/options_spec.rb +49 -30
  539. data/spec/mongoid/clients/sessions_spec.rb +29 -66
  540. data/spec/mongoid/clients/transactions_spec.rb +74 -37
  541. data/spec/mongoid/clients_spec.rb +189 -23
  542. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  543. data/spec/mongoid/composable_spec.rb +2 -0
  544. data/spec/mongoid/config/defaults_spec.rb +160 -0
  545. data/spec/mongoid/config/environment_spec.rb +126 -8
  546. data/spec/mongoid/config/options_spec.rb +22 -3
  547. data/spec/mongoid/config_spec.rb +504 -1
  548. data/spec/mongoid/contextual/aggregable/memory_spec.rb +433 -153
  549. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  550. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  551. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
  552. data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
  553. data/spec/mongoid/contextual/atomic_spec.rb +242 -81
  554. data/spec/mongoid/contextual/geo_near_spec.rb +30 -19
  555. data/spec/mongoid/contextual/map_reduce_spec.rb +22 -19
  556. data/spec/mongoid/contextual/memory_spec.rb +1828 -303
  557. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  558. data/spec/mongoid/contextual/mongo_spec.rb +3504 -1270
  559. data/spec/mongoid/contextual/none_spec.rb +80 -67
  560. data/spec/mongoid/copyable_spec.rb +659 -36
  561. data/spec/mongoid/copyable_spec_models.rb +30 -0
  562. data/spec/mongoid/criteria/findable_spec.rb +161 -228
  563. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  564. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  565. data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
  566. data/spec/mongoid/criteria/marshalable_spec.rb +20 -1
  567. data/spec/mongoid/criteria/modifiable_spec.rb +43 -40
  568. data/spec/mongoid/criteria/options_spec.rb +2 -0
  569. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -1
  570. data/spec/mongoid/criteria/queryable/expandable_spec.rb +61 -0
  571. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +9 -19
  572. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +136 -26
  573. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +3 -1
  574. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +13 -0
  575. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +46 -17
  576. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +2 -0
  577. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +2 -15
  578. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +2 -0
  579. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +2 -0
  580. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -8
  581. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +2 -0
  582. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +239 -178
  583. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +3 -1
  584. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +9 -7
  585. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +2 -0
  586. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +7 -70
  587. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +2 -59
  588. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +53 -23
  589. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +41 -1
  590. data/spec/mongoid/criteria/queryable/key_spec.rb +2 -0
  591. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +145 -12
  592. data/spec/mongoid/criteria/queryable/optional_spec.rb +18 -485
  593. data/spec/mongoid/criteria/queryable/options_spec.rb +3 -1
  594. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +2 -0
  595. data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -1
  596. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +2538 -0
  597. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
  598. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1100 -2880
  599. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
  600. data/spec/mongoid/criteria/queryable/selector_spec.rb +17 -3
  601. data/spec/mongoid/criteria/queryable/smash_spec.rb +2 -0
  602. data/spec/mongoid/criteria/queryable/storable_spec.rb +226 -0
  603. data/spec/mongoid/criteria/scopable_spec.rb +129 -0
  604. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  605. data/spec/mongoid/criteria_projection_spec.rb +406 -0
  606. data/spec/mongoid/criteria_spec.rb +1320 -1723
  607. data/spec/mongoid/document_fields_spec.rb +262 -0
  608. data/spec/mongoid/document_persistence_context_spec.rb +32 -0
  609. data/spec/mongoid/document_query_spec.rb +89 -0
  610. data/spec/mongoid/document_spec.rb +153 -87
  611. data/spec/mongoid/equality_spec.rb +144 -41
  612. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +5 -3
  613. data/spec/mongoid/errors/callback_spec.rb +2 -0
  614. data/spec/mongoid/errors/delete_restriction_spec.rb +4 -2
  615. data/spec/mongoid/errors/document_not_destroyed_spec.rb +2 -0
  616. data/spec/mongoid/errors/document_not_found_spec.rb +78 -0
  617. data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
  618. data/spec/mongoid/errors/{eager_load_spec.rb → invalid_config_file_spec.rb} +7 -5
  619. data/spec/mongoid/errors/invalid_config_option_spec.rb +2 -0
  620. data/spec/mongoid/errors/invalid_field_option_spec.rb +2 -0
  621. data/spec/mongoid/errors/invalid_field_spec.rb +3 -1
  622. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  623. data/spec/mongoid/errors/invalid_find_spec.rb +2 -0
  624. data/spec/mongoid/errors/invalid_includes_spec.rb +2 -0
  625. data/spec/mongoid/errors/invalid_index_spec.rb +2 -0
  626. data/spec/mongoid/errors/invalid_options_spec.rb +4 -2
  627. data/spec/mongoid/errors/invalid_path_spec.rb +2 -0
  628. data/spec/mongoid/errors/invalid_relation_spec.rb +4 -2
  629. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -1
  630. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +2 -0
  631. data/spec/mongoid/errors/invalid_storage_options_spec.rb +2 -0
  632. data/spec/mongoid/errors/invalid_time_spec.rb +2 -0
  633. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -1
  634. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +2 -0
  635. data/spec/mongoid/errors/mixed_relations_spec.rb +2 -0
  636. data/spec/mongoid/errors/mongoid_error_spec.rb +24 -8
  637. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +5 -3
  638. data/spec/mongoid/errors/no_client_config_spec.rb +4 -2
  639. data/spec/mongoid/errors/no_client_database_spec.rb +5 -3
  640. data/spec/mongoid/errors/no_client_hosts_spec.rb +5 -3
  641. data/spec/mongoid/errors/no_clients_config_spec.rb +2 -0
  642. data/spec/mongoid/errors/no_environment_spec.rb +5 -3
  643. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +2 -0
  644. data/spec/mongoid/errors/no_metadata_spec.rb +4 -2
  645. data/spec/mongoid/errors/no_parent_spec.rb +3 -1
  646. data/spec/mongoid/errors/readonly_attribute_spec.rb +2 -0
  647. data/spec/mongoid/errors/readonly_document_spec.rb +4 -2
  648. data/spec/mongoid/errors/scope_overwrite_spec.rb +2 -0
  649. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -1
  650. data/spec/mongoid/errors/unknown_attribute_spec.rb +4 -2
  651. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -1
  652. data/spec/mongoid/errors/unsupported_javascript_spec.rb +2 -0
  653. data/spec/mongoid/errors/validations_spec.rb +2 -0
  654. data/spec/mongoid/extensions/array_spec.rb +41 -45
  655. data/spec/mongoid/extensions/big_decimal_spec.rb +714 -212
  656. data/spec/mongoid/extensions/binary_spec.rb +46 -9
  657. data/spec/mongoid/extensions/boolean_spec.rb +70 -82
  658. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +339 -0
  659. data/spec/mongoid/extensions/date_spec.rb +58 -140
  660. data/spec/mongoid/extensions/date_time_spec.rb +32 -69
  661. data/spec/mongoid/extensions/decimal128_spec.rb +2 -0
  662. data/spec/mongoid/extensions/false_class_spec.rb +3 -1
  663. data/spec/mongoid/extensions/float_spec.rb +66 -73
  664. data/spec/mongoid/extensions/hash_spec.rb +135 -0
  665. data/spec/mongoid/extensions/integer_spec.rb +61 -63
  666. data/spec/mongoid/extensions/module_spec.rb +2 -0
  667. data/spec/mongoid/extensions/nil_class_spec.rb +2 -0
  668. data/spec/mongoid/extensions/object_id_spec.rb +2 -0
  669. data/spec/mongoid/extensions/object_spec.rb +13 -24
  670. data/spec/mongoid/extensions/range_spec.rb +257 -54
  671. data/spec/mongoid/extensions/regexp_spec.rb +60 -33
  672. data/spec/mongoid/extensions/set_spec.rb +108 -0
  673. data/spec/mongoid/extensions/string_spec.rb +111 -50
  674. data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
  675. data/spec/mongoid/extensions/symbol_spec.rb +20 -25
  676. data/spec/mongoid/extensions/time_spec.rb +668 -106
  677. data/spec/mongoid/extensions/time_with_zone_spec.rb +57 -83
  678. data/spec/mongoid/extensions/true_class_spec.rb +3 -1
  679. data/spec/mongoid/extensions_spec.rb +16 -2
  680. data/spec/mongoid/factory_spec.rb +347 -27
  681. data/spec/mongoid/fields/foreign_key_spec.rb +2 -0
  682. data/spec/mongoid/fields/localized_spec.rb +86 -41
  683. data/spec/mongoid/fields/standard_spec.rb +2 -0
  684. data/spec/mongoid/fields_spec.rb +869 -114
  685. data/spec/mongoid/findable_spec.rb +520 -64
  686. data/spec/mongoid/indexable/specification_spec.rb +4 -2
  687. data/spec/mongoid/indexable_spec.rb +87 -32
  688. data/spec/mongoid/inspectable_spec.rb +39 -2
  689. data/spec/mongoid/interceptable_spec.rb +761 -98
  690. data/spec/mongoid/interceptable_spec_models.rb +307 -0
  691. data/spec/mongoid/loggable_spec.rb +2 -0
  692. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  693. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
  694. data/spec/mongoid/matcher/extract_attribute_spec.rb +36 -0
  695. data/spec/mongoid/mongoizable_spec.rb +285 -0
  696. data/spec/mongoid/persistable/creatable_spec.rb +114 -29
  697. data/spec/mongoid/persistable/deletable_spec.rb +300 -18
  698. data/spec/mongoid/persistable/destroyable_spec.rb +228 -18
  699. data/spec/mongoid/persistable/incrementable_spec.rb +60 -7
  700. data/spec/mongoid/persistable/logical_spec.rb +56 -3
  701. data/spec/mongoid/persistable/poppable_spec.rb +55 -3
  702. data/spec/mongoid/persistable/pullable_spec.rb +108 -6
  703. data/spec/mongoid/persistable/pushable_spec.rb +163 -7
  704. data/spec/mongoid/persistable/renamable_spec.rb +54 -2
  705. data/spec/mongoid/persistable/savable_spec.rb +284 -25
  706. data/spec/mongoid/persistable/settable_spec.rb +91 -8
  707. data/spec/mongoid/persistable/unsettable_spec.rb +55 -3
  708. data/spec/mongoid/persistable/updatable_spec.rb +63 -49
  709. data/spec/mongoid/persistable/upsertable_spec.rb +93 -3
  710. data/spec/mongoid/persistable_spec.rb +85 -9
  711. data/spec/mongoid/persistence_context_spec.rb +59 -58
  712. data/spec/mongoid/positional_spec.rb +2 -0
  713. data/spec/mongoid/query_cache_middleware_spec.rb +50 -0
  714. data/spec/mongoid/query_cache_spec.rb +410 -95
  715. data/spec/mongoid/relations/proxy_spec.rb +9 -7
  716. data/spec/mongoid/reloadable_spec.rb +357 -26
  717. data/spec/mongoid/scopable_spec.rb +193 -38
  718. data/spec/mongoid/selectable_spec.rb +8 -6
  719. data/spec/mongoid/serializable_spec.rb +148 -38
  720. data/spec/mongoid/shardable_models.rb +75 -0
  721. data/spec/mongoid/shardable_spec.rb +239 -34
  722. data/spec/mongoid/stateful_spec.rb +153 -9
  723. data/spec/mongoid/tasks/database_rake_spec.rb +89 -13
  724. data/spec/mongoid/tasks/database_spec.rb +130 -1
  725. data/spec/mongoid/threaded_spec.rb +4 -2
  726. data/spec/mongoid/timestamps/created/short_spec.rb +3 -1
  727. data/spec/mongoid/timestamps/created_spec.rb +3 -1
  728. data/spec/mongoid/timestamps/timeless_spec.rb +4 -2
  729. data/spec/mongoid/timestamps/updated/short_spec.rb +5 -3
  730. data/spec/mongoid/timestamps/updated_spec.rb +5 -3
  731. data/spec/mongoid/timestamps_spec.rb +400 -10
  732. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  733. data/spec/mongoid/touchable_spec.rb +568 -33
  734. data/spec/mongoid/touchable_spec_models.rb +59 -0
  735. data/spec/mongoid/traversable_spec.rb +1145 -1
  736. data/spec/mongoid/validatable/associated_spec.rb +2 -0
  737. data/spec/mongoid/validatable/format_spec.rb +2 -0
  738. data/spec/mongoid/validatable/length_spec.rb +2 -0
  739. data/spec/mongoid/validatable/numericality_spec.rb +2 -0
  740. data/spec/mongoid/validatable/presence_spec.rb +28 -22
  741. data/spec/mongoid/validatable/uniqueness_spec.rb +159 -103
  742. data/spec/mongoid/validatable_spec.rb +5 -3
  743. data/spec/mongoid/warnings_spec.rb +35 -0
  744. data/spec/mongoid_spec.rb +37 -9
  745. data/spec/rails/controller_extension/controller_runtime_spec.rb +5 -3
  746. data/spec/rails/mongoid_spec.rb +8 -18
  747. data/spec/shared/LICENSE +20 -0
  748. data/spec/shared/bin/get-mongodb-download-url +17 -0
  749. data/spec/shared/bin/s3-copy +45 -0
  750. data/spec/shared/bin/s3-upload +69 -0
  751. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  752. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  753. data/spec/shared/lib/mrss/constraints.rb +378 -0
  754. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  755. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  756. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  757. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  758. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  759. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  760. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  761. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  762. data/spec/shared/lib/mrss/utils.rb +37 -0
  763. data/spec/shared/share/Dockerfile.erb +321 -0
  764. data/spec/shared/share/haproxy-1.conf +16 -0
  765. data/spec/shared/share/haproxy-2.conf +17 -0
  766. data/spec/shared/shlib/config.sh +27 -0
  767. data/spec/shared/shlib/distro.sh +74 -0
  768. data/spec/shared/shlib/server.sh +416 -0
  769. data/spec/shared/shlib/set_env.sh +169 -0
  770. data/spec/spec_helper.rb +44 -66
  771. data/spec/support/authorization.rb +2 -0
  772. data/spec/support/client_registry.rb +9 -0
  773. data/spec/support/constraints.rb +45 -69
  774. data/spec/support/expectations.rb +21 -3
  775. data/spec/support/helpers.rb +11 -0
  776. data/spec/support/immutable_ids.rb +118 -0
  777. data/spec/support/macros.rb +109 -0
  778. data/spec/{app → support}/models/account.rb +3 -1
  779. data/spec/{app → support}/models/acolyte.rb +2 -0
  780. data/spec/{app → support}/models/actor.rb +3 -1
  781. data/spec/support/models/actress.rb +4 -0
  782. data/spec/{app → support}/models/address.rb +6 -0
  783. data/spec/{app → support}/models/address_component.rb +2 -0
  784. data/spec/{app → support}/models/address_number.rb +2 -0
  785. data/spec/{app → support}/models/agency.rb +2 -0
  786. data/spec/{app → support}/models/agent.rb +2 -0
  787. data/spec/{app → support}/models/album.rb +2 -0
  788. data/spec/{app → support}/models/alert.rb +2 -0
  789. data/spec/{app → support}/models/animal.rb +2 -0
  790. data/spec/{app → support}/models/answer.rb +2 -0
  791. data/spec/{app → support}/models/appointment.rb +2 -0
  792. data/spec/support/models/armrest.rb +9 -0
  793. data/spec/{app → support}/models/article.rb +2 -0
  794. data/spec/{app → support}/models/artist.rb +4 -1
  795. data/spec/{app → support}/models/artwork.rb +2 -0
  796. data/spec/support/models/audible_sound.rb +3 -0
  797. data/spec/{app → support}/models/audio.rb +2 -0
  798. data/spec/support/models/augmentation.rb +25 -0
  799. data/spec/{app → support}/models/author.rb +2 -0
  800. data/spec/{app → support}/models/baby.rb +2 -0
  801. data/spec/{app → support}/models/band.rb +10 -0
  802. data/spec/{app → support}/models/bar.rb +2 -0
  803. data/spec/{app → support}/models/basic.rb +2 -0
  804. data/spec/support/models/bed.rb +3 -0
  805. data/spec/{app → support}/models/big_palette.rb +2 -0
  806. data/spec/{app → support}/models/birthday.rb +2 -0
  807. data/spec/support/models/bolt.rb +7 -0
  808. data/spec/{app → support}/models/bomb.rb +2 -0
  809. data/spec/{app → support}/models/book.rb +3 -0
  810. data/spec/{app → support}/models/breed.rb +2 -0
  811. data/spec/{app → support}/models/browser.rb +3 -1
  812. data/spec/{app → support}/models/building.rb +4 -0
  813. data/spec/{app → support}/models/building_address.rb +2 -0
  814. data/spec/{app → support}/models/bus.rb +2 -0
  815. data/spec/{app → support}/models/business.rb +2 -0
  816. data/spec/{app → support}/models/callback_test.rb +2 -0
  817. data/spec/{app → support}/models/canvas.rb +3 -1
  818. data/spec/support/models/car.rb +3 -0
  819. data/spec/{app → support}/models/cat.rb +2 -0
  820. data/spec/support/models/catalog.rb +24 -0
  821. data/spec/{app → support}/models/category.rb +2 -0
  822. data/spec/{app → support}/models/child.rb +2 -0
  823. data/spec/{app → support}/models/child_doc.rb +5 -3
  824. data/spec/{app → support}/models/church.rb +2 -0
  825. data/spec/{app → support}/models/circle.rb +2 -0
  826. data/spec/{app → support}/models/circuit.rb +2 -0
  827. data/spec/support/models/circus.rb +12 -0
  828. data/spec/{app → support}/models/code.rb +4 -0
  829. data/spec/support/models/coding/pull_request.rb +11 -0
  830. data/spec/support/models/coding.rb +3 -0
  831. data/spec/{app → support}/models/comment.rb +2 -0
  832. data/spec/{app → support}/models/company.rb +2 -0
  833. data/spec/{app → support}/models/consumption_period.rb +2 -0
  834. data/spec/{app → support}/models/contextable_item.rb +2 -0
  835. data/spec/{app → support}/models/contractor.rb +2 -0
  836. data/spec/{app → support}/models/cookie.rb +2 -0
  837. data/spec/{app → support}/models/country_code.rb +4 -0
  838. data/spec/{app → support}/models/courier_job.rb +2 -0
  839. data/spec/support/models/cover.rb +10 -0
  840. data/spec/support/models/crate.rb +12 -0
  841. data/spec/support/models/customer.rb +10 -0
  842. data/spec/support/models/customer_address.rb +11 -0
  843. data/spec/support/models/deed.rb +7 -0
  844. data/spec/{app → support}/models/definition.rb +2 -0
  845. data/spec/support/models/delegating_patient.rb +15 -0
  846. data/spec/{app → support}/models/description.rb +2 -0
  847. data/spec/{app → support}/models/dictionary.rb +8 -0
  848. data/spec/{app → support}/models/division.rb +2 -0
  849. data/spec/{app → support}/models/doctor.rb +2 -0
  850. data/spec/{app → support}/models/dog.rb +2 -0
  851. data/spec/{app → support}/models/dokument.rb +2 -0
  852. data/spec/{app → support}/models/draft.rb +2 -0
  853. data/spec/{app → support}/models/dragon.rb +2 -0
  854. data/spec/{app → support}/models/driver.rb +3 -1
  855. data/spec/{app → support}/models/drug.rb +2 -0
  856. data/spec/{app → support}/models/dungeon.rb +2 -0
  857. data/spec/{app → support}/models/edit.rb +2 -0
  858. data/spec/{app → support}/models/email.rb +2 -0
  859. data/spec/{app → support}/models/employer.rb +2 -0
  860. data/spec/{app → support}/models/entry.rb +2 -0
  861. data/spec/support/models/eraser.rb +3 -0
  862. data/spec/{app → support}/models/even.rb +2 -0
  863. data/spec/{app → support}/models/event.rb +2 -0
  864. data/spec/{app → support}/models/exhibition.rb +2 -0
  865. data/spec/{app → support}/models/exhibitor.rb +2 -0
  866. data/spec/{app → support}/models/explosion.rb +2 -0
  867. data/spec/{app → support}/models/eye.rb +2 -0
  868. data/spec/{app → support}/models/eye_bowl.rb +2 -0
  869. data/spec/{app → support}/models/face.rb +2 -0
  870. data/spec/support/models/fanatic.rb +8 -0
  871. data/spec/{app → support}/models/favorite.rb +2 -0
  872. data/spec/{app → support}/models/filesystem.rb +2 -0
  873. data/spec/{app → support}/models/fire_hydrant.rb +2 -0
  874. data/spec/{app → support}/models/firefox.rb +2 -0
  875. data/spec/{app → support}/models/fish.rb +2 -0
  876. data/spec/{app → support}/models/folder.rb +2 -0
  877. data/spec/{app → support}/models/folder_item.rb +2 -0
  878. data/spec/{app → support}/models/fruits.rb +2 -0
  879. data/spec/{app → support}/models/game.rb +2 -0
  880. data/spec/{app → support}/models/ghost.rb +2 -0
  881. data/spec/support/models/guitar.rb +4 -0
  882. data/spec/support/models/hole.rb +12 -0
  883. data/spec/{app → support}/models/home.rb +2 -0
  884. data/spec/{app → support}/models/house.rb +2 -0
  885. data/spec/{app → support}/models/html_writer.rb +2 -0
  886. data/spec/{app → support}/models/id_key.rb +2 -0
  887. data/spec/support/models/idnodef.rb +7 -0
  888. data/spec/{app → support}/models/image.rb +2 -0
  889. data/spec/{app → support}/models/implant.rb +11 -0
  890. data/spec/support/models/instrument.rb +8 -0
  891. data/spec/{app → support}/models/item.rb +3 -1
  892. data/spec/{app → support}/models/jar.rb +2 -0
  893. data/spec/{app → support}/models/kaleidoscope.rb +2 -0
  894. data/spec/{app → support}/models/kangaroo.rb +3 -1
  895. data/spec/{app → support}/models/label.rb +6 -1
  896. data/spec/{app → support}/models/language.rb +2 -0
  897. data/spec/{app → support}/models/lat_lng.rb +2 -0
  898. data/spec/{app → support}/models/league.rb +2 -0
  899. data/spec/support/models/learner.rb +4 -0
  900. data/spec/{app → support}/models/line_item.rb +2 -0
  901. data/spec/{app → support}/models/location.rb +2 -0
  902. data/spec/{app → support}/models/login.rb +2 -0
  903. data/spec/{app → support}/models/manufacturer.rb +2 -0
  904. data/spec/{app → support}/models/meat.rb +2 -0
  905. data/spec/{app → support}/models/membership.rb +3 -0
  906. data/spec/{app → support}/models/message.rb +2 -0
  907. data/spec/{app → support}/models/minim.rb +0 -1
  908. data/spec/{app → support}/models/mixed_drink.rb +2 -0
  909. data/spec/support/models/mop.rb +24 -0
  910. data/spec/{app → support}/models/movie.rb +2 -0
  911. data/spec/support/models/my_hash.rb +4 -0
  912. data/spec/{app → support}/models/name.rb +2 -0
  913. data/spec/support/models/name_only.rb +8 -0
  914. data/spec/{app → support}/models/node.rb +2 -0
  915. data/spec/{app → support}/models/note.rb +2 -0
  916. data/spec/support/models/nut.rb +7 -0
  917. data/spec/{app → support}/models/odd.rb +2 -0
  918. data/spec/support/models/order.rb +12 -0
  919. data/spec/{app → support}/models/ordered_post.rb +3 -1
  920. data/spec/{app → support}/models/ordered_preference.rb +2 -0
  921. data/spec/{app → support}/models/oscar.rb +2 -0
  922. data/spec/support/models/other_owner_object.rb +4 -0
  923. data/spec/{app → support}/models/override.rb +2 -0
  924. data/spec/{app → support}/models/ownable.rb +2 -0
  925. data/spec/{app → support}/models/owner.rb +4 -0
  926. data/spec/{app → support}/models/pack.rb +2 -0
  927. data/spec/{app → support}/models/page.rb +2 -0
  928. data/spec/{app → support}/models/page_question.rb +2 -0
  929. data/spec/{app → support}/models/palette.rb +3 -1
  930. data/spec/{app → support}/models/parent.rb +2 -0
  931. data/spec/{app → support}/models/parent_doc.rb +2 -0
  932. data/spec/support/models/passport.rb +22 -0
  933. data/spec/{app → support}/models/patient.rb +2 -0
  934. data/spec/{app → support}/models/pdf_writer.rb +2 -0
  935. data/spec/support/models/pencil.rb +3 -0
  936. data/spec/{app → support}/models/person.rb +22 -1
  937. data/spec/{app → support}/models/pet.rb +2 -0
  938. data/spec/{app → support}/models/pet_owner.rb +2 -0
  939. data/spec/{app → support}/models/phone.rb +5 -1
  940. data/spec/support/models/piano.rb +4 -0
  941. data/spec/{app → support}/models/pizza.rb +2 -0
  942. data/spec/{app → support}/models/player.rb +4 -0
  943. data/spec/{app → support}/models/post.rb +2 -0
  944. data/spec/{app → support}/models/post_genre.rb +2 -0
  945. data/spec/support/models/powerup.rb +25 -0
  946. data/spec/{app → support}/models/preference.rb +2 -0
  947. data/spec/{app → support}/models/princess.rb +2 -0
  948. data/spec/{app → support}/models/product.rb +3 -0
  949. data/spec/support/models/profile.rb +17 -0
  950. data/spec/{app → support}/models/pronunciation.rb +2 -0
  951. data/spec/{app → support}/models/pub.rb +2 -0
  952. data/spec/support/models/publication/encyclopedia.rb +11 -0
  953. data/spec/support/models/publication/review.rb +13 -0
  954. data/spec/support/models/publication.rb +4 -0
  955. data/spec/{app → support}/models/purchase.rb +2 -0
  956. data/spec/support/models/purchased_item.rb +10 -0
  957. data/spec/{app → support}/models/question.rb +2 -0
  958. data/spec/{app → support}/models/quiz.rb +2 -0
  959. data/spec/{app → support}/models/rating.rb +2 -0
  960. data/spec/{app → support}/models/record.rb +2 -0
  961. data/spec/{app → support}/models/registry.rb +3 -0
  962. data/spec/{app → support}/models/role.rb +2 -0
  963. data/spec/{app → support}/models/root_category.rb +2 -0
  964. data/spec/{app → support}/models/sandwich.rb +2 -0
  965. data/spec/{app → support}/models/scheduler.rb +2 -0
  966. data/spec/support/models/school.rb +14 -0
  967. data/spec/support/models/scribe.rb +7 -0
  968. data/spec/support/models/sealer.rb +7 -0
  969. data/spec/support/models/seat.rb +24 -0
  970. data/spec/{app → support}/models/seo.rb +2 -0
  971. data/spec/support/models/series.rb +7 -0
  972. data/spec/{app → support}/models/server.rb +2 -0
  973. data/spec/{app → support}/models/service.rb +2 -0
  974. data/spec/{app → support}/models/shape.rb +4 -2
  975. data/spec/{app → support}/models/shelf.rb +2 -0
  976. data/spec/support/models/shield.rb +18 -0
  977. data/spec/{app → support}/models/shipment_address.rb +2 -0
  978. data/spec/{app → support}/models/shipping_container.rb +2 -0
  979. data/spec/{app → support}/models/shipping_pack.rb +2 -0
  980. data/spec/support/models/shirt.rb +11 -0
  981. data/spec/{app → support}/models/shop.rb +2 -0
  982. data/spec/{app → support}/models/short_agent.rb +2 -0
  983. data/spec/{app → support}/models/short_quiz.rb +2 -0
  984. data/spec/{app → support}/models/simple.rb +2 -0
  985. data/spec/{app → support}/models/slave.rb +2 -0
  986. data/spec/{app → support}/models/song.rb +2 -0
  987. data/spec/{app → support}/models/sound.rb +2 -0
  988. data/spec/support/models/spacer.rb +7 -0
  989. data/spec/{app → support}/models/square.rb +2 -0
  990. data/spec/{app → support}/models/staff.rb +2 -0
  991. data/spec/{app → support}/models/store_as_dup_test1.rb +2 -0
  992. data/spec/{app → support}/models/store_as_dup_test2.rb +2 -0
  993. data/spec/{app → support}/models/strategy.rb +2 -0
  994. data/spec/support/models/student.rb +14 -0
  995. data/spec/{app → support}/models/sub_item.rb +2 -0
  996. data/spec/{app → support}/models/subscription.rb +2 -0
  997. data/spec/{app → support}/models/survey.rb +2 -0
  998. data/spec/{app → support}/models/symptom.rb +2 -0
  999. data/spec/support/models/system_role.rb +7 -0
  1000. data/spec/{app → support}/models/tag.rb +2 -0
  1001. data/spec/{app → support}/models/target.rb +2 -0
  1002. data/spec/{app → support}/models/template.rb +2 -0
  1003. data/spec/{app → support}/models/thing.rb +2 -0
  1004. data/spec/support/models/threadlocker.rb +7 -0
  1005. data/spec/{app → support}/models/title.rb +2 -0
  1006. data/spec/{app → support}/models/tool.rb +4 -2
  1007. data/spec/{app → support}/models/topping.rb +2 -0
  1008. data/spec/support/models/toy.rb +9 -0
  1009. data/spec/{app → support}/models/track.rb +2 -0
  1010. data/spec/{app → support}/models/translation.rb +2 -0
  1011. data/spec/{app → support}/models/tree.rb +2 -0
  1012. data/spec/support/models/truck.rb +7 -0
  1013. data/spec/{app → support}/models/user.rb +2 -0
  1014. data/spec/{app → support}/models/user_account.rb +2 -0
  1015. data/spec/{app → support}/models/validation_callback.rb +2 -0
  1016. data/spec/support/models/vehicle.rb +18 -0
  1017. data/spec/{app → support}/models/version.rb +2 -0
  1018. data/spec/{app → support}/models/vertex.rb +3 -1
  1019. data/spec/{app → support}/models/vet_visit.rb +2 -0
  1020. data/spec/{app → support}/models/video.rb +2 -0
  1021. data/spec/support/models/video_game.rb +3 -0
  1022. data/spec/support/models/washer.rb +7 -0
  1023. data/spec/support/models/weapon.rb +25 -0
  1024. data/spec/{app → support}/models/wiki_page.rb +3 -0
  1025. data/spec/{app → support}/models/word.rb +2 -0
  1026. data/spec/{app → support}/models/word_origin.rb +2 -0
  1027. data/spec/{app → support}/models/writer.rb +4 -2
  1028. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  1029. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  1030. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  1031. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  1032. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  1033. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  1034. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  1035. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  1036. data/spec/support/schema_maps/schema_map_local.json +18 -0
  1037. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  1038. data/spec/support/shared/time.rb +53 -0
  1039. data/spec/support/spec_config.rb +30 -5
  1040. data.tar.gz.sig +0 -0
  1041. metadata +1240 -742
  1042. metadata.gz.sig +0 -0
  1043. data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
  1044. data/lib/mongoid/errors/eager_load.rb +0 -22
  1045. data/lib/mongoid/errors/invalid_value.rb +0 -16
  1046. data/lib/mongoid/matchable/all.rb +0 -27
  1047. data/lib/mongoid/matchable/and.rb +0 -30
  1048. data/lib/mongoid/matchable/default.rb +0 -72
  1049. data/lib/mongoid/matchable/elem_match.rb +0 -34
  1050. data/lib/mongoid/matchable/eq.rb +0 -22
  1051. data/lib/mongoid/matchable/exists.rb +0 -23
  1052. data/lib/mongoid/matchable/gt.rb +0 -23
  1053. data/lib/mongoid/matchable/gte.rb +0 -23
  1054. data/lib/mongoid/matchable/in.rb +0 -24
  1055. data/lib/mongoid/matchable/lt.rb +0 -23
  1056. data/lib/mongoid/matchable/lte.rb +0 -23
  1057. data/lib/mongoid/matchable/ne.rb +0 -21
  1058. data/lib/mongoid/matchable/nin.rb +0 -22
  1059. data/lib/mongoid/matchable/nor.rb +0 -37
  1060. data/lib/mongoid/matchable/or.rb +0 -33
  1061. data/lib/mongoid/matchable/regexp.rb +0 -27
  1062. data/lib/mongoid/matchable/size.rb +0 -21
  1063. data/lib/support/ruby_version.rb +0 -26
  1064. data/spec/app/models/actress.rb +0 -2
  1065. data/spec/app/models/augmentation.rb +0 -11
  1066. data/spec/app/models/bed.rb +0 -1
  1067. data/spec/app/models/car.rb +0 -1
  1068. data/spec/app/models/circus.rb +0 -7
  1069. data/spec/app/models/eraser.rb +0 -1
  1070. data/spec/app/models/learner.rb +0 -2
  1071. data/spec/app/models/my_hash.rb +0 -2
  1072. data/spec/app/models/other_owner_object.rb +0 -2
  1073. data/spec/app/models/passport.rb +0 -5
  1074. data/spec/app/models/pencil.rb +0 -1
  1075. data/spec/app/models/powerup.rb +0 -11
  1076. data/spec/app/models/profile.rb +0 -5
  1077. data/spec/app/models/series.rb +0 -4
  1078. data/spec/app/models/truck.rb +0 -3
  1079. data/spec/app/models/vehicle.rb +0 -11
  1080. data/spec/app/models/video_game.rb +0 -1
  1081. data/spec/app/models/weapon.rb +0 -11
  1082. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -58
  1083. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -58
  1084. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
  1085. data/spec/mongoid/matchable/all_spec.rb +0 -31
  1086. data/spec/mongoid/matchable/and_spec.rb +0 -187
  1087. data/spec/mongoid/matchable/default_spec.rb +0 -130
  1088. data/spec/mongoid/matchable/elem_match_spec.rb +0 -106
  1089. data/spec/mongoid/matchable/eq_spec.rb +0 -48
  1090. data/spec/mongoid/matchable/exists_spec.rb +0 -57
  1091. data/spec/mongoid/matchable/gt_spec.rb +0 -86
  1092. data/spec/mongoid/matchable/gte_spec.rb +0 -84
  1093. data/spec/mongoid/matchable/in_spec.rb +0 -49
  1094. data/spec/mongoid/matchable/lt_spec.rb +0 -85
  1095. data/spec/mongoid/matchable/lte_spec.rb +0 -85
  1096. data/spec/mongoid/matchable/ne_spec.rb +0 -46
  1097. data/spec/mongoid/matchable/nin_spec.rb +0 -48
  1098. data/spec/mongoid/matchable/nor_spec.rb +0 -209
  1099. data/spec/mongoid/matchable/or_spec.rb +0 -131
  1100. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
  1101. data/spec/mongoid/matchable/size_spec.rb +0 -25
  1102. data/spec/mongoid/matchable_spec.rb +0 -853
  1103. data/spec/support/cluster_config.rb +0 -158
  1104. /data/spec/{app → support}/models/array_field.rb +0 -0
  1105. /data/spec/{app → support}/models/store_as_dup_test3.rb +0 -0
  1106. /data/spec/{app → support}/models/store_as_dup_test4.rb +0 -0
  1107. /data/spec/{app → support}/models/updatable.rb +0 -0
@@ -1,43 +1,262 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require "spec_helper"
4
+ require_relative './selectable_shared_examples'
5
+
6
+ class FieldWithSerializer
7
+ def evolve(object)
8
+ Integer.evolve(object)
9
+ end
10
+
11
+ def localized?
12
+ false
13
+ end
14
+ end
2
15
 
3
16
  describe Mongoid::Criteria::Queryable::Selectable do
4
17
 
5
18
  let(:query) do
6
- Mongoid::Query.new("id" => "_id")
19
+ Mongoid::Query.new("id" => "_id")
7
20
  end
8
21
 
9
- shared_examples_for "a cloning selection" do
22
+ shared_examples_for 'supports merge strategies' do
23
+
24
+ context 'when the field is not aliased' do
25
+
26
+ context "when the strategy is not set" do
27
+
28
+ let(:selection) do
29
+ query.send(query_method, first: [ 1, 2 ]).send(query_method, first: [ 3, 4 ])
30
+ end
31
+
32
+ it "combines the conditions with $and" do
33
+ expect(selection.selector).to eq({
34
+ "first" => { operator => [ 1, 2 ] },
35
+ '$and' => [{'first' => {operator => [3, 4]}}],
36
+ })
37
+ end
38
+
39
+ it_behaves_like "returns a cloned query"
40
+ end
41
+
42
+ context "when the strategy is intersect" do
43
+
44
+ let(:selection) do
45
+ query.send(query_method, first: [ 1, 2 ]).intersect.send(query_method, first: [ 2, 3 ])
46
+ end
47
+
48
+ it "intersects the conditions" do
49
+ expect(selection.selector).to eq({
50
+ "first" => { operator => [ 2 ] }
51
+ })
52
+ end
53
+
54
+ it_behaves_like "returns a cloned query"
55
+ end
56
+
57
+ context "when the strategy is override" do
58
+
59
+ let(:selection) do
60
+ query.send(query_method, first: [ 1, 2 ]).override.send(query_method, first: [ 3, 4 ])
61
+ end
62
+
63
+ it "overwrites the first condition" do
64
+ expect(selection.selector).to eq({
65
+ "first" => { operator => [ 3, 4 ] }
66
+ })
67
+ end
68
+
69
+ it_behaves_like "returns a cloned query"
70
+ end
71
+
72
+ context "when the strategy is union" do
73
+
74
+ let(:selection) do
75
+ query.send(query_method, first: [ 1, 2 ]).union.send(query_method, first: [ 3, 4 ])
76
+ end
77
+
78
+ it "unions the conditions" do
79
+ expect(selection.selector).to eq({
80
+ "first" => { operator => [ 1, 2, 3, 4 ] }
81
+ })
82
+ end
10
83
 
11
- it "returns a cloned query" do
12
- expect(selection).to_not equal(query)
84
+ it_behaves_like "returns a cloned query"
85
+ end
13
86
  end
14
- end
15
87
 
16
- describe "#all" do
88
+ context 'when the field is aliased' do
17
89
 
18
- context "when provided no criterion" do
90
+ context "when the strategy is not set" do
19
91
 
20
- let(:selection) do
21
- query.all
92
+ let(:selection) do
93
+ query.send(query_method, id: [ 1, 2 ]).send(query_method, _id: [ 3, 4 ])
94
+ end
95
+
96
+ it "combines the conditions with $and" do
97
+ expect(selection.selector).to eq({
98
+ "_id" => { operator => [ 1, 2 ] },
99
+ '$and' => [{'_id' => {operator => [3, 4]}}],
100
+ })
101
+ end
102
+
103
+ it_behaves_like "returns a cloned query"
22
104
  end
23
105
 
24
- it "does not add any criterion" do
25
- expect(selection.selector).to eq({})
106
+ context "when the strategy is intersect" do
107
+
108
+ let(:selection) do
109
+ query.send(query_method, id: [ 1, 2 ]).intersect.send(query_method, _id: [ 2, 3 ])
110
+ end
111
+
112
+ it "intersects the conditions" do
113
+ expect(selection.selector).to eq({
114
+ "_id" => { operator => [ 2 ] }
115
+ })
116
+ end
117
+
118
+ it_behaves_like "returns a cloned query"
26
119
  end
27
120
 
28
- it "returns the query" do
29
- expect(selection).to eq(query)
121
+ context "when the strategy is override" do
122
+
123
+ let(:selection) do
124
+ query.send(query_method, _id: [ 1, 2 ]).override.send(query_method, id: [ 3, 4 ])
125
+ end
126
+
127
+ it "overwrites the first condition" do
128
+ expect(selection.selector).to eq({
129
+ "_id" => { operator => [ 3, 4 ] }
130
+ })
131
+ end
132
+
133
+ it_behaves_like "returns a cloned query"
30
134
  end
31
135
 
32
- it "returns a cloned query" do
33
- expect(selection).to_not equal(query)
136
+ context "when the strategy is union" do
137
+
138
+ let(:selection) do
139
+ query.send(query_method, _id: [ 1, 2 ]).union.send(query_method, id: [ 3, 4 ])
140
+ end
141
+
142
+ it "unions the conditions" do
143
+ expect(selection.selector).to eq({
144
+ "_id" => { operator => [ 1, 2, 3, 4 ] }
145
+ })
146
+ end
147
+
148
+ it_behaves_like "returns a cloned query"
149
+ end
150
+ end
151
+
152
+ context 'when the field uses a serializer' do
153
+
154
+ let(:query) do
155
+ Mongoid::Query.new({}, { "field" => FieldWithSerializer.new })
156
+ end
157
+
158
+
159
+ context "when the strategy is not set" do
160
+
161
+ let(:selection) do
162
+ query.send(query_method, field: [ '1', '2' ]).send(query_method, field: [ '3', '4' ])
163
+ end
164
+
165
+ it "combines the conditions with $and" do
166
+ expect(selection.selector).to eq({
167
+ "field" => { operator => [ 1, 2 ] },
168
+ '$and' => [{'field' => {operator => [3, 4]}}],
169
+ })
170
+ end
171
+
172
+ it_behaves_like "returns a cloned query"
173
+ end
174
+
175
+ context "when the strategy is set" do
176
+
177
+ let(:selection) do
178
+ query.send(query_method, field: [ '1', '2' ]).intersect.send(query_method, field: [ '2', '3' ])
179
+ end
180
+
181
+ it "intersects the conditions" do
182
+ expect(selection.selector).to eq({
183
+ "field" => { operator => [ 2 ] }
184
+ })
185
+ end
186
+
187
+ it_behaves_like "returns a cloned query"
188
+ end
189
+ end
190
+
191
+ context 'when operator value is a Range' do
192
+
193
+ context "when there is no existing condition and strategy is not specified" do
194
+
195
+ let(:selection) do
196
+ query.send(query_method, foo: 2..4)
197
+ end
198
+
199
+ it 'expands range to array' do
200
+ expect(selection.selector).to eq({
201
+ "foo" => { operator => [ 2, 3, 4 ] }
202
+ })
203
+
204
+ end
205
+ end
206
+
207
+ context "when there is no existing condition and strategy is specified" do
208
+
209
+ let(:selection) do
210
+ query.union.send(query_method, foo: 2..4)
211
+ end
212
+
213
+ it 'expands range to array' do
214
+ expect(selection.selector).to eq({
215
+ "foo" => { operator => [ 2, 3, 4 ] }
216
+ })
217
+
218
+ end
219
+ end
220
+
221
+ context "when existing condition has Array value" do
222
+
223
+ let(:selection) do
224
+ query.send(query_method, foo: [ 1, 2 ]).union.send(query_method, foo: 2..4)
225
+ end
226
+
227
+ it 'expands range to array' do
228
+ expect(selection.selector).to eq({
229
+ "foo" => { operator => [ 1, 2, 3, 4 ] }
230
+ })
231
+
232
+ end
233
+ end
234
+
235
+ context "when existing condition has Range value" do
236
+
237
+ let(:selection) do
238
+ query.send(query_method, foo: 1..2).union.send(query_method, foo: 2..4)
239
+ end
240
+
241
+ it 'expands range to array' do
242
+ expect(selection.selector).to eq({
243
+ "foo" => { operator => [ 1, 2, 3, 4 ] }
244
+ })
245
+
246
+ end
34
247
  end
35
248
  end
249
+ end
36
250
 
37
- context "when provided nil" do
251
+ describe "#all" do
252
+
253
+ let(:query_method) { :all }
254
+ let(:operator) { '$all' }
255
+
256
+ context "when provided no criterion" do
38
257
 
39
258
  let(:selection) do
40
- query.all(nil)
259
+ query.all
41
260
  end
42
261
 
43
262
  it "does not add any criterion" do
@@ -53,6 +272,8 @@ describe Mongoid::Criteria::Queryable::Selectable do
53
272
  end
54
273
  end
55
274
 
275
+ it_behaves_like 'requires a non-nil argument'
276
+
56
277
  context "when provided a single criterion" do
57
278
 
58
279
  context "when no serializers are provided" do
@@ -74,23 +295,6 @@ describe Mongoid::Criteria::Queryable::Selectable do
74
295
  end
75
296
  end
76
297
 
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
298
  context "when providing a single value" do
95
299
 
96
300
  let(:selection) do
@@ -147,23 +351,6 @@ describe Mongoid::Criteria::Queryable::Selectable do
147
351
  end
148
352
  end
149
353
 
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
354
  context "when providing a single value" do
168
355
 
169
356
  let(:selection) do
@@ -226,1634 +413,110 @@ describe Mongoid::Criteria::Queryable::Selectable do
226
413
 
227
414
  context "when the criterion are on the same field" do
228
415
 
229
- context "when no serializers are provided" do
416
+ it_behaves_like 'supports merge strategies'
417
+ end
418
+ end
419
+ end
230
420
 
231
- context "when the strategy is the default (union)" do
421
+ describe "#between" do
232
422
 
233
- let(:selection) do
234
- query.all(first: [ 1, 2 ]).all(first: [ 3, 4 ])
235
- end
423
+ let(:query_method) { :between }
236
424
 
237
- it "overwrites the first $all selector" do
238
- expect(selection.selector).to eq({
239
- "first" => { "$all" => [ 1, 2, 3, 4 ] }
240
- })
241
- end
425
+ it_behaves_like 'requires an argument'
426
+ it_behaves_like 'requires a non-nil argument'
242
427
 
243
- it "returns a cloned query" do
244
- expect(selection).to_not equal(query)
245
- end
246
- end
428
+ context "when provided a single range" do
247
429
 
248
- context "when the strategy is intersect" do
430
+ let(:selection) do
431
+ query.between(field: 1..10)
432
+ end
249
433
 
250
- let(:selection) do
251
- query.all(first: [ 1, 2 ]).intersect.all(first: [ 2, 3 ])
252
- end
434
+ it "adds the $gte and $lte selectors" do
435
+ expect(selection.selector).to eq({
436
+ "field" => { "$gte" => 1, "$lte" => 10 }
437
+ })
438
+ end
253
439
 
254
- it "intersects the $all selectors" do
255
- expect(selection.selector).to eq({
256
- "first" => { "$all" => [ 2 ] }
257
- })
258
- end
440
+ it "returns a cloned query" do
441
+ expect(selection).to_not equal(query)
442
+ end
443
+ end
259
444
 
260
- it "returns a cloned query" do
261
- expect(selection).to_not equal(query)
262
- end
263
- end
445
+ context "when provided multiple ranges" do
264
446
 
265
- context "when the strategy is override" do
447
+ context "when the ranges are on different fields" do
266
448
 
267
- let(:selection) do
268
- query.all(first: [ 1, 2 ]).override.all(first: [ 3, 4 ])
269
- end
449
+ let(:selection) do
450
+ query.between(field: 1..10, key: 5..7)
451
+ end
270
452
 
271
- it "overwrites the first $all selector" do
272
- expect(selection.selector).to eq({
273
- "first" => { "$all" => [ 3, 4 ] }
274
- })
275
- end
453
+ it "adds the $gte and $lte selectors" do
454
+ expect(selection.selector).to eq({
455
+ "field" => { "$gte" => 1, "$lte" => 10 },
456
+ "key" => { "$gte" => 5, "$lte" => 7 }
457
+ })
458
+ end
276
459
 
277
- it "returns a cloned query" do
278
- expect(selection).to_not equal(query)
279
- end
280
- end
460
+ it "returns a cloned query" do
461
+ expect(selection).to_not equal(query)
462
+ end
463
+ end
464
+ end
465
+ end
281
466
 
282
- context "when the strategy is union" do
467
+ describe "#elem_match" do
283
468
 
284
- let(:selection) do
285
- query.all(first: [ 1, 2 ]).union.all(first: [ 3, 4 ])
286
- end
469
+ let(:query_method) { :elem_match }
287
470
 
288
- it "unions the $all selectors" do
289
- expect(selection.selector).to eq({
290
- "first" => { "$all" => [ 1, 2, 3, 4 ] }
291
- })
292
- end
471
+ it_behaves_like 'requires an argument'
472
+ it_behaves_like 'requires a non-nil argument'
293
473
 
294
- it "returns a cloned query" do
295
- expect(selection).to_not equal(query)
296
- end
297
- end
298
- end
474
+ context "when provided a criterion" do
299
475
 
300
- context "when serializers are provided" do
476
+ context "when there are no nested complex keys" do
301
477
 
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
478
+ let(:selection) do
479
+ query.elem_match(users: { name: "value" })
480
+ end
312
481
 
313
- after(:all) do
314
- Object.send(:remove_const, :Field)
315
- end
482
+ context "when overwrite_chained_operators is false" do
483
+ config_override :overwrite_chained_operators, false
316
484
 
317
- let!(:query) do
318
- Mongoid::Query.new({}, { "field" => Field.new })
485
+ it "adds the $elemMatch expression" do
486
+ expect(selection.selector).to eq({
487
+ "users" => { "$elemMatch" => { "name" => "value" }}
488
+ })
319
489
  end
490
+ end
320
491
 
321
- context "when the strategy is the default (union)" do
492
+ context "when overwrite_chained_operators is true" do
493
+ config_override :overwrite_chained_operators, true
322
494
 
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
495
+ it "adds the $elemMatch expression" do
496
+ expect(selection.selector).to eq({
497
+ "users" => { "$elemMatch" => { name: "value" }}
498
+ })
387
499
  end
388
500
  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
501
 
645
502
  it "returns a cloned query" do
646
503
  expect(selection).to_not equal(query)
647
504
  end
648
505
  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
506
 
1846
- context "when provided a criterion" do
507
+ context "when there are nested complex keys" do
1847
508
 
1848
- context "when a $near criterion exists on the same field" do
509
+ let(:time) do
510
+ Time.now
511
+ end
1849
512
 
1850
513
  let(:selection) do
1851
- query.near(location: [ 1, 1 ]).max_distance(location: 50)
514
+ query.elem_match(users: { :time.gt => time })
1852
515
  end
1853
516
 
1854
- it "adds the $maxDistance expression" do
517
+ it "adds the $elemMatch expression" do
1855
518
  expect(selection.selector).to eq({
1856
- "location" => { "$near" => [ 1, 1 ], "$maxDistance" => 50 }
519
+ "users" => { "$elemMatch" => { "time" => { "$gt" => time }}}
1857
520
  })
1858
521
  end
1859
522
 
@@ -1862,81 +525,38 @@ describe Mongoid::Criteria::Queryable::Selectable do
1862
525
  end
1863
526
  end
1864
527
  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
528
 
1924
529
  context "when providing multiple criteria" do
1925
530
 
1926
531
  context "when the fields differ" do
1927
532
 
1928
533
  let(:selection) do
1929
- query.mod(
1930
- value: [ 10, 1 ],
1931
- comments: [ 10, 1 ]
534
+ query.elem_match(
535
+ users: { name: "value" },
536
+ comments: { text: "value" }
1932
537
  )
1933
538
  end
1934
539
 
1935
- it "adds the $mod expression" do
1936
- expect(selection.selector).to eq({
1937
- "value" => { "$mod" => [ 10, 1 ] },
1938
- "comments" => { "$mod" => [ 10, 1 ] }
1939
- })
540
+ context "when overwrite_chained_operators is false" do
541
+ config_override :overwrite_chained_operators, false
542
+
543
+ it "adds the $elemMatch expression" do
544
+ expect(selection.selector).to eq({
545
+ "users" => { "$elemMatch" => { "name" => "value" }},
546
+ "comments" => { "$elemMatch" => { "text" => "value" }}
547
+ })
548
+ end
549
+ end
550
+
551
+ context "when overwrite_chained_operators is true" do
552
+ config_override :overwrite_chained_operators, true
553
+
554
+ it "adds the $elemMatch expression" do
555
+ expect(selection.selector).to eq({
556
+ "users" => { "$elemMatch" => { name: "value" }},
557
+ "comments" => { "$elemMatch" => { text: "value" }}
558
+ })
559
+ end
1940
560
  end
1941
561
 
1942
562
  it "returns a cloned query" do
@@ -1951,120 +571,64 @@ describe Mongoid::Criteria::Queryable::Selectable do
1951
571
 
1952
572
  let(:selection) do
1953
573
  query.
1954
- mod(value: [ 10, 1 ]).
1955
- mod(result: [ 10, 1 ])
574
+ elem_match(users: { name: "value" }).
575
+ elem_match(comments: { text: "value" })
1956
576
  end
1957
577
 
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
578
+ context "when overwrite_chained_operators is false" do
579
+ config_override :overwrite_chained_operators, false
1964
580
 
1965
- it "returns a cloned query" do
1966
- expect(selection).to_not equal(query)
581
+ it "adds the $elemMatch expression" do
582
+ expect(selection.selector).to eq({
583
+ "users" => { "$elemMatch" => { "name" => "value" }},
584
+ "comments" => { "$elemMatch" => { "text" => "value" }}
585
+ })
586
+ end
1967
587
  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
588
 
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
589
+ context "when overwrite_chained_operators is true" do
590
+ config_override :overwrite_chained_operators, true
2028
591
 
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
- })
592
+ it "adds the $elemMatch expression" do
593
+ expect(selection.selector).to eq({
594
+ "users" => { "$elemMatch" => { name: "value" }},
595
+ "comments" => { "$elemMatch" => { text: "value" }}
596
+ })
597
+ end
2045
598
  end
2046
599
 
2047
600
  it "returns a cloned query" do
2048
601
  expect(selection).to_not equal(query)
2049
602
  end
2050
603
  end
2051
- end
2052
604
 
2053
- context "when chaining multiple criteria" do
2054
-
2055
- context "when the fields differ" do
605
+ context "when the fields are the same" do
2056
606
 
2057
607
  let(:selection) do
2058
608
  query.
2059
- ne(value: 10).
2060
- ne(result: 10)
609
+ elem_match(users: { name: "value" }).
610
+ elem_match(users: { state: "new" })
2061
611
  end
2062
612
 
2063
- it "adds the $ne expression" do
2064
- expect(selection.selector).to eq({
2065
- "value" => { "$ne" => 10 },
2066
- "result" => { "$ne" => 10 }
2067
- })
613
+ context "when overwrite_chained_operators is false" do
614
+ config_override :overwrite_chained_operators, false
615
+
616
+ it "adds an $elemMatch expression" do
617
+ expect(selection.selector).to eq({
618
+ "users" => { "$elemMatch" => { "name" => "value" } },
619
+ "$and" => [ { "users" => { "$elemMatch" => { "state" => "new" } } } ],
620
+ })
621
+ end
622
+ end
623
+
624
+ context "when overwrite_chained_operators is true" do
625
+ config_override :overwrite_chained_operators, true
626
+
627
+ it "overrides the $elemMatch expression" do
628
+ expect(selection.selector).to eq({
629
+ "users" => { "$elemMatch" => { state: "new" }}
630
+ })
631
+ end
2068
632
  end
2069
633
 
2070
634
  it "returns a cloned query" do
@@ -2074,78 +638,24 @@ describe Mongoid::Criteria::Queryable::Selectable do
2074
638
  end
2075
639
  end
2076
640
 
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
641
+ describe "#exists" do
2128
642
 
2129
- it "returns a cloned query" do
2130
- expect(selection).to_not equal(query)
2131
- end
2132
- end
643
+ let(:query_method) { :exists }
2133
644
 
2134
- context "when providing multiple criteria" do
645
+ it_behaves_like 'requires an argument'
646
+ it_behaves_like 'requires a non-nil argument'
2135
647
 
2136
- context "when the fields differ" do
648
+ context "when provided a criterion" do
649
+
650
+ context "when provided a boolean" do
2137
651
 
2138
652
  let(:selection) do
2139
- query.near(
2140
- location: [ 20, 21 ],
2141
- comments: [ 20, 21 ]
2142
- )
653
+ query.exists(users: true)
2143
654
  end
2144
655
 
2145
- it "adds the $near expression" do
656
+ it "adds the $exists expression" do
2146
657
  expect(selection.selector).to eq({
2147
- "location" => { "$near" => [ 20, 21 ] },
2148
- "comments" => { "$near" => [ 20, 21 ] }
658
+ "users" => { "$exists" => true }
2149
659
  })
2150
660
  end
2151
661
 
@@ -2153,22 +663,16 @@ describe Mongoid::Criteria::Queryable::Selectable do
2153
663
  expect(selection).to_not equal(query)
2154
664
  end
2155
665
  end
2156
- end
2157
666
 
2158
- context "when chaining multiple criteria" do
2159
-
2160
- context "when the fields differ" do
667
+ context "when provided a string" do
2161
668
 
2162
669
  let(:selection) do
2163
- query.
2164
- near(location: [ 20, 21 ]).
2165
- near(comments: [ 20, 21 ])
670
+ query.exists(users: "yes")
2166
671
  end
2167
672
 
2168
- it "adds the $near expression" do
673
+ it "adds the $exists expression" do
2169
674
  expect(selection.selector).to eq({
2170
- "location" => { "$near" => [ 20, 21 ] },
2171
- "comments" => { "$near" => [ 20, 21 ] }
675
+ "users" => { "$exists" => true }
2172
676
  })
2173
677
  end
2174
678
 
@@ -2177,85 +681,51 @@ describe Mongoid::Criteria::Queryable::Selectable do
2177
681
  end
2178
682
  end
2179
683
  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
684
 
2217
- it "returns a cloned query" do
2218
- expect(selection).to_not equal(query)
2219
- end
2220
- end
685
+ context "when providing multiple criteria" do
2221
686
 
2222
- context "when provided a criterion" do
687
+ context "when the fields differ" do
2223
688
 
2224
- let(:selection) do
2225
- query.near_sphere(location: [ 20, 21 ])
2226
- end
689
+ context "when providing boolean values" do
2227
690
 
2228
- it "adds the $nearSphere expression" do
2229
- expect(selection.selector).to eq({
2230
- "location" => { "$nearSphere" => [ 20, 21 ] }
2231
- })
2232
- end
691
+ let(:selection) do
692
+ query.exists(
693
+ users: true,
694
+ comments: true
695
+ )
696
+ end
2233
697
 
2234
- it "returns a cloned query" do
2235
- expect(selection).to_not equal(query)
2236
- end
2237
- end
698
+ it "adds the $exists expression" do
699
+ expect(selection.selector).to eq({
700
+ "users" => { "$exists" => true },
701
+ "comments" => { "$exists" => true }
702
+ })
703
+ end
2238
704
 
2239
- context "when providing multiple criteria" do
705
+ it "returns a cloned query" do
706
+ expect(selection).to_not equal(query)
707
+ end
708
+ end
2240
709
 
2241
- context "when the fields differ" do
710
+ context "when providing string values" do
2242
711
 
2243
- let(:selection) do
2244
- query.near_sphere(
2245
- location: [ 20, 21 ],
2246
- comments: [ 20, 21 ]
2247
- )
2248
- end
712
+ let(:selection) do
713
+ query.exists(
714
+ users: "y",
715
+ comments: "true"
716
+ )
717
+ end
2249
718
 
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
719
+ it "adds the $exists expression" do
720
+ expect(selection.selector).to eq({
721
+ "users" => { "$exists" => true },
722
+ "comments" => { "$exists" => true }
723
+ })
724
+ end
2256
725
 
2257
- it "returns a cloned query" do
2258
- expect(selection).to_not equal(query)
726
+ it "returns a cloned query" do
727
+ expect(selection).to_not equal(query)
728
+ end
2259
729
  end
2260
730
  end
2261
731
  end
@@ -2266,14 +736,14 @@ describe Mongoid::Criteria::Queryable::Selectable do
2266
736
 
2267
737
  let(:selection) do
2268
738
  query.
2269
- near_sphere(location: [ 20, 21 ]).
2270
- near_sphere(comments: [ 20, 21 ])
739
+ exists(users: true).
740
+ exists(comments: true)
2271
741
  end
2272
742
 
2273
- it "adds the $nearSphere expression" do
743
+ it "adds the $exists expression" do
2274
744
  expect(selection.selector).to eq({
2275
- "location" => { "$nearSphere" => [ 20, 21 ] },
2276
- "comments" => { "$nearSphere" => [ 20, 21 ] }
745
+ "users" => { "$exists" => true },
746
+ "comments" => { "$exists" => true }
2277
747
  })
2278
748
  end
2279
749
 
@@ -2284,126 +754,144 @@ describe Mongoid::Criteria::Queryable::Selectable do
2284
754
  end
2285
755
  end
2286
756
 
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
757
+ describe "#geo_spatial" do
2298
758
 
2299
- it "returns the query" do
2300
- expect(selection).to eq(query)
2301
- end
759
+ let(:query_method) { :geo_spatial }
2302
760
 
2303
- it "returns a cloned query" do
2304
- expect(selection).to_not equal(query)
2305
- end
2306
- end
761
+ it_behaves_like 'requires an argument'
762
+ it_behaves_like 'requires a non-nil argument'
2307
763
 
2308
- context "when provided nil" do
764
+ context "when provided a criterion" do
2309
765
 
2310
- let(:selection) do
2311
- query.nin(nil)
2312
- end
766
+ context "when the geometry is a point intersection" do
2313
767
 
2314
- it "does not add any criterion" do
2315
- expect(selection.selector).to eq({})
2316
- end
768
+ let(:selection) do
769
+ query.geo_spatial(:location.intersects_point => [ 1, 10 ])
770
+ end
2317
771
 
2318
- it "returns the query" do
2319
- expect(selection).to eq(query)
2320
- end
772
+ it "adds the $geoIntersects expression" do
773
+ expect(selection.selector).to eq({
774
+ "location" => {
775
+ "$geoIntersects" => {
776
+ "$geometry" => {
777
+ "type" => "Point",
778
+ "coordinates" => [ 1, 10 ]
779
+ }
780
+ }
781
+ }
782
+ })
783
+ end
2321
784
 
2322
- it "returns a cloned query" do
2323
- expect(selection).to_not equal(query)
785
+ it_behaves_like "returns a cloned query"
2324
786
  end
2325
- end
2326
787
 
2327
- context "when provided a single criterion" do
2328
-
2329
- context "when providing an array" do
788
+ context "when the geometry is a line intersection" do
2330
789
 
2331
790
  let(:selection) do
2332
- query.nin(field: [ 1, 2 ])
791
+ query.geo_spatial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
2333
792
  end
2334
793
 
2335
- it "adds the $nin selector" do
794
+ it "adds the $geoIntersects expression" do
2336
795
  expect(selection.selector).to eq({
2337
- "field" => { "$nin" => [ 1, 2 ] }
796
+ "location" => {
797
+ "$geoIntersects" => {
798
+ "$geometry" => {
799
+ "type" => "LineString",
800
+ "coordinates" => [[ 1, 10 ], [ 2, 10 ]]
801
+ }
802
+ }
803
+ }
2338
804
  })
2339
805
  end
2340
806
 
2341
- it "returns a cloned query" do
2342
- expect(selection).to_not equal(query)
2343
- end
807
+ it_behaves_like "returns a cloned query"
2344
808
  end
2345
809
 
2346
- context "when providing a range" do
810
+ context "when the geometry is a polygon intersection" do
2347
811
 
2348
812
  let(:selection) do
2349
- query.nin(field: 1..3)
813
+ query.geo_spatial(:location.intersects_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]])
2350
814
  end
2351
815
 
2352
- it "adds the $nin selector with converted range" do
816
+ it "adds the $geoIntersects expression" do
2353
817
  expect(selection.selector).to eq({
2354
- "field" => { "$nin" => [ 1, 2, 3 ] }
818
+ "location" => {
819
+ "$geoIntersects" => {
820
+ "$geometry" => {
821
+ "type" => "Polygon",
822
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
823
+ }
824
+ }
825
+ }
2355
826
  })
2356
827
  end
2357
828
 
2358
- it "returns a cloned query" do
2359
- expect(selection).to_not equal(query)
2360
- end
829
+ it_behaves_like "returns a cloned query"
2361
830
  end
2362
831
 
2363
- context "when providing a single value" do
832
+ context "when the geometry is within a polygon" do
2364
833
 
2365
834
  let(:selection) do
2366
- query.nin(field: 1)
835
+ query.geo_spatial(:location.within_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]])
2367
836
  end
2368
837
 
2369
- it "adds the $nin selector with wrapped value" do
838
+ it "adds the $geoIntersects expression" do
2370
839
  expect(selection.selector).to eq({
2371
- "field" => { "$nin" => [ 1 ] }
840
+ "location" => {
841
+ "$geoWithin" => {
842
+ "$geometry" => {
843
+ "type" => "Polygon",
844
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
845
+ }
846
+ }
847
+ }
2372
848
  })
2373
849
  end
2374
850
 
2375
- it "returns a cloned query" do
2376
- expect(selection).to_not equal(query)
851
+ context "when used with the $box operator ($geoWithin query) " do
852
+ let(:selection) do
853
+ query.geo_spatial(:location.within_box => [[ 1, 10 ], [ 2, 10 ]])
854
+ end
855
+
856
+ it "adds the $geoIntersects expression" do
857
+ expect(selection.selector).to eq({
858
+ "location" => {
859
+ "$geoWithin" => {
860
+ "$box" => [
861
+ [ 1, 10 ], [ 2, 10 ]
862
+ ]
863
+ }
864
+ }
865
+ })
866
+ end
2377
867
  end
868
+
869
+ it_behaves_like "returns a cloned query"
2378
870
  end
2379
871
  end
872
+ end
2380
873
 
2381
- context "when unioning on the same field" do
874
+ describe "#gt" do
2382
875
 
2383
- context "when the field is not aliased" do
876
+ let(:query_method) { :gt }
2384
877
 
2385
- let(:selection) do
2386
- query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
2387
- end
878
+ it_behaves_like 'requires an argument'
879
+ it_behaves_like 'requires a non-nil argument'
2388
880
 
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
881
+ context "when provided a single criterion" do
2395
882
 
2396
- context "when the field is aliased" do
883
+ let(:selection) do
884
+ query.gt(field: 10)
885
+ end
2397
886
 
2398
- let(:selection) do
2399
- query.nin(id: [ 1, 2 ]).union.nin(id: [ 3, 4 ])
2400
- end
887
+ it "adds the $gt selector" do
888
+ expect(selection.selector).to eq({
889
+ "field" => { "$gt" => 10 }
890
+ })
891
+ end
2401
892
 
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
893
+ it "returns a cloned query" do
894
+ expect(selection).to_not equal(query)
2407
895
  end
2408
896
  end
2409
897
 
@@ -2412,13 +900,13 @@ describe Mongoid::Criteria::Queryable::Selectable do
2412
900
  context "when the criterion are for different fields" do
2413
901
 
2414
902
  let(:selection) do
2415
- query.nin(first: [ 1, 2 ], second: [ 3, 4 ])
903
+ query.gt(first: 10, second: 15)
2416
904
  end
2417
905
 
2418
- it "adds the $nin selectors" do
906
+ it "adds the $gt selectors" do
2419
907
  expect(selection.selector).to eq({
2420
- "first" => { "$nin" => [ 1, 2 ] },
2421
- "second" => { "$nin" => [ 3, 4 ] }
908
+ "first" => { "$gt" => 10 },
909
+ "second" => { "$gt" => 15 }
2422
910
  })
2423
911
  end
2424
912
 
@@ -2428,18 +916,18 @@ describe Mongoid::Criteria::Queryable::Selectable do
2428
916
  end
2429
917
  end
2430
918
 
2431
- context "when chaninning the criterion" do
919
+ context "when chaining the criterion" do
2432
920
 
2433
921
  context "when the criterion are for different fields" do
2434
922
 
2435
923
  let(:selection) do
2436
- query.nin(first: [ 1, 2 ]).nin(second: [ 3, 4 ])
924
+ query.gt(first: 10).gt(second: 15)
2437
925
  end
2438
926
 
2439
- it "adds the $nin selectors" do
927
+ it "adds the $gt selectors" do
2440
928
  expect(selection.selector).to eq({
2441
- "first" => { "$nin" => [ 1, 2 ] },
2442
- "second" => { "$nin" => [ 3, 4 ] }
929
+ "first" => { "$gt" => 10 },
930
+ "second" => { "$gt" => 15 }
2443
931
  })
2444
932
  end
2445
933
 
@@ -2450,50 +938,17 @@ describe Mongoid::Criteria::Queryable::Selectable do
2450
938
 
2451
939
  context "when the criterion are on the same field" do
2452
940
 
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
941
+ context "when overwrite_chained_operators is true" do
942
+ config_override :overwrite_chained_operators, true
2488
943
 
2489
944
  let(:selection) do
2490
- query.nin(first: [ 1, 2 ]).override.nin(first: [ 3, 4 ])
945
+ query.gt(first: 10).gt(first: 15)
2491
946
  end
2492
947
 
2493
- it "overwrites the first $nin selector" do
948
+ it "overwrites the first $gt selector" do
2494
949
  expect(selection.selector).to eq({
2495
- "first" => { "$nin" => [ 3, 4 ] }
2496
- })
950
+ "first" => { "$gt" => 15 },
951
+ })
2497
952
  end
2498
953
 
2499
954
  it "returns a cloned query" do
@@ -2501,16 +956,17 @@ describe Mongoid::Criteria::Queryable::Selectable do
2501
956
  end
2502
957
  end
2503
958
 
2504
- context "when the stretegy is union" do
2505
-
959
+ context "when overwrite_chained_operators is false" do
960
+ config_override :overwrite_chained_operators, false
2506
961
  let(:selection) do
2507
- query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
962
+ query.gt(first: 10).gt(first: 15)
2508
963
  end
2509
964
 
2510
- it "unions the $nin selectors" do
965
+ it "overwrites the first $gt selector" do
2511
966
  expect(selection.selector).to eq({
2512
- "first" => { "$nin" => [ 1, 2, 3, 4 ] }
2513
- })
967
+ "first" => { "$gt" => 10 },
968
+ "$and" => [{ "first" => { "$gt" => 15 } }]
969
+ })
2514
970
  end
2515
971
 
2516
972
  it "returns a cloned query" do
@@ -2521,55 +977,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
2521
977
  end
2522
978
  end
2523
979
 
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
980
+ describe "#gte" do
2554
981
 
2555
- it "returns the query" do
2556
- expect(selection).to eq(query)
2557
- end
982
+ let(:query_method) { :gte }
2558
983
 
2559
- it "returns a cloned query" do
2560
- expect(selection).to_not equal(query)
2561
- end
2562
- end
984
+ it_behaves_like 'requires an argument'
985
+ it_behaves_like 'requires a non-nil argument'
2563
986
 
2564
987
  context "when provided a single criterion" do
2565
988
 
2566
989
  let(:selection) do
2567
- query.nor(field: [ 1, 2 ])
990
+ query.gte(field: 10)
2568
991
  end
2569
992
 
2570
- it "adds the $nor selector" do
993
+ it "adds the $gte selector" do
2571
994
  expect(selection.selector).to eq({
2572
- "$nor" => [{"field" => [ 1, 2 ] }]
995
+ "field" => { "$gte" => 10 }
2573
996
  })
2574
997
  end
2575
998
 
@@ -2580,38 +1003,16 @@ describe Mongoid::Criteria::Queryable::Selectable do
2580
1003
 
2581
1004
  context "when provided multiple criterion" do
2582
1005
 
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
1006
+ context "when the criterion are for different fields" do
2604
1007
 
2605
1008
  let(:selection) do
2606
- query.nor({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
1009
+ query.gte(first: 10, second: 15)
2607
1010
  end
2608
1011
 
2609
- it "appends both $nor expressions" do
1012
+ it "adds the $gte selectors" do
2610
1013
  expect(selection.selector).to eq({
2611
- "$nor" => [
2612
- { "first" => [ 1, 2 ] },
2613
- { "first" => [ 3, 4 ] }
2614
- ]
1014
+ "first" => { "$gte" => 10 },
1015
+ "second" => { "$gte" => 15 }
2615
1016
  })
2616
1017
  end
2617
1018
 
@@ -2623,18 +1024,16 @@ describe Mongoid::Criteria::Queryable::Selectable do
2623
1024
 
2624
1025
  context "when chaining the criterion" do
2625
1026
 
2626
- context "when the criterion are fnor different fields" do
1027
+ context "when the criterion are for different fields" do
2627
1028
 
2628
1029
  let(:selection) do
2629
- query.nor(first: [ 1, 2 ]).nor(second: [ 3, 4 ])
1030
+ query.gte(first: 10).gte(second: 15)
2630
1031
  end
2631
1032
 
2632
- it "adds the $nor selectors" do
1033
+ it "adds the $gte selectors" do
2633
1034
  expect(selection.selector).to eq({
2634
- "$nor" => [
2635
- { "first" => [ 1, 2 ] },
2636
- { "second" => [ 3, 4 ] }
2637
- ]
1035
+ "first" => { "$gte" => 10 },
1036
+ "second" => { "$gte" => 15 }
2638
1037
  })
2639
1038
  end
2640
1039
 
@@ -2646,16 +1045,28 @@ describe Mongoid::Criteria::Queryable::Selectable do
2646
1045
  context "when the criterion are on the same field" do
2647
1046
 
2648
1047
  let(:selection) do
2649
- query.nor(first: [ 1, 2 ]).nor(first: [ 3, 4 ])
1048
+ query.gte(first: 10).gte(first: 15)
2650
1049
  end
2651
1050
 
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
- })
1051
+ context "when overwrite_chained_operators is false" do
1052
+ config_override :overwrite_chained_operators, false
1053
+
1054
+ it "adds a second $gte selector" do
1055
+ expect(selection.selector).to eq({
1056
+ "first" => { "$gte" => 10 },
1057
+ "$and" => [ { "first" => { "$gte" => 15 } } ]
1058
+ })
1059
+ end
1060
+ end
1061
+
1062
+ context "when overwrite_chained_operators is true" do
1063
+ config_override :overwrite_chained_operators, true
1064
+
1065
+ it "overwrites the first $gte selector" do
1066
+ expect(selection.selector).to eq({
1067
+ "first" => { "$gte" => 15 }
1068
+ })
1069
+ end
2659
1070
  end
2660
1071
 
2661
1072
  it "returns a cloned query" do
@@ -2665,140 +1076,115 @@ describe Mongoid::Criteria::Queryable::Selectable do
2665
1076
  end
2666
1077
  end
2667
1078
 
2668
- describe "#not" do
2669
-
2670
- context "when provided no criterion" do
2671
-
2672
- let(:selection) do
2673
- query.not
2674
- end
1079
+ describe "#in" do
2675
1080
 
2676
- it "does not add any criterion" do
2677
- expect(selection.selector).to eq({})
2678
- end
1081
+ let(:query_method) { :in }
1082
+ let(:operator) { '$in' }
2679
1083
 
2680
- it "returns the query" do
2681
- expect(selection).to eq(query)
2682
- end
1084
+ it_behaves_like 'requires an argument'
1085
+ it_behaves_like 'requires a non-nil argument'
2683
1086
 
2684
- it "returns a non cloned query" do
2685
- expect(selection).to equal(query)
2686
- end
1087
+ context "when provided a single criterion" do
2687
1088
 
2688
- context "when the following criteria is a query method" do
1089
+ context "when providing an array" do
2689
1090
 
2690
1091
  let(:selection) do
2691
- query.not.all(field: [ 1, 2 ])
1092
+ query.in(field: [ 1, 2 ])
2692
1093
  end
2693
1094
 
2694
- it "negates the all selection" do
2695
- expect(selection.selector).to eq(
2696
- { "field" => { "$not" => { "$all" => [ 1, 2 ] }}}
2697
- )
1095
+ it "adds the $in selector" do
1096
+ expect(selection.selector).to eq({
1097
+ "field" => { "$in" => [ 1, 2 ] }
1098
+ })
2698
1099
  end
2699
1100
 
2700
1101
  it "returns a cloned query" do
2701
1102
  expect(selection).to_not equal(query)
2702
1103
  end
2703
-
2704
- it "removes the negation on the clone" do
2705
- expect(selection).to_not be_negating
2706
- end
2707
1104
  end
2708
1105
 
2709
- context "when the following criteria is a gt method" do
1106
+ context "when providing a single value" do
2710
1107
 
2711
1108
  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
- )
1109
+ query.in(field: 1)
2719
1110
  end
2720
1111
 
2721
- it "returns a coned query" do
2722
- expect(selection).to_not eq(query)
1112
+ it "adds the $in selector with wrapped value" do
1113
+ expect(selection.selector).to eq({
1114
+ "field" => { "$in" => [ 1 ] }
1115
+ })
2723
1116
  end
2724
1117
 
2725
- it "removes the negation on the clone" do
2726
- expect(selection).to_not be_negating
1118
+ it "returns a cloned query" do
1119
+ expect(selection).to_not equal(query)
2727
1120
  end
2728
1121
  end
1122
+ end
1123
+
1124
+ context "when provided multiple criterion" do
2729
1125
 
2730
- context "when the following criteria is a where" do
1126
+ context "when the criterion are for different fields" do
2731
1127
 
2732
1128
  let(:selection) do
2733
- query.not.where(field: 1, :other.in => [ 1, 2 ])
1129
+ query.in(first: [ 1, 2 ], second: 3..4)
2734
1130
  end
2735
1131
 
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
- )
1132
+ it "adds the $in selectors" do
1133
+ expect(selection.selector).to eq({
1134
+ "first" => { "$in" => [ 1, 2 ] },
1135
+ "second" => { "$in" => [ 3, 4 ] }
1136
+ })
2740
1137
  end
2741
1138
 
2742
1139
  it "returns a cloned query" do
2743
1140
  expect(selection).to_not equal(query)
2744
1141
  end
2745
-
2746
- it "removes the negation on the clone" do
2747
- expect(selection).to_not be_negating
2748
- end
2749
1142
  end
1143
+ end
1144
+
1145
+ context "when chaining the criterion" do
2750
1146
 
2751
- context "when the following criteria is a where with a regexp" do
1147
+ context "when the criterion are for different fields" do
2752
1148
 
2753
1149
  let(:selection) do
2754
- query.not.where(field: 1, other: /test/)
1150
+ query.in(first: [ 1, 2 ]).in(second: [ 3, 4 ])
2755
1151
  end
2756
1152
 
2757
- it "negates the selection with an operator" do
2758
- expect(selection.selector).to eq(
2759
- { "field" => { "$ne" => 1 }, "other" => { "$not" => /test/ } }
2760
- )
1153
+ it "adds the $in selectors" do
1154
+ expect(selection.selector).to eq({
1155
+ "first" => { "$in" => [ 1, 2 ] },
1156
+ "second" => { "$in" => [ 3, 4 ] }
1157
+ })
2761
1158
  end
2762
1159
 
2763
1160
  it "returns a cloned query" do
2764
1161
  expect(selection).to_not equal(query)
2765
1162
  end
2766
-
2767
- it "removes the negation on the clone" do
2768
- expect(selection).to_not be_negating
2769
- end
2770
-
2771
1163
  end
2772
- end
2773
1164
 
2774
- context "when provided nil" do
1165
+ context "when the criterion are on the same field" do
2775
1166
 
2776
- let(:selection) do
2777
- query.not(nil)
1167
+ it_behaves_like 'supports merge strategies'
2778
1168
  end
1169
+ end
1170
+ end
2779
1171
 
2780
- it "does not add any criterion" do
2781
- expect(selection.selector).to eq({})
2782
- end
1172
+ describe "#lt" do
2783
1173
 
2784
- it "returns the query" do
2785
- expect(selection).to eq(query)
2786
- end
1174
+ let(:query_method) { :lt }
2787
1175
 
2788
- it "returns a cloned query" do
2789
- expect(selection).to_not equal(query)
2790
- end
2791
- end
1176
+ it_behaves_like 'requires an argument'
1177
+ it_behaves_like 'requires a non-nil argument'
2792
1178
 
2793
1179
  context "when provided a single criterion" do
2794
1180
 
2795
1181
  let(:selection) do
2796
- query.not(field: /test/)
1182
+ query.lt(field: 10)
2797
1183
  end
2798
1184
 
2799
- it "adds the $not selector" do
1185
+ it "adds the $lt selector" do
2800
1186
  expect(selection.selector).to eq({
2801
- "field" => { "$not" => /test/ }
1187
+ "field" => { "$lt" => 10 }
2802
1188
  })
2803
1189
  end
2804
1190
 
@@ -2812,13 +1198,13 @@ describe Mongoid::Criteria::Queryable::Selectable do
2812
1198
  context "when the criterion are for different fields" do
2813
1199
 
2814
1200
  let(:selection) do
2815
- query.not(first: /1/, second: /2/)
1201
+ query.lt(first: 10, second: 15)
2816
1202
  end
2817
1203
 
2818
- it "adds the $not selectors" do
1204
+ it "adds the $lt selectors" do
2819
1205
  expect(selection.selector).to eq({
2820
- "first" => { "$not" => /1/ },
2821
- "second" => { "$not" => /2/ }
1206
+ "first" => { "$lt" => 10 },
1207
+ "second" => { "$lt" => 15 }
2822
1208
  })
2823
1209
  end
2824
1210
 
@@ -2833,47 +1219,13 @@ describe Mongoid::Criteria::Queryable::Selectable do
2833
1219
  context "when the criterion are for different fields" do
2834
1220
 
2835
1221
  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/)
1222
+ query.lt(first: 10).lt(second: 15)
2872
1223
  end
2873
1224
 
2874
- it "does not double the $not selector" do
1225
+ it "adds the $lt selectors" do
2875
1226
  expect(selection.selector).to eq({
2876
- "first" => { "$not" => /1/ }
1227
+ "first" => { "$lt" => 10 },
1228
+ "second" => { "$lt" => 15 }
2877
1229
  })
2878
1230
  end
2879
1231
 
@@ -2881,58 +1233,57 @@ describe Mongoid::Criteria::Queryable::Selectable do
2881
1233
  expect(selection).to_not equal(query)
2882
1234
  end
2883
1235
  end
2884
- end
2885
- end
2886
-
2887
- describe "#or" do
2888
1236
 
2889
- context "when provided no criterion" do
1237
+ context "when the criterion are on the same field" do
2890
1238
 
2891
- let(:selection) do
2892
- query.or
2893
- end
1239
+ let(:selection) do
1240
+ query.lt(first: 10).lt(first: 15)
1241
+ end
2894
1242
 
2895
- it "does not add any criterion" do
2896
- expect(selection.selector).to eq({})
2897
- end
1243
+ context "when overwrite_chained_operators is false" do
1244
+ config_override :overwrite_chained_operators, false
2898
1245
 
2899
- it "returns the query" do
2900
- expect(selection).to eq(query)
2901
- end
1246
+ it "adds a second $lt selector" do
1247
+ expect(selection.selector).to eq({
1248
+ "first" => { "$lt" => 10 },
1249
+ "$and" => [ { "first" => { "$lt" => 15 } } ]
1250
+ })
1251
+ end
1252
+ end
2902
1253
 
2903
- it "returns a cloned query" do
2904
- expect(selection).to_not equal(query)
2905
- end
2906
- end
1254
+ context "when overwrite_chained_operators is true" do
1255
+ config_override :overwrite_chained_operators, true
2907
1256
 
2908
- context "when provided nil" do
1257
+ it "overwrites the first $lt selector" do
1258
+ expect(selection.selector).to eq({
1259
+ "first" => { "$lt" => 15 }
1260
+ })
1261
+ end
1262
+ end
2909
1263
 
2910
- let(:selection) do
2911
- query.or(nil)
1264
+ it "returns a cloned query" do
1265
+ expect(selection).to_not equal(query)
1266
+ end
2912
1267
  end
1268
+ end
1269
+ end
2913
1270
 
2914
- it "does not add any criterion" do
2915
- expect(selection.selector).to eq({})
2916
- end
1271
+ describe "#lte" do
2917
1272
 
2918
- it "returns the query" do
2919
- expect(selection).to eq(query)
2920
- end
1273
+ let(:query_method) { :lte }
2921
1274
 
2922
- it "returns a cloned query" do
2923
- expect(selection).to_not equal(query)
2924
- end
2925
- end
1275
+ it_behaves_like 'requires an argument'
1276
+ it_behaves_like 'requires a non-nil argument'
2926
1277
 
2927
1278
  context "when provided a single criterion" do
2928
1279
 
2929
1280
  let(:selection) do
2930
- query.or(field: [ 1, 2 ])
1281
+ query.lte(field: 10)
2931
1282
  end
2932
1283
 
2933
- it "adds the $or selector" do
1284
+ it "adds the $lte selector" do
2934
1285
  expect(selection.selector).to eq({
2935
- "$or" => [{ "field" => [ 1, 2 ] }]
1286
+ "field" => { "$lte" => 10 }
2936
1287
  })
2937
1288
  end
2938
1289
 
@@ -2946,15 +1297,13 @@ describe Mongoid::Criteria::Queryable::Selectable do
2946
1297
  context "when the criterion are for different fields" do
2947
1298
 
2948
1299
  let(:selection) do
2949
- query.or({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
1300
+ query.lte(first: 10, second: 15)
2950
1301
  end
2951
1302
 
2952
- it "adds the $or selector" do
1303
+ it "adds the $lte selectors" do
2953
1304
  expect(selection.selector).to eq({
2954
- "$or" => [
2955
- { "first" => [ 1, 2 ] },
2956
- { "second" => [ 3, 4 ] }
2957
- ]
1305
+ "first" => { "$lte" => 10 },
1306
+ "second" => { "$lte" => 15 }
2958
1307
  })
2959
1308
  end
2960
1309
 
@@ -2962,19 +1311,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
2962
1311
  expect(selection).to_not equal(query)
2963
1312
  end
2964
1313
  end
1314
+ end
1315
+
1316
+ context "when chaining the criterion" do
2965
1317
 
2966
- context "when a criterion has a selectable key" do
1318
+ context "when the criterion are for different fields" do
2967
1319
 
2968
1320
  let(:selection) do
2969
- query.or({ first: [ 1, 2 ] }, { :second.gt => 3 })
1321
+ query.lte(first: 10).lte(second: 15)
2970
1322
  end
2971
1323
 
2972
- it "adds the $or selector" do
1324
+ it "adds the $lte selectors" do
2973
1325
  expect(selection.selector).to eq({
2974
- "$or" => [
2975
- { "first" => [ 1, 2 ] },
2976
- { "second" => { "$gt" => 3 }}
2977
- ]
1326
+ "first" => { "$lte" => 10 },
1327
+ "second" => { "$lte" => 15 }
2978
1328
  })
2979
1329
  end
2980
1330
 
@@ -2983,35 +1333,58 @@ describe Mongoid::Criteria::Queryable::Selectable do
2983
1333
  end
2984
1334
  end
2985
1335
 
2986
- context "when the criterion has an aliased field" do
1336
+ context "when the criterion are on the same field" do
2987
1337
 
2988
1338
  let(:selection) do
2989
- query.or({ id: 1 })
1339
+ query.lte(first: 10).lte(first: 15)
2990
1340
  end
2991
1341
 
2992
- it "adds the $or selector and aliases the field" do
2993
- expect(selection.selector).to eq({
2994
- "$or" => [ { "_id" => 1 } ]
2995
- })
1342
+ context "when overwrite_chained_operators is false" do
1343
+ config_override :overwrite_chained_operators, false
1344
+
1345
+ it "adds a second $lte selector" do
1346
+ expect(selection.selector).to eq({
1347
+ "first" => { "$lte" => 10 },
1348
+ "$and" => [ { "first" => { "$lte" => 15 } } ]
1349
+ })
1350
+ end
1351
+ end
1352
+
1353
+ context "when overwrite_chained_operators is true" do
1354
+ config_override :overwrite_chained_operators, true
1355
+
1356
+ it "overwrites the first $lte selector" do
1357
+ expect(selection.selector).to eq({
1358
+ "first" => { "$lte" => 15 }
1359
+ })
1360
+ end
2996
1361
  end
2997
1362
 
2998
1363
  it "returns a cloned query" do
2999
1364
  expect(selection).to_not equal(query)
3000
1365
  end
3001
1366
  end
1367
+ end
1368
+ end
1369
+
1370
+ describe "#max_distance" do
1371
+
1372
+ let(:query_method) { :max_distance }
3002
1373
 
3003
- context "when a criterion is wrapped in an array" do
1374
+ it_behaves_like 'requires an argument'
1375
+ it_behaves_like 'requires a non-nil argument'
1376
+
1377
+ context "when provided a criterion" do
1378
+
1379
+ context "when a $near criterion exists on the same field" do
3004
1380
 
3005
1381
  let(:selection) do
3006
- query.or([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
1382
+ query.near(location: [ 1, 1 ]).max_distance(location: 50)
3007
1383
  end
3008
1384
 
3009
- it "adds the $or selector" do
1385
+ it "adds the $maxDistance expression" do
3010
1386
  expect(selection.selector).to eq({
3011
- "$or" => [
3012
- { "first" => [ 1, 2 ] },
3013
- { "second" => { "$gt" => 3 }}
3014
- ]
1387
+ "location" => { "$near" => [ 1, 1 ], "$maxDistance" => 50 }
3015
1388
  })
3016
1389
  end
3017
1390
 
@@ -3019,42 +1392,48 @@ describe Mongoid::Criteria::Queryable::Selectable do
3019
1392
  expect(selection).to_not equal(query)
3020
1393
  end
3021
1394
  end
1395
+ end
1396
+ end
3022
1397
 
3023
- context "when the criterion are on the same field" do
1398
+ describe "#mod" do
3024
1399
 
3025
- let(:selection) do
3026
- query.or({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
3027
- end
1400
+ let(:query_method) { :mod }
3028
1401
 
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
1402
+ it_behaves_like 'requires an argument'
1403
+ it_behaves_like 'requires a non-nil argument'
3037
1404
 
3038
- it "returns a cloned query" do
3039
- expect(selection).to_not equal(query)
3040
- end
1405
+ context "when provided a criterion" do
1406
+
1407
+ let(:selection) do
1408
+ query.mod(value: [ 10, 1 ])
1409
+ end
1410
+
1411
+ it "adds the $mod expression" do
1412
+ expect(selection.selector).to eq({
1413
+ "value" => { "$mod" => [ 10, 1 ] }
1414
+ })
1415
+ end
1416
+
1417
+ it "returns a cloned query" do
1418
+ expect(selection).to_not equal(query)
3041
1419
  end
3042
1420
  end
3043
1421
 
3044
- context "when chaining the criterion" do
1422
+ context "when providing multiple criteria" do
3045
1423
 
3046
- context "when the criterion are for different fields" do
1424
+ context "when the fields differ" do
3047
1425
 
3048
1426
  let(:selection) do
3049
- query.or(first: [ 1, 2 ]).or(second: [ 3, 4 ])
1427
+ query.mod(
1428
+ value: [ 10, 1 ],
1429
+ comments: [ 10, 1 ]
1430
+ )
3050
1431
  end
3051
1432
 
3052
- it "adds the $or selectors" do
1433
+ it "adds the $mod expression" do
3053
1434
  expect(selection.selector).to eq({
3054
- "$or" => [
3055
- { "first" => [ 1, 2 ] },
3056
- { "second" => [ 3, 4 ] }
3057
- ]
1435
+ "value" => { "$mod" => [ 10, 1 ] },
1436
+ "comments" => { "$mod" => [ 10, 1 ] }
3058
1437
  })
3059
1438
  end
3060
1439
 
@@ -3062,19 +1441,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
3062
1441
  expect(selection).to_not equal(query)
3063
1442
  end
3064
1443
  end
1444
+ end
3065
1445
 
3066
- context "when the criterion are on the same field" do
1446
+ context "when chaining multiple criteria" do
1447
+
1448
+ context "when the fields differ" do
3067
1449
 
3068
1450
  let(:selection) do
3069
- query.or(first: [ 1, 2 ]).or(first: [ 3, 4 ])
1451
+ query.
1452
+ mod(value: [ 10, 1 ]).
1453
+ mod(result: [ 10, 1 ])
3070
1454
  end
3071
1455
 
3072
- it "appends both $or expressions" do
1456
+ it "adds the $mod expression" do
3073
1457
  expect(selection.selector).to eq({
3074
- "$or" => [
3075
- { "first" => [ 1, 2 ] },
3076
- { "first" => [ 3, 4 ] }
3077
- ]
1458
+ "value" => { "$mod" => [ 10, 1 ] },
1459
+ "result" => { "$mod" => [ 10, 1 ] }
3078
1460
  })
3079
1461
  end
3080
1462
 
@@ -3085,39 +1467,23 @@ describe Mongoid::Criteria::Queryable::Selectable do
3085
1467
  end
3086
1468
  end
3087
1469
 
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
1470
+ describe "#ne" do
3099
1471
 
3100
- it "returns the query" do
3101
- expect(selection).to eq(query)
3102
- end
1472
+ let(:query_method) { :ne }
3103
1473
 
3104
- it "returns a cloned query" do
3105
- expect(selection).to_not equal(query)
3106
- end
3107
- end
1474
+ it_behaves_like 'requires an argument'
1475
+ it_behaves_like 'requires a non-nil argument'
3108
1476
 
3109
- context "when provided nil" do
1477
+ context "when provided a criterion" do
3110
1478
 
3111
1479
  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({})
1480
+ query.ne(value: 10)
3117
1481
  end
3118
1482
 
3119
- it "returns the query" do
3120
- expect(selection).to eq(query)
1483
+ it "adds the $ne expression" do
1484
+ expect(selection.selector).to eq({
1485
+ "value" => { "$ne" => 10 }
1486
+ })
3121
1487
  end
3122
1488
 
3123
1489
  it "returns a cloned query" do
@@ -3125,17 +1491,21 @@ describe Mongoid::Criteria::Queryable::Selectable do
3125
1491
  end
3126
1492
  end
3127
1493
 
3128
- context "when provided a single criterion" do
1494
+ context "when providing multiple criteria" do
3129
1495
 
3130
- context "when provided an integer" do
1496
+ context "when the fields differ" do
3131
1497
 
3132
1498
  let(:selection) do
3133
- query.with_size(field: 10)
1499
+ query.ne(
1500
+ value: 10,
1501
+ comments: 10
1502
+ )
3134
1503
  end
3135
1504
 
3136
- it "adds the $size selector" do
1505
+ it "adds the $ne expression" do
3137
1506
  expect(selection.selector).to eq({
3138
- "field" => { "$size" => 10 }
1507
+ "value" => { "$ne" => 10 },
1508
+ "comments" => { "$ne" => 10 }
3139
1509
  })
3140
1510
  end
3141
1511
 
@@ -3143,16 +1513,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
3143
1513
  expect(selection).to_not equal(query)
3144
1514
  end
3145
1515
  end
1516
+ end
3146
1517
 
3147
- context "when provided a string" do
1518
+ context "when chaining multiple criteria" do
1519
+
1520
+ context "when the fields differ" do
3148
1521
 
3149
1522
  let(:selection) do
3150
- query.with_size(field: "10")
1523
+ query.
1524
+ ne(value: 10).
1525
+ ne(result: 10)
3151
1526
  end
3152
1527
 
3153
- it "adds the $size selector with an integer" do
1528
+ it "adds the $ne expression" do
3154
1529
  expect(selection.selector).to eq({
3155
- "field" => { "$size" => 10 }
1530
+ "value" => { "$ne" => 10 },
1531
+ "result" => { "$ne" => 10 }
3156
1532
  })
3157
1533
  end
3158
1534
 
@@ -3161,61 +1537,47 @@ describe Mongoid::Criteria::Queryable::Selectable do
3161
1537
  end
3162
1538
  end
3163
1539
  end
1540
+ end
3164
1541
 
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
1542
+ describe "#near" do
3174
1543
 
3175
- it "adds the $size selectors" do
3176
- expect(selection.selector).to eq({
3177
- "first" => { "$size" => 10 },
3178
- "second" => { "$size" => 15 }
3179
- })
3180
- end
1544
+ let(:query_method) { :near }
3181
1545
 
3182
- it "returns a cloned query" do
3183
- expect(selection).to_not equal(query)
3184
- end
3185
- end
1546
+ it_behaves_like 'requires an argument'
1547
+ it_behaves_like 'requires a non-nil argument'
3186
1548
 
3187
- context "when provided strings" do
1549
+ context "when provided a criterion" do
3188
1550
 
3189
- let(:selection) do
3190
- query.with_size(first: "10", second: "15")
3191
- end
1551
+ let(:selection) do
1552
+ query.near(location: [ 20, 21 ])
1553
+ end
3192
1554
 
3193
- it "adds the $size selectors" do
3194
- expect(selection.selector).to eq({
3195
- "first" => { "$size" => 10 },
3196
- "second" => { "$size" => 15 }
3197
- })
3198
- end
1555
+ it "adds the $near expression" do
1556
+ expect(selection.selector).to eq({
1557
+ "location" => { "$near" => [ 20, 21 ] }
1558
+ })
1559
+ end
3199
1560
 
3200
- it "returns a cloned query" do
3201
- expect(selection).to_not equal(query)
3202
- end
3203
- end
1561
+ it "returns a cloned query" do
1562
+ expect(selection).to_not equal(query)
3204
1563
  end
3205
1564
  end
3206
1565
 
3207
- context "when chaining the criterion" do
1566
+ context "when providing multiple criteria" do
3208
1567
 
3209
- context "when the criterion are for different fields" do
1568
+ context "when the fields differ" do
3210
1569
 
3211
1570
  let(:selection) do
3212
- query.with_size(first: 10).with_size(second: 15)
1571
+ query.near(
1572
+ location: [ 20, 21 ],
1573
+ comments: [ 20, 21 ]
1574
+ )
3213
1575
  end
3214
1576
 
3215
- it "adds the $size selectors" do
1577
+ it "adds the $near expression" do
3216
1578
  expect(selection.selector).to eq({
3217
- "first" => { "$size" => 10 },
3218
- "second" => { "$size" => 15 }
1579
+ "location" => { "$near" => [ 20, 21 ] },
1580
+ "comments" => { "$near" => [ 20, 21 ] }
3219
1581
  })
3220
1582
  end
3221
1583
 
@@ -3223,16 +1585,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
3223
1585
  expect(selection).to_not equal(query)
3224
1586
  end
3225
1587
  end
1588
+ end
1589
+
1590
+ context "when chaining multiple criteria" do
3226
1591
 
3227
- context "when the criterion are on the same field" do
1592
+ context "when the fields differ" do
3228
1593
 
3229
1594
  let(:selection) do
3230
- query.with_size(first: 10).with_size(first: 15)
1595
+ query.
1596
+ near(location: [ 20, 21 ]).
1597
+ near(comments: [ 20, 21 ])
3231
1598
  end
3232
1599
 
3233
- it "overwrites the first $size selector" do
1600
+ it "adds the $near expression" do
3234
1601
  expect(selection.selector).to eq({
3235
- "first" => { "$size" => 15 }
1602
+ "location" => { "$near" => [ 20, 21 ] },
1603
+ "comments" => { "$near" => [ 20, 21 ] }
3236
1604
  })
3237
1605
  end
3238
1606
 
@@ -3243,39 +1611,23 @@ describe Mongoid::Criteria::Queryable::Selectable do
3243
1611
  end
3244
1612
  end
3245
1613
 
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
1614
+ describe "#near_sphere" do
3257
1615
 
3258
- it "returns the query" do
3259
- expect(selection).to eq(query)
3260
- end
1616
+ let(:query_method) { :near_sphere }
3261
1617
 
3262
- it "returns a cloned query" do
3263
- expect(selection).to_not equal(query)
3264
- end
3265
- end
1618
+ it_behaves_like 'requires an argument'
1619
+ it_behaves_like 'requires a non-nil argument'
3266
1620
 
3267
- context "when provided nil" do
1621
+ context "when provided a criterion" do
3268
1622
 
3269
1623
  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({})
1624
+ query.near_sphere(location: [ 20, 21 ])
3275
1625
  end
3276
1626
 
3277
- it "returns the query" do
3278
- expect(selection).to eq(query)
1627
+ it "adds the $nearSphere expression" do
1628
+ expect(selection.selector).to eq({
1629
+ "location" => { "$nearSphere" => [ 20, 21 ] }
1630
+ })
3279
1631
  end
3280
1632
 
3281
1633
  it "returns a cloned query" do
@@ -3283,17 +1635,21 @@ describe Mongoid::Criteria::Queryable::Selectable do
3283
1635
  end
3284
1636
  end
3285
1637
 
3286
- context "when provided a single criterion" do
1638
+ context "when providing multiple criteria" do
3287
1639
 
3288
- context "when provided an integer" do
1640
+ context "when the fields differ" do
3289
1641
 
3290
1642
  let(:selection) do
3291
- query.with_type(field: 10)
1643
+ query.near_sphere(
1644
+ location: [ 20, 21 ],
1645
+ comments: [ 20, 21 ]
1646
+ )
3292
1647
  end
3293
1648
 
3294
- it "adds the $type selector" do
1649
+ it "adds the $nearSphere expression" do
3295
1650
  expect(selection.selector).to eq({
3296
- "field" => { "$type" => 10 }
1651
+ "location" => { "$nearSphere" => [ 20, 21 ] },
1652
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
3297
1653
  })
3298
1654
  end
3299
1655
 
@@ -3301,16 +1657,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
3301
1657
  expect(selection).to_not equal(query)
3302
1658
  end
3303
1659
  end
1660
+ end
3304
1661
 
3305
- context "when provided a string" do
1662
+ context "when chaining multiple criteria" do
1663
+
1664
+ context "when the fields differ" do
3306
1665
 
3307
1666
  let(:selection) do
3308
- query.with_type(field: "10")
1667
+ query.
1668
+ near_sphere(location: [ 20, 21 ]).
1669
+ near_sphere(comments: [ 20, 21 ])
3309
1670
  end
3310
1671
 
3311
- it "adds the $type selector" do
1672
+ it "adds the $nearSphere expression" do
3312
1673
  expect(selection.selector).to eq({
3313
- "field" => { "$type" => 10 }
1674
+ "location" => { "$nearSphere" => [ 20, 21 ] },
1675
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
3314
1676
  })
3315
1677
  end
3316
1678
 
@@ -3319,19 +1681,27 @@ describe Mongoid::Criteria::Queryable::Selectable do
3319
1681
  end
3320
1682
  end
3321
1683
  end
1684
+ end
3322
1685
 
3323
- context "when provided multiple criterion" do
1686
+ describe "#nin" do
3324
1687
 
3325
- context "when the criterion are for different fields" do
1688
+ let(:query_method) { :nin }
1689
+ let(:operator) { '$nin' }
1690
+
1691
+ it_behaves_like 'requires an argument'
1692
+ it_behaves_like 'requires a non-nil argument'
1693
+
1694
+ context "when provided a single criterion" do
1695
+
1696
+ context "when providing an array" do
3326
1697
 
3327
1698
  let(:selection) do
3328
- query.with_type(first: 10, second: 15)
1699
+ query.nin(field: [ 1, 2 ])
3329
1700
  end
3330
1701
 
3331
- it "adds the $type selectors" do
1702
+ it "adds the $nin selector" do
3332
1703
  expect(selection.selector).to eq({
3333
- "first" => { "$type" => 10 },
3334
- "second" => { "$type" => 15 }
1704
+ "field" => { "$nin" => [ 1, 2 ] }
3335
1705
  })
3336
1706
  end
3337
1707
 
@@ -3339,20 +1709,16 @@ describe Mongoid::Criteria::Queryable::Selectable do
3339
1709
  expect(selection).to_not equal(query)
3340
1710
  end
3341
1711
  end
3342
- end
3343
-
3344
- context "when chaining the criterion" do
3345
1712
 
3346
- context "when the criterion are for different fields" do
1713
+ context "when providing a single value" do
3347
1714
 
3348
1715
  let(:selection) do
3349
- query.with_type(first: 10).with_type(second: 15)
1716
+ query.nin(field: 1)
3350
1717
  end
3351
1718
 
3352
- it "adds the $type selectors" do
1719
+ it "adds the $nin selector with wrapped value" do
3353
1720
  expect(selection.selector).to eq({
3354
- "first" => { "$type" => 10 },
3355
- "second" => { "$type" => 15 }
1721
+ "field" => { "$nin" => [ 1 ] }
3356
1722
  })
3357
1723
  end
3358
1724
 
@@ -3360,16 +1726,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
3360
1726
  expect(selection).to_not equal(query)
3361
1727
  end
3362
1728
  end
1729
+ end
3363
1730
 
3364
- context "when the criterion are on the same field" do
1731
+ context "when provided multiple criterion" do
1732
+
1733
+ context "when the criterion are for different fields" do
3365
1734
 
3366
1735
  let(:selection) do
3367
- query.with_type(first: 10).with_type(first: 15)
1736
+ query.nin(first: [ 1, 2 ], second: [ 3, 4 ])
3368
1737
  end
3369
1738
 
3370
- it "overwrites the first $type selector" do
1739
+ it "adds the $nin selectors" do
3371
1740
  expect(selection.selector).to eq({
3372
- "first" => { "$type" => 15 }
1741
+ "first" => { "$nin" => [ 1, 2 ] },
1742
+ "second" => { "$nin" => [ 3, 4 ] }
3373
1743
  })
3374
1744
  end
3375
1745
 
@@ -3378,510 +1748,313 @@ describe Mongoid::Criteria::Queryable::Selectable do
3378
1748
  end
3379
1749
  end
3380
1750
  end
3381
- end
3382
-
3383
- describe "#text_search" do
3384
1751
 
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
1752
+ context "when chaining the criterion" do
3398
1753
 
3399
- context "when providing text search options" do
1754
+ context "when the criterion are for different fields" do
3400
1755
 
3401
1756
  let(:selection) do
3402
- query.text_search("essais", { :$language => "fr" })
1757
+ query.nin(first: [ 1, 2 ]).nin(second: [ 3, 4 ])
3403
1758
  end
3404
1759
 
3405
- it "constructs a text search document" do
3406
- expect(selection.selector['$text']['$search']).to eq("essais")
1760
+ it "adds the $nin selectors" do
1761
+ expect(selection.selector).to eq({
1762
+ "first" => { "$nin" => [ 1, 2 ] },
1763
+ "second" => { "$nin" => [ 3, 4 ] }
1764
+ })
3407
1765
  end
3408
1766
 
3409
- it "add the options to the text search document" do
3410
- expect(selection.selector['$text'][:$language]).to eq("fr")
1767
+ it "returns a cloned query" do
1768
+ expect(selection).to_not equal(query)
3411
1769
  end
3412
-
3413
- it_behaves_like "a cloning selection"
3414
1770
  end
3415
- end
3416
1771
 
3417
- context 'when given more than once' do
3418
- let(:selection) do
3419
- query.text_search("one").text_search('two')
3420
- end
1772
+ context "when the criterion are on the same field" do
3421
1773
 
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
- )
1774
+ it_behaves_like 'supports merge strategies'
3433
1775
  end
3434
1776
  end
3435
1777
  end
3436
1778
 
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
1779
+ describe "#with_size" do
3482
1780
 
3483
- it "adds the $where criterion" do
3484
- expect(selection.selector).to eq({ "$where" => "this.value = 10" })
3485
- end
1781
+ let(:query_method) { :with_size }
3486
1782
 
3487
- it "returns a cloned query" do
3488
- expect(selection).to_not equal(query)
3489
- end
3490
- end
1783
+ it_behaves_like 'requires an argument'
1784
+ it_behaves_like 'requires a non-nil argument'
3491
1785
 
3492
1786
  context "when provided a single criterion" do
3493
1787
 
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
1788
+ context "when provided an integer" do
3581
1789
 
3582
- let(:selection) do
3583
- query.where(:field.elem_match => { key: 1 })
3584
- end
1790
+ let(:selection) do
1791
+ query.with_size(field: 10)
1792
+ end
3585
1793
 
3586
- it "adds the $elemMatch criterion" do
3587
- expect(selection.selector).to eq(
3588
- { "field" => { "$elemMatch" => { key: 1 } }}
3589
- )
3590
- end
1794
+ it "adds the $size selector" do
1795
+ expect(selection.selector).to eq({
1796
+ "field" => { "$size" => 10 }
1797
+ })
1798
+ end
3591
1799
 
3592
- it "returns a cloned query" do
3593
- expect(selection).to_not eq(query)
3594
- end
1800
+ it "returns a cloned query" do
1801
+ expect(selection).to_not equal(query)
3595
1802
  end
1803
+ end
3596
1804
 
3597
- context "when the value is complex" do
1805
+ context "when provided a string" do
3598
1806
 
3599
- let(:selection) do
3600
- query.where(:field.elem_match => { :key.gt => 1 })
3601
- end
1807
+ let(:selection) do
1808
+ query.with_size(field: "10")
1809
+ end
3602
1810
 
3603
- it "adds the $elemMatch criterion" do
3604
- expect(selection.selector).to eq(
3605
- { "field" => { "$elemMatch" => { "key" => { "$gt" => 1 }}}}
3606
- )
3607
- end
1811
+ it "adds the $size selector with an integer" do
1812
+ expect(selection.selector).to eq({
1813
+ "field" => { "$size" => 10 }
1814
+ })
1815
+ end
3608
1816
 
3609
- it "returns a cloned query" do
3610
- expect(selection).to_not eq(query)
3611
- end
1817
+ it "returns a cloned query" do
1818
+ expect(selection).to_not equal(query)
3612
1819
  end
3613
1820
  end
1821
+ end
3614
1822
 
3615
- context "when performing an $exists" do
1823
+ context "when provided multiple criterion" do
3616
1824
 
3617
- context "when providing boolean values" do
1825
+ context "when the criterion are for different fields" do
1826
+
1827
+ context "when provided integers" do
3618
1828
 
3619
1829
  let(:selection) do
3620
- query.where(:field.exists => true)
1830
+ query.with_size(first: 10, second: 15)
3621
1831
  end
3622
1832
 
3623
- it "adds the $exists criterion" do
3624
- expect(selection.selector).to eq(
3625
- { "field" => { "$exists" => true }}
3626
- )
1833
+ it "adds the $size selectors" do
1834
+ expect(selection.selector).to eq({
1835
+ "first" => { "$size" => 10 },
1836
+ "second" => { "$size" => 15 }
1837
+ })
3627
1838
  end
3628
1839
 
3629
1840
  it "returns a cloned query" do
3630
- expect(selection).to_not eq(query)
1841
+ expect(selection).to_not equal(query)
3631
1842
  end
3632
1843
  end
3633
1844
 
3634
- context "when providing string values" do
1845
+ context "when provided strings" do
3635
1846
 
3636
1847
  let(:selection) do
3637
- query.where(:field.exists => "t")
1848
+ query.with_size(first: "10", second: "15")
3638
1849
  end
3639
1850
 
3640
- it "adds the $exists criterion" do
3641
- expect(selection.selector).to eq(
3642
- { "field" => { "$exists" => true }}
3643
- )
1851
+ it "adds the $size selectors" do
1852
+ expect(selection.selector).to eq({
1853
+ "first" => { "$size" => 10 },
1854
+ "second" => { "$size" => 15 }
1855
+ })
3644
1856
  end
3645
1857
 
3646
1858
  it "returns a cloned query" do
3647
- expect(selection).to_not eq(query)
1859
+ expect(selection).to_not equal(query)
3648
1860
  end
3649
1861
  end
3650
1862
  end
1863
+ end
3651
1864
 
3652
- context "when performing a $gt" do
1865
+ context "when chaining the criterion" do
1866
+
1867
+ context "when the criterion are for different fields" do
3653
1868
 
3654
1869
  let(:selection) do
3655
- query.where(:field.gt => 10)
1870
+ query.with_size(first: 10).with_size(second: 15)
3656
1871
  end
3657
1872
 
3658
- it "adds the $gt criterion" do
3659
- expect(selection.selector).to eq(
3660
- { "field" => { "$gt" => 10 }}
3661
- )
1873
+ it "adds the $size selectors" do
1874
+ expect(selection.selector).to eq({
1875
+ "first" => { "$size" => 10 },
1876
+ "second" => { "$size" => 15 }
1877
+ })
3662
1878
  end
3663
1879
 
3664
1880
  it "returns a cloned query" do
3665
- expect(selection).to_not eq(query)
1881
+ expect(selection).to_not equal(query)
3666
1882
  end
3667
1883
  end
3668
1884
 
3669
- context "when performing a $gte" do
1885
+ context "when the criterion are on the same field" do
3670
1886
 
3671
1887
  let(:selection) do
3672
- query.where(:field.gte => 10)
1888
+ query.with_size(first: 10).with_size(first: 15)
3673
1889
  end
3674
1890
 
3675
- it "adds the $gte criterion" do
3676
- expect(selection.selector).to eq(
3677
- { "field" => { "$gte" => 10 }}
3678
- )
1891
+ it "overwrites the first $size selector" do
1892
+ expect(selection.selector).to eq({
1893
+ "first" => { "$size" => 15 }
1894
+ })
3679
1895
  end
3680
1896
 
3681
1897
  it "returns a cloned query" do
3682
- expect(selection).to_not eq(query)
1898
+ expect(selection).to_not equal(query)
3683
1899
  end
3684
1900
  end
1901
+ end
1902
+ end
3685
1903
 
3686
- context "when performing an $in" do
1904
+ describe "#with_type" do
3687
1905
 
3688
- let(:selection) do
3689
- query.where(:field.in => [ 1, 2 ])
3690
- end
1906
+ let(:query_method) { :with_type }
3691
1907
 
3692
- it "adds the $in criterion" do
3693
- expect(selection.selector).to eq({ "field" => { "$in" => [ 1, 2 ] }})
3694
- end
1908
+ it_behaves_like 'requires an argument'
1909
+ it_behaves_like 'requires a non-nil argument'
3695
1910
 
3696
- it "returns a cloned query" do
3697
- expect(selection).to_not eq(query)
3698
- end
3699
- end
1911
+ context "when provided a single criterion" do
3700
1912
 
3701
- context "when performing a $lt" do
1913
+ context "when provided an integer" do
3702
1914
 
3703
1915
  let(:selection) do
3704
- query.where(:field.lt => 10)
1916
+ query.with_type(field: 10)
3705
1917
  end
3706
1918
 
3707
- it "adds the $lt criterion" do
3708
- expect(selection.selector).to eq(
3709
- { "field" => { "$lt" => 10 }}
3710
- )
1919
+ it "adds the $type selector" do
1920
+ expect(selection.selector).to eq({
1921
+ "field" => { "$type" => 10 }
1922
+ })
3711
1923
  end
3712
1924
 
3713
1925
  it "returns a cloned query" do
3714
- expect(selection).to_not eq(query)
1926
+ expect(selection).to_not equal(query)
3715
1927
  end
3716
1928
  end
3717
1929
 
3718
- context "when performing a $lte" do
1930
+ context "when provided a string" do
3719
1931
 
3720
1932
  let(:selection) do
3721
- query.where(:field.lte => 10)
1933
+ query.with_type(field: "10")
3722
1934
  end
3723
1935
 
3724
- it "adds the $lte criterion" do
3725
- expect(selection.selector).to eq(
3726
- { "field" => { "$lte" => 10 }}
3727
- )
1936
+ it "adds the $type selector" do
1937
+ expect(selection.selector).to eq({
1938
+ "field" => { "$type" => 10 }
1939
+ })
3728
1940
  end
3729
1941
 
3730
1942
  it "returns a cloned query" do
3731
- expect(selection).to_not eq(query)
1943
+ expect(selection).to_not equal(query)
3732
1944
  end
3733
1945
  end
1946
+ end
1947
+
1948
+ context "when provided multiple criterion" do
3734
1949
 
3735
- context "when performing a $mod" do
1950
+ context "when the criterion are for different fields" do
3736
1951
 
3737
1952
  let(:selection) do
3738
- query.where(:field.mod => [ 10, 1 ])
1953
+ query.with_type(first: 10, second: 15)
3739
1954
  end
3740
1955
 
3741
- it "adds the $lte criterion" do
3742
- expect(selection.selector).to eq(
3743
- { "field" => { "$mod" => [ 10, 1 ]}}
3744
- )
1956
+ it "adds the $type selectors" do
1957
+ expect(selection.selector).to eq({
1958
+ "first" => { "$type" => 10 },
1959
+ "second" => { "$type" => 15 }
1960
+ })
3745
1961
  end
3746
1962
 
3747
1963
  it "returns a cloned query" do
3748
- expect(selection).to_not eq(query)
1964
+ expect(selection).to_not equal(query)
3749
1965
  end
3750
1966
  end
1967
+ end
1968
+
1969
+ context "when chaining the criterion" do
3751
1970
 
3752
- context "when performing a $ne" do
1971
+ context "when the criterion are for different fields" do
3753
1972
 
3754
1973
  let(:selection) do
3755
- query.where(:field.ne => 10)
1974
+ query.with_type(first: 10).with_type(second: 15)
3756
1975
  end
3757
1976
 
3758
- it "adds the $ne criterion" do
3759
- expect(selection.selector).to eq(
3760
- { "field" => { "$ne" => 10 }}
3761
- )
1977
+ it "adds the $type selectors" do
1978
+ expect(selection.selector).to eq({
1979
+ "first" => { "$type" => 10 },
1980
+ "second" => { "$type" => 15 }
1981
+ })
3762
1982
  end
3763
1983
 
3764
1984
  it "returns a cloned query" do
3765
- expect(selection).to_not eq(query)
1985
+ expect(selection).to_not equal(query)
3766
1986
  end
3767
1987
  end
3768
1988
 
3769
- context "when performing a $near" do
1989
+ context "when the criterion are on the same field" do
3770
1990
 
3771
1991
  let(:selection) do
3772
- query.where(:field.near => [ 1, 1 ])
1992
+ query.with_type(first: 10).with_type(first: 15)
3773
1993
  end
3774
1994
 
3775
- it "adds the $near criterion" do
3776
- expect(selection.selector).to eq(
3777
- { "field" => { "$near" => [ 1, 1 ] }}
3778
- )
1995
+ it "overwrites the first $type selector" do
1996
+ expect(selection.selector).to eq({
1997
+ "first" => { "$type" => 15 }
1998
+ })
3779
1999
  end
3780
2000
 
3781
2001
  it "returns a cloned query" do
3782
- expect(selection).to_not eq(query)
2002
+ expect(selection).to_not equal(query)
3783
2003
  end
3784
2004
  end
2005
+ end
2006
+ end
3785
2007
 
3786
- context "when performing a $nearSphere" do
3787
-
3788
- let(:selection) do
3789
- query.where(:field.near_sphere => [ 1, 1 ])
3790
- end
2008
+ describe "#text_search" do
3791
2009
 
3792
- it "adds the $nearSphere criterion" do
3793
- expect(selection.selector).to eq(
3794
- { "field" => { "$nearSphere" => [ 1, 1 ] }}
3795
- )
3796
- end
2010
+ context "when providing a search string" do
3797
2011
 
3798
- it "returns a cloned query" do
3799
- expect(selection).to_not eq(query)
3800
- end
2012
+ let(:selection) do
2013
+ query.text_search("testing")
3801
2014
  end
3802
2015
 
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
2016
+ it "constructs a text search document" do
2017
+ expect(selection.selector).to eq({ '$text' => { '$search' => "testing" }})
2018
+ end
3812
2019
 
3813
- it "returns a cloned query" do
3814
- expect(selection).to_not eq(query)
3815
- end
2020
+ it "returns the cloned selectable" do
2021
+ expect(selection).to be_a(Mongoid::Criteria::Queryable::Selectable)
3816
2022
  end
3817
2023
 
3818
- context "when performing a $not" do
2024
+ context "when providing text search options" do
3819
2025
 
3820
2026
  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/ }})
2027
+ query.text_search("essais", { :$language => "fr" })
3826
2028
  end
3827
2029
 
3828
- it "returns a cloned query" do
3829
- expect(selection).to_not eq(query)
2030
+ it "constructs a text search document" do
2031
+ expect(selection.selector['$text']['$search']).to eq("essais")
3830
2032
  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
2033
 
3847
- it "returns a cloned query" do
3848
- expect(selection).to_not eq(query)
3849
- end
2034
+ it "add the options to the text search document" do
2035
+ expect(selection.selector['$text'][:$language]).to eq("fr")
3850
2036
  end
3851
2037
 
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
2038
+ it_behaves_like "returns a cloned query"
3868
2039
  end
2040
+ end
3869
2041
 
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
2042
+ context 'when given more than once' do
2043
+ let(:selection) do
2044
+ query.text_search("one").text_search('two')
2045
+ end
3881
2046
 
3882
- it "returns a cloned query" do
3883
- expect(selection).to_not eq(query)
3884
- end
2047
+ # MongoDB server can only handle one text expression at a time,
2048
+ # per https://www.mongodb.com/docs/manual/reference/operator/query/text/.
2049
+ # Nonetheless we test that the query is built correctly when
2050
+ # a user supplies more than one text condition.
2051
+ it 'merges conditions' do
2052
+ expect(Mongoid.logger).to receive(:warn)
2053
+ expect(selection.selector).to eq('$and' => [
2054
+ {'$text' => {'$search' => 'one'}}
2055
+ ],
2056
+ '$text' => {'$search' => 'two'},
2057
+ )
3885
2058
  end
3886
2059
  end
3887
2060
  end
@@ -3894,7 +2067,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3894
2067
  :field.all
3895
2068
  end
3896
2069
 
3897
- it "returns a selecton key" do
2070
+ it "returns a selection key" do
3898
2071
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3899
2072
  end
3900
2073
 
@@ -3913,7 +2086,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3913
2086
  :field.elem_match
3914
2087
  end
3915
2088
 
3916
- it "returns a selecton key" do
2089
+ it "returns a selection key" do
3917
2090
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3918
2091
  end
3919
2092
 
@@ -3932,7 +2105,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3932
2105
  :field.exists
3933
2106
  end
3934
2107
 
3935
- it "returns a selecton key" do
2108
+ it "returns a selection key" do
3936
2109
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3937
2110
  end
3938
2111
 
@@ -3951,7 +2124,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3951
2124
  :field.gt
3952
2125
  end
3953
2126
 
3954
- it "returns a selecton key" do
2127
+ it "returns a selection key" do
3955
2128
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3956
2129
  end
3957
2130
 
@@ -3970,7 +2143,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3970
2143
  :field.gte
3971
2144
  end
3972
2145
 
3973
- it "returns a selecton key" do
2146
+ it "returns a selection key" do
3974
2147
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3975
2148
  end
3976
2149
 
@@ -3989,7 +2162,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3989
2162
  :field.in
3990
2163
  end
3991
2164
 
3992
- it "returns a selecton key" do
2165
+ it "returns a selection key" do
3993
2166
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3994
2167
  end
3995
2168
 
@@ -4008,7 +2181,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4008
2181
  :field.lt
4009
2182
  end
4010
2183
 
4011
- it "returns a selecton key" do
2184
+ it "returns a selection key" do
4012
2185
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4013
2186
  end
4014
2187
 
@@ -4027,7 +2200,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4027
2200
  :field.lte
4028
2201
  end
4029
2202
 
4030
- it "returns a selecton key" do
2203
+ it "returns a selection key" do
4031
2204
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4032
2205
  end
4033
2206
 
@@ -4046,7 +2219,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4046
2219
  :field.mod
4047
2220
  end
4048
2221
 
4049
- it "returns a selecton key" do
2222
+ it "returns a selection key" do
4050
2223
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4051
2224
  end
4052
2225
 
@@ -4065,7 +2238,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4065
2238
  :field.ne
4066
2239
  end
4067
2240
 
4068
- it "returns a selecton key" do
2241
+ it "returns a selection key" do
4069
2242
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4070
2243
  end
4071
2244
 
@@ -4084,7 +2257,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4084
2257
  :field.near
4085
2258
  end
4086
2259
 
4087
- it "returns a selecton key" do
2260
+ it "returns a selection key" do
4088
2261
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4089
2262
  end
4090
2263
 
@@ -4103,7 +2276,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4103
2276
  :field.near_sphere
4104
2277
  end
4105
2278
 
4106
- it "returns a selecton key" do
2279
+ it "returns a selection key" do
4107
2280
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4108
2281
  end
4109
2282
 
@@ -4122,7 +2295,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4122
2295
  :field.nin
4123
2296
  end
4124
2297
 
4125
- it "returns a selecton key" do
2298
+ it "returns a selection key" do
4126
2299
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4127
2300
  end
4128
2301
 
@@ -4161,7 +2334,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4161
2334
  :field.with_size
4162
2335
  end
4163
2336
 
4164
- it "returns a selecton key" do
2337
+ it "returns a selection key" do
4165
2338
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4166
2339
  end
4167
2340
 
@@ -4180,7 +2353,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4180
2353
  :field.with_type
4181
2354
  end
4182
2355
 
4183
- it "returns a selecton key" do
2356
+ it "returns a selection key" do
4184
2357
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4185
2358
  end
4186
2359
 
@@ -4198,7 +2371,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4198
2371
 
4199
2372
  context "when using the strategies via methods" do
4200
2373
 
4201
- context "when the values are a hash" do
2374
+ context "when different operators are specified" do
4202
2375
 
4203
2376
  let(:selection) do
4204
2377
  query.gt(field: 5).lt(field: 10).ne(field: 7)
@@ -4206,26 +2379,26 @@ describe Mongoid::Criteria::Queryable::Selectable do
4206
2379
 
4207
2380
  it "merges the strategies on the same field" do
4208
2381
  expect(selection.selector).to eq(
4209
- { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
2382
+ "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }
4210
2383
  )
4211
2384
  end
4212
2385
  end
4213
2386
 
4214
- context "when the values are not hashes" do
2387
+ context "when the same operator is specified" do
4215
2388
 
4216
2389
  let(:selection) do
4217
2390
  query.where(field: 5).where(field: 10)
4218
2391
  end
4219
2392
 
4220
- it "overrides the previous field" do
4221
- expect(selection.selector).to eq({ "field" => 10 })
2393
+ it "combines conditions" do
2394
+ expect(selection.selector).to eq("field" => 5, '$and' => [{'field' => 10}] )
4222
2395
  end
4223
2396
  end
4224
2397
  end
4225
2398
 
4226
2399
  context "when using the strategies via #where" do
4227
2400
 
4228
- context "when the values are a hash" do
2401
+ context "when using complex keys with different operators" do
4229
2402
 
4230
2403
  let(:selection) do
4231
2404
  query.where(:field.gt => 5, :field.lt => 10, :field.ne => 7)
@@ -4233,10 +2406,57 @@ describe Mongoid::Criteria::Queryable::Selectable do
4233
2406
 
4234
2407
  it "merges the strategies on the same field" do
4235
2408
  expect(selection.selector).to eq(
4236
- { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
2409
+ "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }
4237
2410
  )
4238
2411
  end
4239
2412
  end
4240
2413
  end
4241
2414
  end
2415
+
2416
+ describe "Mongoid.overwrite_chained_operators" do
2417
+ [ :eq, :elem_match, :gt, :gte, :lt, :lte, :mod, :ne, :near, :near_sphere ].each do |meth|
2418
+
2419
+ context "when chaining the #{meth} method when using the same field" do
2420
+ let(:op) do
2421
+ {
2422
+ eq: "$eq",
2423
+ elem_match: "$elemMatch",
2424
+ gt: "$gt",
2425
+ gte: "$gte",
2426
+ lt: "$lt",
2427
+ lte: "$lte",
2428
+ mod: "$mod",
2429
+ ne: "$ne",
2430
+ near: "$near",
2431
+ near_sphere: "$nearSphere"
2432
+ }[meth]
2433
+ end
2434
+
2435
+ let(:criteria) do
2436
+ Band.send(meth, {views: 1}).send(meth, {views:2})
2437
+ end
2438
+
2439
+ context "when overwrite_chained_operators is true" do
2440
+ config_override :overwrite_chained_operators, true
2441
+
2442
+ it "overrides the previous operators" do
2443
+ expect(criteria.selector).to eq({
2444
+ "views" => { op => 2 },
2445
+ })
2446
+ end
2447
+ end
2448
+
2449
+ context "when overwrite_chained_operators is false" do
2450
+ config_override :overwrite_chained_operators, false
2451
+
2452
+ it "overrides the previous operators" do
2453
+ expect(criteria.selector).to eq({
2454
+ "views" => { op => 1 },
2455
+ "$and" => [{ "views" => { op => 2 } }]
2456
+ })
2457
+ end
2458
+ end
2459
+ end
2460
+ end
2461
+ end
4242
2462
  end