mongoid 7.0.2 → 8.1.1

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 (1104) 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 +100 -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 +42 -38
  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 +106 -67
  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 +104 -127
  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 +149 -89
  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 +3 -4
  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 +49 -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 +152 -73
  84. data/lib/mongoid/clients/factory.rb +42 -17
  85. data/lib/mongoid/clients/options.rb +21 -18
  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 +46 -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 +15 -21
  121. data/lib/mongoid/criteria/options.rb +4 -5
  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 +105 -31
  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 +471 -168
  149. data/lib/mongoid/criteria/queryable/selector.rb +133 -58
  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 +162 -103
  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 -7
  243. data/lib/mongoid/extensions/set.rb +13 -11
  244. data/lib/mongoid/extensions/string.rb +35 -64
  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 -154
  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 +107 -52
  313. data/lib/mongoid/positional.rb +3 -6
  314. data/lib/mongoid/query_cache.rb +18 -234
  315. data/lib/mongoid/railtie.rb +20 -16
  316. data/lib/mongoid/railties/controller_runtime.rb +88 -0
  317. data/lib/mongoid/railties/database.rake +16 -2
  318. data/lib/mongoid/reloadable.rb +19 -22
  319. data/lib/mongoid/scopable.rb +37 -60
  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 +80 -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 +8 -15
  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 +33 -0
  358. data/spec/config/mongoid.yml +29 -3
  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 +33 -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 +83 -0
  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 +61 -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 +8 -0
  480. data/spec/mongoid/association/embedded/embeds_one_models.rb +73 -0
  481. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
  482. data/spec/mongoid/association/embedded/embeds_one_spec.rb +77 -1
  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 +266 -17
  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 +96 -29
  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 +67 -4
  498. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +76 -0
  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 +92 -0
  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 +84 -7
  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_query_spec.rb +23 -0
  508. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +859 -502
  509. data/spec/mongoid/association/referenced/has_many_models.rb +97 -0
  510. data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
  511. data/spec/mongoid/association/referenced/has_many_spec.rb +51 -3
  512. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +2 -0
  513. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +55 -9
  514. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +34 -4
  515. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +135 -27
  516. data/spec/mongoid/association/referenced/has_one_models.rb +113 -0
  517. data/spec/mongoid/association/referenced/has_one_query_spec.rb +37 -0
  518. data/spec/mongoid/association/referenced/has_one_spec.rb +87 -7
  519. data/spec/mongoid/association/reflections_spec.rb +2 -0
  520. data/spec/mongoid/association/syncable_spec.rb +48 -32
  521. data/spec/mongoid/association_spec.rb +2 -0
  522. data/spec/mongoid/atomic/modifiers_spec.rb +49 -0
  523. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +2 -0
  524. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +2 -0
  525. data/spec/mongoid/atomic/paths/root_spec.rb +2 -0
  526. data/spec/mongoid/atomic/paths_spec.rb +93 -12
  527. data/spec/mongoid/atomic_spec.rb +53 -6
  528. data/spec/mongoid/attributes/dynamic_spec.rb +152 -0
  529. data/spec/mongoid/attributes/nested_spec.rb +149 -78
  530. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  531. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  532. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  533. data/spec/mongoid/attributes/projector_spec.rb +40 -0
  534. data/spec/mongoid/attributes/readonly_spec.rb +24 -22
  535. data/spec/mongoid/attributes_spec.rb +895 -54
  536. data/spec/mongoid/cacheable_spec.rb +6 -4
  537. data/spec/mongoid/changeable_spec.rb +484 -67
  538. data/spec/mongoid/clients/factory_spec.rb +139 -33
  539. data/spec/mongoid/clients/options_spec.rb +76 -54
  540. data/spec/mongoid/clients/sessions_spec.rb +35 -63
  541. data/spec/mongoid/clients/transactions_spec.rb +87 -41
  542. data/spec/mongoid/clients_spec.rb +257 -31
  543. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  544. data/spec/mongoid/composable_spec.rb +2 -0
  545. data/spec/mongoid/config/defaults_spec.rb +160 -0
  546. data/spec/mongoid/config/environment_spec.rb +126 -8
  547. data/spec/mongoid/config/options_spec.rb +22 -3
  548. data/spec/mongoid/config_spec.rb +507 -2
  549. data/spec/mongoid/contextual/aggregable/memory_spec.rb +433 -153
  550. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  551. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  552. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
  553. data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
  554. data/spec/mongoid/contextual/atomic_spec.rb +242 -81
  555. data/spec/mongoid/contextual/geo_near_spec.rb +31 -19
  556. data/spec/mongoid/contextual/map_reduce_spec.rb +22 -19
  557. data/spec/mongoid/contextual/memory_spec.rb +1828 -303
  558. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  559. data/spec/mongoid/contextual/mongo_spec.rb +3505 -1268
  560. data/spec/mongoid/contextual/none_spec.rb +80 -67
  561. data/spec/mongoid/copyable_spec.rb +697 -40
  562. data/spec/mongoid/copyable_spec_models.rb +47 -0
  563. data/spec/mongoid/criteria/findable_spec.rb +161 -228
  564. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  565. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  566. data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
  567. data/spec/mongoid/criteria/marshalable_spec.rb +20 -1
  568. data/spec/mongoid/criteria/modifiable_spec.rb +100 -48
  569. data/spec/mongoid/criteria/options_spec.rb +2 -0
  570. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +3 -1
  571. data/spec/mongoid/criteria/queryable/expandable_spec.rb +61 -0
  572. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +9 -19
  573. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +136 -26
  574. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +3 -1
  575. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +13 -0
  576. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +46 -17
  577. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +2 -0
  578. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +2 -15
  579. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +2 -0
  580. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +2 -0
  581. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +119 -0
  582. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +2 -0
  583. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +239 -178
  584. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +3 -1
  585. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +9 -7
  586. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +2 -0
  587. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +7 -70
  588. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +2 -59
  589. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +53 -23
  590. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +41 -1
  591. data/spec/mongoid/criteria/queryable/key_spec.rb +50 -6
  592. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +145 -12
  593. data/spec/mongoid/criteria/queryable/optional_spec.rb +18 -485
  594. data/spec/mongoid/criteria/queryable/options_spec.rb +3 -1
  595. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +2 -0
  596. data/spec/mongoid/criteria/queryable/queryable_spec.rb +3 -1
  597. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +2538 -0
  598. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
  599. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1193 -2934
  600. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
  601. data/spec/mongoid/criteria/queryable/selector_spec.rb +56 -5
  602. data/spec/mongoid/criteria/queryable/smash_spec.rb +2 -0
  603. data/spec/mongoid/criteria/queryable/storable_spec.rb +226 -0
  604. data/spec/mongoid/criteria/scopable_spec.rb +210 -0
  605. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  606. data/spec/mongoid/criteria_projection_spec.rb +406 -0
  607. data/spec/mongoid/criteria_spec.rb +1334 -1719
  608. data/spec/mongoid/document_fields_spec.rb +262 -0
  609. data/spec/mongoid/document_persistence_context_spec.rb +32 -0
  610. data/spec/mongoid/document_query_spec.rb +89 -0
  611. data/spec/mongoid/document_spec.rb +212 -67
  612. data/spec/mongoid/equality_spec.rb +144 -41
  613. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +5 -3
  614. data/spec/mongoid/errors/callback_spec.rb +2 -0
  615. data/spec/mongoid/errors/delete_restriction_spec.rb +4 -2
  616. data/spec/mongoid/errors/document_not_destroyed_spec.rb +2 -0
  617. data/spec/mongoid/errors/document_not_found_spec.rb +78 -0
  618. data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
  619. data/spec/mongoid/errors/{eager_load_spec.rb → invalid_config_file_spec.rb} +7 -5
  620. data/spec/mongoid/errors/invalid_config_option_spec.rb +2 -0
  621. data/spec/mongoid/errors/invalid_field_option_spec.rb +2 -0
  622. data/spec/mongoid/errors/invalid_field_spec.rb +3 -1
  623. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  624. data/spec/mongoid/errors/invalid_find_spec.rb +2 -0
  625. data/spec/mongoid/errors/invalid_includes_spec.rb +2 -0
  626. data/spec/mongoid/errors/invalid_index_spec.rb +2 -0
  627. data/spec/mongoid/errors/invalid_options_spec.rb +4 -2
  628. data/spec/mongoid/errors/invalid_path_spec.rb +2 -0
  629. data/spec/mongoid/errors/invalid_relation_spec.rb +4 -2
  630. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -1
  631. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +2 -0
  632. data/spec/mongoid/errors/invalid_storage_options_spec.rb +2 -0
  633. data/spec/mongoid/errors/invalid_time_spec.rb +2 -0
  634. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -1
  635. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +2 -0
  636. data/spec/mongoid/errors/mixed_relations_spec.rb +2 -0
  637. data/spec/mongoid/errors/mongoid_error_spec.rb +24 -8
  638. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +5 -3
  639. data/spec/mongoid/errors/no_client_config_spec.rb +4 -2
  640. data/spec/mongoid/errors/no_client_database_spec.rb +5 -3
  641. data/spec/mongoid/errors/no_client_hosts_spec.rb +5 -3
  642. data/spec/mongoid/errors/no_clients_config_spec.rb +2 -0
  643. data/spec/mongoid/errors/no_environment_spec.rb +5 -3
  644. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +2 -0
  645. data/spec/mongoid/errors/no_metadata_spec.rb +4 -2
  646. data/spec/mongoid/errors/no_parent_spec.rb +3 -1
  647. data/spec/mongoid/errors/readonly_attribute_spec.rb +2 -0
  648. data/spec/mongoid/errors/readonly_document_spec.rb +4 -2
  649. data/spec/mongoid/errors/scope_overwrite_spec.rb +2 -0
  650. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +3 -1
  651. data/spec/mongoid/errors/unknown_attribute_spec.rb +4 -2
  652. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -1
  653. data/spec/mongoid/errors/unsupported_javascript_spec.rb +2 -0
  654. data/spec/mongoid/errors/validations_spec.rb +2 -0
  655. data/spec/mongoid/extensions/array_spec.rb +41 -45
  656. data/spec/mongoid/extensions/big_decimal_spec.rb +715 -213
  657. data/spec/mongoid/extensions/binary_spec.rb +46 -9
  658. data/spec/mongoid/extensions/boolean_spec.rb +70 -82
  659. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +339 -0
  660. data/spec/mongoid/extensions/date_spec.rb +58 -140
  661. data/spec/mongoid/extensions/date_time_spec.rb +32 -69
  662. data/spec/mongoid/extensions/decimal128_spec.rb +2 -0
  663. data/spec/mongoid/extensions/false_class_spec.rb +3 -1
  664. data/spec/mongoid/extensions/float_spec.rb +66 -73
  665. data/spec/mongoid/extensions/hash_spec.rb +135 -0
  666. data/spec/mongoid/extensions/integer_spec.rb +61 -63
  667. data/spec/mongoid/extensions/module_spec.rb +2 -0
  668. data/spec/mongoid/extensions/nil_class_spec.rb +2 -0
  669. data/spec/mongoid/extensions/object_id_spec.rb +2 -0
  670. data/spec/mongoid/extensions/object_spec.rb +13 -24
  671. data/spec/mongoid/extensions/range_spec.rb +257 -54
  672. data/spec/mongoid/extensions/regexp_spec.rb +70 -20
  673. data/spec/mongoid/extensions/set_spec.rb +108 -0
  674. data/spec/mongoid/extensions/string_spec.rb +146 -57
  675. data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
  676. data/spec/mongoid/extensions/symbol_spec.rb +20 -25
  677. data/spec/mongoid/extensions/time_spec.rb +668 -106
  678. data/spec/mongoid/extensions/time_with_zone_spec.rb +57 -83
  679. data/spec/mongoid/extensions/true_class_spec.rb +3 -1
  680. data/spec/mongoid/extensions_spec.rb +16 -2
  681. data/spec/mongoid/factory_spec.rb +347 -27
  682. data/spec/mongoid/fields/foreign_key_spec.rb +2 -0
  683. data/spec/mongoid/fields/localized_spec.rb +86 -41
  684. data/spec/mongoid/fields/standard_spec.rb +2 -0
  685. data/spec/mongoid/fields_spec.rb +869 -114
  686. data/spec/mongoid/findable_spec.rb +521 -65
  687. data/spec/mongoid/indexable/specification_spec.rb +4 -2
  688. data/spec/mongoid/indexable_spec.rb +87 -32
  689. data/spec/mongoid/inspectable_spec.rb +39 -2
  690. data/spec/mongoid/interceptable_spec.rb +761 -98
  691. data/spec/mongoid/interceptable_spec_models.rb +307 -0
  692. data/spec/mongoid/loggable_spec.rb +2 -0
  693. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  694. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
  695. data/spec/mongoid/matcher/extract_attribute_spec.rb +36 -0
  696. data/spec/mongoid/mongoizable_spec.rb +285 -0
  697. data/spec/mongoid/persistable/creatable_spec.rb +114 -29
  698. data/spec/mongoid/persistable/deletable_spec.rb +300 -18
  699. data/spec/mongoid/persistable/destroyable_spec.rb +228 -18
  700. data/spec/mongoid/persistable/incrementable_spec.rb +66 -13
  701. data/spec/mongoid/persistable/logical_spec.rb +56 -3
  702. data/spec/mongoid/persistable/poppable_spec.rb +55 -3
  703. data/spec/mongoid/persistable/pullable_spec.rb +108 -6
  704. data/spec/mongoid/persistable/pushable_spec.rb +163 -7
  705. data/spec/mongoid/persistable/renamable_spec.rb +54 -2
  706. data/spec/mongoid/persistable/savable_spec.rb +284 -25
  707. data/spec/mongoid/persistable/settable_spec.rb +91 -8
  708. data/spec/mongoid/persistable/unsettable_spec.rb +55 -3
  709. data/spec/mongoid/persistable/updatable_spec.rb +63 -49
  710. data/spec/mongoid/persistable/upsertable_spec.rb +93 -3
  711. data/spec/mongoid/persistable_spec.rb +85 -9
  712. data/spec/mongoid/persistence_context_spec.rb +60 -59
  713. data/spec/mongoid/positional_spec.rb +2 -0
  714. data/spec/mongoid/query_cache_middleware_spec.rb +50 -0
  715. data/spec/mongoid/query_cache_spec.rb +446 -78
  716. data/spec/mongoid/relations/proxy_spec.rb +9 -7
  717. data/spec/mongoid/reloadable_spec.rb +381 -26
  718. data/spec/mongoid/scopable_spec.rb +206 -38
  719. data/spec/mongoid/selectable_spec.rb +8 -6
  720. data/spec/mongoid/serializable_spec.rb +148 -38
  721. data/spec/mongoid/shardable_models.rb +75 -0
  722. data/spec/mongoid/shardable_spec.rb +239 -34
  723. data/spec/mongoid/stateful_spec.rb +153 -9
  724. data/spec/mongoid/tasks/database_rake_spec.rb +89 -13
  725. data/spec/mongoid/tasks/database_spec.rb +130 -1
  726. data/spec/mongoid/threaded_spec.rb +72 -2
  727. data/spec/mongoid/timestamps/created/short_spec.rb +3 -1
  728. data/spec/mongoid/timestamps/created_spec.rb +3 -1
  729. data/spec/mongoid/timestamps/timeless_spec.rb +4 -2
  730. data/spec/mongoid/timestamps/updated/short_spec.rb +5 -3
  731. data/spec/mongoid/timestamps/updated_spec.rb +5 -3
  732. data/spec/mongoid/timestamps_spec.rb +400 -10
  733. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  734. data/spec/mongoid/touchable_spec.rb +568 -33
  735. data/spec/mongoid/touchable_spec_models.rb +59 -0
  736. data/spec/mongoid/traversable_spec.rb +1145 -1
  737. data/spec/mongoid/validatable/associated_spec.rb +2 -0
  738. data/spec/mongoid/validatable/format_spec.rb +2 -0
  739. data/spec/mongoid/validatable/length_spec.rb +2 -0
  740. data/spec/mongoid/validatable/numericality_spec.rb +2 -0
  741. data/spec/mongoid/validatable/presence_spec.rb +28 -22
  742. data/spec/mongoid/validatable/uniqueness_spec.rb +159 -103
  743. data/spec/mongoid/validatable_spec.rb +5 -3
  744. data/spec/mongoid/warnings_spec.rb +35 -0
  745. data/spec/mongoid_spec.rb +36 -10
  746. data/spec/rails/controller_extension/controller_runtime_spec.rb +112 -0
  747. data/spec/rails/mongoid_spec.rb +8 -18
  748. data/spec/shared/LICENSE +20 -0
  749. data/spec/shared/bin/get-mongodb-download-url +17 -0
  750. data/spec/shared/bin/s3-copy +45 -0
  751. data/spec/shared/bin/s3-upload +69 -0
  752. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  753. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  754. data/spec/shared/lib/mrss/constraints.rb +378 -0
  755. data/spec/shared/lib/mrss/docker_runner.rb +298 -0
  756. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  757. data/spec/shared/lib/mrss/event_subscriber.rb +210 -0
  758. data/spec/shared/lib/mrss/lite_constraints.rb +238 -0
  759. data/spec/shared/lib/mrss/server_version_registry.rb +113 -0
  760. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  761. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  762. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  763. data/spec/shared/lib/mrss/utils.rb +37 -0
  764. data/spec/shared/share/Dockerfile.erb +321 -0
  765. data/spec/shared/share/haproxy-1.conf +16 -0
  766. data/spec/shared/share/haproxy-2.conf +17 -0
  767. data/spec/shared/shlib/config.sh +27 -0
  768. data/spec/shared/shlib/distro.sh +74 -0
  769. data/spec/shared/shlib/server.sh +416 -0
  770. data/spec/shared/shlib/set_env.sh +169 -0
  771. data/spec/spec_helper.rb +74 -88
  772. data/spec/support/authorization.rb +2 -0
  773. data/spec/support/client_registry.rb +9 -0
  774. data/spec/support/constraints.rb +77 -0
  775. data/spec/support/expectations.rb +21 -3
  776. data/spec/support/helpers.rb +11 -0
  777. data/spec/support/immutable_ids.rb +118 -0
  778. data/spec/support/macros.rb +129 -0
  779. data/spec/{app → support}/models/account.rb +3 -1
  780. data/spec/{app → support}/models/acolyte.rb +2 -0
  781. data/spec/{app → support}/models/actor.rb +3 -1
  782. data/spec/support/models/actress.rb +4 -0
  783. data/spec/{app → support}/models/address.rb +6 -0
  784. data/spec/{app → support}/models/address_component.rb +2 -0
  785. data/spec/{app → support}/models/address_number.rb +2 -0
  786. data/spec/{app → support}/models/agency.rb +2 -0
  787. data/spec/{app → support}/models/agent.rb +2 -0
  788. data/spec/{app → support}/models/album.rb +2 -0
  789. data/spec/{app → support}/models/alert.rb +2 -0
  790. data/spec/{app → support}/models/animal.rb +2 -0
  791. data/spec/{app → support}/models/answer.rb +2 -0
  792. data/spec/{app → support}/models/appointment.rb +2 -0
  793. data/spec/support/models/armrest.rb +9 -0
  794. data/spec/{app → support}/models/article.rb +2 -0
  795. data/spec/{app → support}/models/artist.rb +4 -1
  796. data/spec/{app → support}/models/artwork.rb +2 -0
  797. data/spec/support/models/audible_sound.rb +3 -0
  798. data/spec/{app → support}/models/audio.rb +2 -0
  799. data/spec/support/models/augmentation.rb +25 -0
  800. data/spec/{app → support}/models/author.rb +2 -0
  801. data/spec/{app → support}/models/baby.rb +2 -0
  802. data/spec/{app → support}/models/band.rb +10 -0
  803. data/spec/{app → support}/models/bar.rb +2 -0
  804. data/spec/{app → support}/models/basic.rb +2 -0
  805. data/spec/support/models/bed.rb +3 -0
  806. data/spec/{app → support}/models/big_palette.rb +2 -0
  807. data/spec/{app → support}/models/birthday.rb +2 -0
  808. data/spec/support/models/bolt.rb +7 -0
  809. data/spec/{app → support}/models/bomb.rb +2 -0
  810. data/spec/{app → support}/models/book.rb +3 -0
  811. data/spec/{app → support}/models/breed.rb +2 -0
  812. data/spec/{app → support}/models/browser.rb +3 -1
  813. data/spec/{app → support}/models/building.rb +4 -0
  814. data/spec/{app → support}/models/building_address.rb +2 -0
  815. data/spec/{app → support}/models/bus.rb +2 -0
  816. data/spec/{app → support}/models/business.rb +2 -0
  817. data/spec/{app → support}/models/callback_test.rb +2 -0
  818. data/spec/{app → support}/models/canvas.rb +3 -1
  819. data/spec/support/models/car.rb +3 -0
  820. data/spec/{app → support}/models/cat.rb +2 -0
  821. data/spec/support/models/catalog.rb +24 -0
  822. data/spec/{app → support}/models/category.rb +2 -0
  823. data/spec/{app → support}/models/child.rb +2 -0
  824. data/spec/{app → support}/models/child_doc.rb +5 -3
  825. data/spec/{app → support}/models/church.rb +2 -0
  826. data/spec/{app → support}/models/circle.rb +2 -0
  827. data/spec/{app → support}/models/circuit.rb +2 -0
  828. data/spec/support/models/circus.rb +12 -0
  829. data/spec/{app → support}/models/code.rb +4 -0
  830. data/spec/support/models/coding/pull_request.rb +11 -0
  831. data/spec/support/models/coding.rb +3 -0
  832. data/spec/{app → support}/models/comment.rb +2 -0
  833. data/spec/{app → support}/models/company.rb +2 -0
  834. data/spec/{app → support}/models/consumption_period.rb +2 -0
  835. data/spec/{app → support}/models/contextable_item.rb +2 -0
  836. data/spec/{app → support}/models/contractor.rb +2 -0
  837. data/spec/{app → support}/models/cookie.rb +2 -0
  838. data/spec/{app → support}/models/country_code.rb +4 -0
  839. data/spec/{app → support}/models/courier_job.rb +2 -0
  840. data/spec/support/models/cover.rb +10 -0
  841. data/spec/support/models/crate.rb +12 -0
  842. data/spec/support/models/customer.rb +10 -0
  843. data/spec/support/models/customer_address.rb +11 -0
  844. data/spec/support/models/deed.rb +7 -0
  845. data/spec/{app → support}/models/definition.rb +2 -0
  846. data/spec/support/models/delegating_patient.rb +15 -0
  847. data/spec/{app → support}/models/description.rb +2 -0
  848. data/spec/{app → support}/models/dictionary.rb +8 -0
  849. data/spec/{app → support}/models/division.rb +2 -0
  850. data/spec/{app → support}/models/doctor.rb +2 -0
  851. data/spec/{app → support}/models/dog.rb +2 -0
  852. data/spec/{app → support}/models/dokument.rb +2 -0
  853. data/spec/{app → support}/models/draft.rb +2 -0
  854. data/spec/{app → support}/models/dragon.rb +2 -0
  855. data/spec/{app → support}/models/driver.rb +3 -1
  856. data/spec/{app → support}/models/drug.rb +2 -0
  857. data/spec/{app → support}/models/dungeon.rb +2 -0
  858. data/spec/{app → support}/models/edit.rb +2 -0
  859. data/spec/{app → support}/models/email.rb +2 -0
  860. data/spec/{app → support}/models/employer.rb +2 -0
  861. data/spec/{app → support}/models/entry.rb +2 -0
  862. data/spec/support/models/eraser.rb +3 -0
  863. data/spec/{app → support}/models/even.rb +2 -0
  864. data/spec/{app → support}/models/event.rb +2 -0
  865. data/spec/{app → support}/models/exhibition.rb +2 -0
  866. data/spec/{app → support}/models/exhibitor.rb +2 -0
  867. data/spec/{app → support}/models/explosion.rb +2 -0
  868. data/spec/{app → support}/models/eye.rb +2 -0
  869. data/spec/{app → support}/models/eye_bowl.rb +2 -0
  870. data/spec/{app → support}/models/face.rb +2 -0
  871. data/spec/support/models/fanatic.rb +8 -0
  872. data/spec/{app → support}/models/favorite.rb +2 -0
  873. data/spec/{app → support}/models/filesystem.rb +2 -0
  874. data/spec/{app → support}/models/fire_hydrant.rb +2 -0
  875. data/spec/{app → support}/models/firefox.rb +2 -0
  876. data/spec/{app → support}/models/fish.rb +2 -0
  877. data/spec/{app → support}/models/folder.rb +2 -0
  878. data/spec/{app → support}/models/folder_item.rb +2 -0
  879. data/spec/{app → support}/models/fruits.rb +2 -0
  880. data/spec/{app → support}/models/game.rb +2 -0
  881. data/spec/{app → support}/models/ghost.rb +2 -0
  882. data/spec/support/models/guitar.rb +4 -0
  883. data/spec/support/models/hole.rb +12 -0
  884. data/spec/{app → support}/models/home.rb +2 -0
  885. data/spec/{app → support}/models/house.rb +2 -0
  886. data/spec/{app → support}/models/html_writer.rb +2 -0
  887. data/spec/{app → support}/models/id_key.rb +2 -0
  888. data/spec/support/models/idnodef.rb +7 -0
  889. data/spec/{app → support}/models/image.rb +2 -0
  890. data/spec/{app → support}/models/implant.rb +11 -0
  891. data/spec/support/models/instrument.rb +8 -0
  892. data/spec/{app → support}/models/item.rb +3 -1
  893. data/spec/{app → support}/models/jar.rb +2 -0
  894. data/spec/{app → support}/models/kaleidoscope.rb +2 -0
  895. data/spec/{app → support}/models/kangaroo.rb +3 -1
  896. data/spec/{app → support}/models/label.rb +6 -1
  897. data/spec/{app → support}/models/language.rb +2 -0
  898. data/spec/{app → support}/models/lat_lng.rb +2 -0
  899. data/spec/{app → support}/models/league.rb +2 -0
  900. data/spec/support/models/learner.rb +4 -0
  901. data/spec/{app → support}/models/line_item.rb +2 -0
  902. data/spec/{app → support}/models/location.rb +2 -0
  903. data/spec/{app → support}/models/login.rb +2 -0
  904. data/spec/{app → support}/models/manufacturer.rb +2 -0
  905. data/spec/{app → support}/models/meat.rb +2 -0
  906. data/spec/{app → support}/models/membership.rb +3 -0
  907. data/spec/{app → support}/models/message.rb +2 -0
  908. data/spec/support/models/minim.rb +6 -0
  909. data/spec/{app → support}/models/mixed_drink.rb +2 -0
  910. data/spec/support/models/mop.rb +24 -0
  911. data/spec/{app → support}/models/movie.rb +2 -0
  912. data/spec/support/models/my_hash.rb +4 -0
  913. data/spec/{app → support}/models/name.rb +2 -0
  914. data/spec/support/models/name_only.rb +8 -0
  915. data/spec/{app → support}/models/node.rb +2 -0
  916. data/spec/{app → support}/models/note.rb +2 -0
  917. data/spec/support/models/nut.rb +7 -0
  918. data/spec/{app → support}/models/odd.rb +2 -0
  919. data/spec/support/models/order.rb +12 -0
  920. data/spec/{app → support}/models/ordered_post.rb +3 -1
  921. data/spec/{app → support}/models/ordered_preference.rb +2 -0
  922. data/spec/{app → support}/models/oscar.rb +2 -0
  923. data/spec/support/models/other_owner_object.rb +4 -0
  924. data/spec/{app → support}/models/override.rb +2 -0
  925. data/spec/{app → support}/models/ownable.rb +2 -0
  926. data/spec/{app → support}/models/owner.rb +4 -0
  927. data/spec/{app → support}/models/pack.rb +2 -0
  928. data/spec/{app → support}/models/page.rb +2 -0
  929. data/spec/{app → support}/models/page_question.rb +2 -0
  930. data/spec/{app → support}/models/palette.rb +3 -1
  931. data/spec/{app → support}/models/parent.rb +2 -0
  932. data/spec/{app → support}/models/parent_doc.rb +2 -0
  933. data/spec/support/models/passport.rb +22 -0
  934. data/spec/{app → support}/models/patient.rb +2 -0
  935. data/spec/{app → support}/models/pdf_writer.rb +2 -0
  936. data/spec/support/models/pencil.rb +3 -0
  937. data/spec/{app → support}/models/person.rb +22 -1
  938. data/spec/{app → support}/models/pet.rb +2 -0
  939. data/spec/{app → support}/models/pet_owner.rb +2 -0
  940. data/spec/{app → support}/models/phone.rb +5 -1
  941. data/spec/support/models/piano.rb +4 -0
  942. data/spec/{app → support}/models/pizza.rb +2 -0
  943. data/spec/{app → support}/models/player.rb +4 -0
  944. data/spec/{app → support}/models/post.rb +2 -0
  945. data/spec/{app → support}/models/post_genre.rb +2 -0
  946. data/spec/support/models/powerup.rb +25 -0
  947. data/spec/{app → support}/models/preference.rb +2 -0
  948. data/spec/{app → support}/models/princess.rb +2 -0
  949. data/spec/{app → support}/models/product.rb +3 -0
  950. data/spec/support/models/profile.rb +17 -0
  951. data/spec/{app → support}/models/pronunciation.rb +2 -0
  952. data/spec/{app → support}/models/pub.rb +2 -0
  953. data/spec/support/models/publication/encyclopedia.rb +11 -0
  954. data/spec/support/models/publication/review.rb +13 -0
  955. data/spec/support/models/publication.rb +4 -0
  956. data/spec/{app → support}/models/purchase.rb +2 -0
  957. data/spec/support/models/purchased_item.rb +10 -0
  958. data/spec/{app → support}/models/question.rb +2 -0
  959. data/spec/{app → support}/models/quiz.rb +2 -0
  960. data/spec/{app → support}/models/rating.rb +2 -0
  961. data/spec/{app → support}/models/record.rb +2 -0
  962. data/spec/{app → support}/models/registry.rb +3 -0
  963. data/spec/{app → support}/models/role.rb +2 -0
  964. data/spec/{app → support}/models/root_category.rb +2 -0
  965. data/spec/{app → support}/models/sandwich.rb +2 -0
  966. data/spec/{app → support}/models/scheduler.rb +2 -0
  967. data/spec/support/models/school.rb +14 -0
  968. data/spec/support/models/scribe.rb +7 -0
  969. data/spec/support/models/sealer.rb +7 -0
  970. data/spec/support/models/seat.rb +24 -0
  971. data/spec/{app → support}/models/seo.rb +2 -0
  972. data/spec/support/models/series.rb +7 -0
  973. data/spec/{app → support}/models/server.rb +2 -0
  974. data/spec/{app → support}/models/service.rb +2 -0
  975. data/spec/{app → support}/models/shape.rb +4 -2
  976. data/spec/{app → support}/models/shelf.rb +2 -0
  977. data/spec/support/models/shield.rb +18 -0
  978. data/spec/{app → support}/models/shipment_address.rb +2 -0
  979. data/spec/{app → support}/models/shipping_container.rb +2 -0
  980. data/spec/{app → support}/models/shipping_pack.rb +2 -0
  981. data/spec/support/models/shirt.rb +11 -0
  982. data/spec/{app → support}/models/shop.rb +2 -0
  983. data/spec/{app → support}/models/short_agent.rb +2 -0
  984. data/spec/{app → support}/models/short_quiz.rb +2 -0
  985. data/spec/{app → support}/models/simple.rb +2 -0
  986. data/spec/{app → support}/models/slave.rb +2 -0
  987. data/spec/{app → support}/models/song.rb +2 -0
  988. data/spec/{app → support}/models/sound.rb +2 -0
  989. data/spec/support/models/spacer.rb +7 -0
  990. data/spec/{app → support}/models/square.rb +2 -0
  991. data/spec/{app → support}/models/staff.rb +2 -0
  992. data/spec/{app → support}/models/store_as_dup_test1.rb +2 -0
  993. data/spec/{app → support}/models/store_as_dup_test2.rb +2 -0
  994. data/spec/support/models/store_as_dup_test3.rb +7 -0
  995. data/spec/support/models/store_as_dup_test4.rb +7 -0
  996. data/spec/{app → support}/models/strategy.rb +2 -0
  997. data/spec/support/models/student.rb +14 -0
  998. data/spec/{app → support}/models/sub_item.rb +2 -0
  999. data/spec/{app → support}/models/subscription.rb +2 -0
  1000. data/spec/{app → support}/models/survey.rb +2 -0
  1001. data/spec/{app → support}/models/symptom.rb +2 -0
  1002. data/spec/support/models/system_role.rb +7 -0
  1003. data/spec/{app → support}/models/tag.rb +2 -0
  1004. data/spec/{app → support}/models/target.rb +2 -0
  1005. data/spec/{app → support}/models/template.rb +2 -0
  1006. data/spec/{app → support}/models/thing.rb +2 -0
  1007. data/spec/support/models/threadlocker.rb +7 -0
  1008. data/spec/{app → support}/models/title.rb +2 -0
  1009. data/spec/{app → support}/models/tool.rb +4 -2
  1010. data/spec/{app → support}/models/topping.rb +2 -0
  1011. data/spec/support/models/toy.rb +9 -0
  1012. data/spec/{app → support}/models/track.rb +2 -0
  1013. data/spec/{app → support}/models/translation.rb +2 -0
  1014. data/spec/{app → support}/models/tree.rb +2 -0
  1015. data/spec/support/models/truck.rb +7 -0
  1016. data/spec/{app → support}/models/user.rb +2 -0
  1017. data/spec/{app → support}/models/user_account.rb +2 -0
  1018. data/spec/{app → support}/models/validation_callback.rb +2 -0
  1019. data/spec/support/models/vehicle.rb +18 -0
  1020. data/spec/{app → support}/models/version.rb +2 -0
  1021. data/spec/{app → support}/models/vertex.rb +3 -1
  1022. data/spec/{app → support}/models/vet_visit.rb +2 -0
  1023. data/spec/{app → support}/models/video.rb +2 -0
  1024. data/spec/support/models/video_game.rb +3 -0
  1025. data/spec/support/models/washer.rb +7 -0
  1026. data/spec/support/models/weapon.rb +25 -0
  1027. data/spec/{app → support}/models/wiki_page.rb +3 -0
  1028. data/spec/{app → support}/models/word.rb +2 -0
  1029. data/spec/{app → support}/models/word_origin.rb +2 -0
  1030. data/spec/{app → support}/models/writer.rb +4 -2
  1031. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  1032. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  1033. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  1034. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  1035. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  1036. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  1037. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  1038. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  1039. data/spec/support/schema_maps/schema_map_local.json +18 -0
  1040. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  1041. data/spec/support/shared/time.rb +53 -0
  1042. data/spec/support/spec_config.rb +64 -0
  1043. data.tar.gz.sig +1 -2
  1044. metadata +1158 -615
  1045. metadata.gz.sig +0 -0
  1046. data/lib/mongoid/criteria/queryable/forwardable.rb +0 -65
  1047. data/lib/mongoid/errors/eager_load.rb +0 -22
  1048. data/lib/mongoid/errors/invalid_value.rb +0 -16
  1049. data/lib/mongoid/matchable/all.rb +0 -27
  1050. data/lib/mongoid/matchable/and.rb +0 -30
  1051. data/lib/mongoid/matchable/default.rb +0 -72
  1052. data/lib/mongoid/matchable/elem_match.rb +0 -34
  1053. data/lib/mongoid/matchable/exists.rb +0 -23
  1054. data/lib/mongoid/matchable/gt.rb +0 -23
  1055. data/lib/mongoid/matchable/gte.rb +0 -23
  1056. data/lib/mongoid/matchable/in.rb +0 -24
  1057. data/lib/mongoid/matchable/lt.rb +0 -23
  1058. data/lib/mongoid/matchable/lte.rb +0 -23
  1059. data/lib/mongoid/matchable/ne.rb +0 -21
  1060. data/lib/mongoid/matchable/nin.rb +0 -22
  1061. data/lib/mongoid/matchable/nor.rb +0 -37
  1062. data/lib/mongoid/matchable/or.rb +0 -33
  1063. data/lib/mongoid/matchable/regexp.rb +0 -27
  1064. data/lib/mongoid/matchable/size.rb +0 -21
  1065. data/lib/support/ruby_version.rb +0 -26
  1066. data/spec/app/models/actress.rb +0 -2
  1067. data/spec/app/models/augmentation.rb +0 -11
  1068. data/spec/app/models/bed.rb +0 -1
  1069. data/spec/app/models/car.rb +0 -1
  1070. data/spec/app/models/circus.rb +0 -7
  1071. data/spec/app/models/eraser.rb +0 -1
  1072. data/spec/app/models/learner.rb +0 -2
  1073. data/spec/app/models/my_hash.rb +0 -2
  1074. data/spec/app/models/passport.rb +0 -5
  1075. data/spec/app/models/pencil.rb +0 -1
  1076. data/spec/app/models/powerup.rb +0 -11
  1077. data/spec/app/models/profile.rb +0 -5
  1078. data/spec/app/models/series.rb +0 -4
  1079. data/spec/app/models/truck.rb +0 -3
  1080. data/spec/app/models/vehicle.rb +0 -11
  1081. data/spec/app/models/video_game.rb +0 -1
  1082. data/spec/app/models/weapon.rb +0 -11
  1083. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -58
  1084. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -58
  1085. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +0 -87
  1086. data/spec/mongoid/matchable/all_spec.rb +0 -31
  1087. data/spec/mongoid/matchable/and_spec.rb +0 -187
  1088. data/spec/mongoid/matchable/default_spec.rb +0 -130
  1089. data/spec/mongoid/matchable/elem_match_spec.rb +0 -106
  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/{app → support}/models/array_field.rb +0 -0
  1104. /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,2034 +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
387
- end
388
- end
389
- end
390
- end
391
- end
392
-
393
- describe "#and" do
394
-
395
- context "when provided no criterion" do
396
-
397
- let(:selection) do
398
- query.and
399
- end
400
-
401
- it "does not add any criterion" do
402
- expect(selection.selector).to eq({})
403
- end
404
-
405
- it "returns the query" do
406
- expect(selection).to eq(query)
407
- end
408
-
409
- it "returns a cloned query" do
410
- expect(selection).to_not equal(query)
411
- end
412
- end
413
-
414
- context "when provided nil" do
415
-
416
- let(:selection) do
417
- query.and(nil)
418
- end
419
-
420
- it "does not add any criterion" do
421
- expect(selection.selector).to eq({})
422
- end
423
-
424
- it "returns the query" do
425
- expect(selection).to eq(query)
426
- end
427
-
428
- it "returns a cloned query" do
429
- expect(selection).to_not equal(query)
430
- end
431
- end
432
-
433
- context "when provided a single criterion" do
434
-
435
- let(:selection) do
436
- query.and(field: [ 1, 2 ])
437
- end
438
-
439
- it "adds the $and selector" do
440
- expect(selection.selector).to eq({
441
- "$and" => [{ "field" => [ 1, 2 ] }]
442
- })
443
- end
444
-
445
- it "returns a cloned query" do
446
- expect(selection).to_not equal(query)
447
- end
448
- end
449
-
450
- context "when provided a nested criterion" do
451
-
452
- let(:selection) do
453
- query.and(:test.elem_match => { :field.in => [ 1, 2 ] })
454
- end
455
-
456
- it "adds the $and selector" do
457
- expect(selection.selector).to eq({
458
- "$and" => [{ "test" => { "$elemMatch" => { "field" => { "$in" => [ 1, 2 ] }}}}]
459
- })
460
- end
461
-
462
- it "returns a cloned query" do
463
- expect(selection).to_not equal(query)
464
- end
465
- end
466
-
467
- context "when provided multiple criterion" do
468
-
469
- context "when the criterion is already included" do
470
-
471
- let(:selection) do
472
- query.and({ first: [ 1, 2 ] }).and({ first: [ 1, 2 ] })
473
- end
474
-
475
- it "does not duplicate the $and selector" do
476
- expect(selection.selector).to eq({
477
- "$and" => [
478
- { "first" => [ 1, 2 ] }
479
- ]
480
- })
481
- end
482
-
483
- it "returns a cloned query" do
484
- expect(selection).to_not equal(query)
485
- end
486
- end
487
-
488
- context "when the criterion are for different fields" do
489
-
490
- let(:selection) do
491
- query.and({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
492
- end
493
-
494
- it "adds the $and selector" do
495
- expect(selection.selector).to eq({
496
- "$and" => [
497
- { "first" => [ 1, 2 ] },
498
- { "second" => [ 3, 4 ] }
499
- ]
500
- })
501
- end
502
-
503
- it "returns a cloned query" do
504
- expect(selection).to_not equal(query)
505
- end
506
- end
507
-
508
- context "when the criterion are on the same field" do
509
-
510
- let(:selection) do
511
- query.and({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
512
- end
513
-
514
- it "appends both $and expressions" do
515
- expect(selection.selector).to eq({
516
- "$and" => [
517
- { "first" => [ 1, 2 ] },
518
- { "first" => [ 3, 4 ] }
519
- ]
520
- })
521
- end
522
-
523
- it "returns a cloned query" do
524
- expect(selection).to_not equal(query)
525
- end
526
- end
527
- end
528
-
529
- context "when chaining the criterion" do
530
-
531
- context "when the criterion are for different fields" do
532
-
533
- let(:selection) do
534
- query.and(first: [ 1, 2 ]).and(second: [ 3, 4 ])
535
- end
536
-
537
- it "adds the $and selectors" do
538
- expect(selection.selector).to eq({
539
- "$and" => [
540
- { "first" => [ 1, 2 ] },
541
- { "second" => [ 3, 4 ] }
542
- ]
543
- })
544
- end
545
-
546
- it "returns a cloned query" do
547
- expect(selection).to_not equal(query)
548
- end
549
- end
550
-
551
- context "when the criterion are on the same field" do
552
-
553
- let(:selection) do
554
- query.and(first: [ 1, 2 ]).and(first: [ 3, 4 ])
555
- end
556
-
557
- it "appends both $and expressions" do
558
- expect(selection.selector).to eq({
559
- "$and" => [
560
- { "first" => [ 1, 2 ] },
561
- { "first" => [ 3, 4 ] }
562
- ]
563
- })
564
- end
565
-
566
- it "returns a cloned query" do
567
- expect(selection).to_not equal(query)
568
- end
569
- end
570
- end
571
- end
572
-
573
- describe "#between" do
574
-
575
- context "when provided no criterion" do
576
-
577
- let(:selection) do
578
- query.between
579
- end
580
-
581
- it "does not add any criterion" do
582
- expect(selection.selector).to eq({})
583
- end
584
-
585
- it "returns the query" do
586
- expect(selection).to eq(query)
587
- end
588
-
589
- it "returns a cloned query" do
590
- expect(selection).to_not equal(query)
591
- end
592
- end
593
-
594
- context "when provided nil" do
595
-
596
- let(:selection) do
597
- query.between(nil)
598
- end
599
-
600
- it "does not add any criterion" do
601
- expect(selection.selector).to eq({})
602
- end
603
-
604
- it "returns the query" do
605
- expect(selection).to eq(query)
606
- end
607
-
608
- it "returns a cloned query" do
609
- expect(selection).to_not equal(query)
610
- end
611
- end
612
-
613
- context "when provided a single range" do
614
-
615
- let(:selection) do
616
- query.between(field: 1..10)
617
- end
618
-
619
- it "adds the $gte and $lte selectors" do
620
- expect(selection.selector).to eq({
621
- "field" => { "$gte" => 1, "$lte" => 10 }
622
- })
623
- end
624
-
625
- it "returns a cloned query" do
626
- expect(selection).to_not equal(query)
627
- end
628
- end
629
-
630
- context "when provided multiple ranges" do
631
-
632
- context "when the ranges are on different fields" do
633
-
634
- let(:selection) do
635
- query.between(field: 1..10, key: 5..7)
636
- end
637
-
638
- it "adds the $gte and $lte selectors" do
639
- expect(selection.selector).to eq({
640
- "field" => { "$gte" => 1, "$lte" => 10 },
641
- "key" => { "$gte" => 5, "$lte" => 7 }
642
- })
643
- end
644
-
645
- it "returns a cloned query" do
646
- expect(selection).to_not equal(query)
647
- end
648
- end
649
- end
650
- end
651
-
652
- describe "#elem_match" do
653
-
654
- context "when provided no criterion" do
655
-
656
- let(:selection) do
657
- query.elem_match
658
- end
659
-
660
- it "does not add any criterion" do
661
- expect(selection.selector).to eq({})
662
- end
663
-
664
- it "returns the query" do
665
- expect(selection).to eq(query)
666
- end
667
-
668
- it "returns a cloned query" do
669
- expect(selection).to_not equal(query)
670
- end
671
- end
672
-
673
- context "when provided nil" do
674
-
675
- let(:selection) do
676
- query.elem_match(nil)
677
- end
678
-
679
- it "does not add any criterion" do
680
- expect(selection.selector).to eq({})
681
- end
682
-
683
- it "returns the query" do
684
- expect(selection).to eq(query)
685
- end
686
-
687
- it "returns a cloned query" do
688
- expect(selection).to_not equal(query)
689
- end
690
- end
691
-
692
- context "when provided a criterion" do
693
-
694
- context "when there are no nested complex keys" do
695
-
696
- let(:selection) do
697
- query.elem_match(users: { name: "value" })
698
- end
699
-
700
- it "adds the $elemMatch expression" do
701
- expect(selection.selector).to eq({
702
- "users" => { "$elemMatch" => { name: "value" }}
703
- })
704
- end
705
-
706
- it "returns a cloned query" do
707
- expect(selection).to_not equal(query)
708
- end
709
- end
710
-
711
- context "when there are nested complex keys" do
712
-
713
- let(:time) do
714
- Time.now
715
- end
716
-
717
- let(:selection) do
718
- query.elem_match(users: { :time.gt => time })
719
- end
720
-
721
- it "adds the $elemMatch expression" do
722
- expect(selection.selector).to eq({
723
- "users" => { "$elemMatch" => { "time" => { "$gt" => time }}}
724
- })
725
- end
726
-
727
- it "returns a cloned query" do
728
- expect(selection).to_not equal(query)
729
- end
730
- end
731
- end
732
-
733
- context "when providing multiple criteria" do
734
-
735
- context "when the fields differ" do
736
-
737
- let(:selection) do
738
- query.elem_match(
739
- users: { name: "value" },
740
- comments: { text: "value" }
741
- )
742
- end
743
-
744
- it "adds the $elemMatch expression" do
745
- expect(selection.selector).to eq({
746
- "users" => { "$elemMatch" => { name: "value" }},
747
- "comments" => { "$elemMatch" => { text: "value" }}
748
- })
749
- end
750
-
751
- it "returns a cloned query" do
752
- expect(selection).to_not equal(query)
753
- end
754
- end
755
- end
756
-
757
- context "when chaining multiple criteria" do
758
-
759
- context "when the fields differ" do
760
-
761
- let(:selection) do
762
- query.
763
- elem_match(users: { name: "value" }).
764
- elem_match(comments: { text: "value" })
765
- end
766
-
767
- it "adds the $elemMatch expression" do
768
- expect(selection.selector).to eq({
769
- "users" => { "$elemMatch" => { name: "value" }},
770
- "comments" => { "$elemMatch" => { text: "value" }}
771
- })
772
- end
773
-
774
- it "returns a cloned query" do
775
- expect(selection).to_not equal(query)
776
- end
777
- end
778
-
779
- context "when the fields are the same" do
780
-
781
- let(:selection) do
782
- query.
783
- elem_match(users: { name: "value" }).
784
- elem_match(users: { state: "new" })
785
- end
786
-
787
- it "overrides the $elemMatch expression" do
788
- expect(selection.selector).to eq({
789
- "users" => { "$elemMatch" => { state: "new" }}
790
- })
791
- end
792
-
793
- it "returns a cloned query" do
794
- expect(selection).to_not equal(query)
795
- end
796
- end
797
- end
798
- end
799
-
800
- describe "#exists" do
801
-
802
- context "when provided no criterion" do
803
-
804
- let(:selection) do
805
- query.exists
806
- end
807
-
808
- it "does not add any criterion" do
809
- expect(selection.selector).to eq({})
810
- end
811
-
812
- it "returns the query" do
813
- expect(selection).to eq(query)
814
- end
815
-
816
- it "returns a cloned query" do
817
- expect(selection).to_not equal(query)
818
- end
819
- end
820
-
821
- context "when provided nil" do
822
-
823
- let(:selection) do
824
- query.exists(nil)
825
- end
826
-
827
- it "does not add any criterion" do
828
- expect(selection.selector).to eq({})
829
- end
830
-
831
- it "returns the query" do
832
- expect(selection).to eq(query)
833
- end
834
-
835
- it "returns a cloned query" do
836
- expect(selection).to_not equal(query)
837
- end
838
- end
839
-
840
- context "when provided a criterion" do
841
-
842
- context "when provided a boolean" do
843
-
844
- let(:selection) do
845
- query.exists(users: true)
846
- end
847
-
848
- it "adds the $exists expression" do
849
- expect(selection.selector).to eq({
850
- "users" => { "$exists" => true }
851
- })
852
- end
853
-
854
- it "returns a cloned query" do
855
- expect(selection).to_not equal(query)
856
- end
857
- end
858
-
859
- context "when provided a string" do
860
-
861
- let(:selection) do
862
- query.exists(users: "yes")
863
- end
864
-
865
- it "adds the $exists expression" do
866
- expect(selection.selector).to eq({
867
- "users" => { "$exists" => true }
868
- })
869
- end
870
-
871
- it "returns a cloned query" do
872
- expect(selection).to_not equal(query)
873
- end
874
- end
875
- end
876
-
877
- context "when providing multiple criteria" do
878
-
879
- context "when the fields differ" do
880
-
881
- context "when providing boolean values" do
882
-
883
- let(:selection) do
884
- query.exists(
885
- users: true,
886
- comments: true
887
- )
888
- end
889
-
890
- it "adds the $exists expression" do
891
- expect(selection.selector).to eq({
892
- "users" => { "$exists" => true },
893
- "comments" => { "$exists" => true }
894
- })
895
- end
896
-
897
- it "returns a cloned query" do
898
- expect(selection).to_not equal(query)
899
- end
900
- end
901
-
902
- context "when providing string values" do
903
-
904
- let(:selection) do
905
- query.exists(
906
- users: "y",
907
- comments: "true"
908
- )
909
- end
910
-
911
- it "adds the $exists expression" do
912
- expect(selection.selector).to eq({
913
- "users" => { "$exists" => true },
914
- "comments" => { "$exists" => true }
915
- })
916
- end
917
-
918
- it "returns a cloned query" do
919
- expect(selection).to_not equal(query)
920
- end
921
- end
922
- end
923
- end
924
-
925
- context "when chaining multiple criteria" do
926
-
927
- context "when the fields differ" do
928
-
929
- let(:selection) do
930
- query.
931
- exists(users: true).
932
- exists(comments: true)
933
- end
934
-
935
- it "adds the $exists expression" do
936
- expect(selection.selector).to eq({
937
- "users" => { "$exists" => true },
938
- "comments" => { "$exists" => true }
939
- })
940
- end
941
-
942
- it "returns a cloned query" do
943
- expect(selection).to_not equal(query)
944
- end
945
- end
946
- end
947
- end
948
-
949
- describe "#geo_spacial" do
950
-
951
- context "when provided no criterion" do
952
-
953
- let(:selection) do
954
- query.geo_spacial
955
- end
956
-
957
- it "does not add any criterion" do
958
- expect(selection.selector).to be_empty
959
- end
960
-
961
- it "returns the query" do
962
- expect(selection).to eq(query)
963
- end
964
-
965
- it_behaves_like "a cloning selection"
966
- end
967
-
968
- context "when provided nil" do
969
-
970
- let(:selection) do
971
- query.geo_spacial(nil)
972
- end
973
-
974
- it "does not add any criterion" do
975
- expect(selection.selector).to be_empty
976
- end
977
-
978
- it "returns the query" do
979
- expect(selection).to eq(query)
980
- end
981
-
982
- it_behaves_like "a cloning selection"
983
- end
984
-
985
- context "when provided a criterion" do
986
-
987
- context "when the geometry is a point intersection" do
988
-
989
- let(:selection) do
990
- query.geo_spacial(:location.intersects_point => [ 1, 10 ])
991
- end
992
-
993
- it "adds the $geoIntersects expression" do
994
- expect(selection.selector).to eq({
995
- "location" => {
996
- "$geoIntersects" => {
997
- "$geometry" => {
998
- "type" => "Point",
999
- "coordinates" => [ 1, 10 ]
1000
- }
1001
- }
1002
- }
1003
- })
1004
- end
1005
-
1006
- it_behaves_like "a cloning selection"
1007
- end
1008
-
1009
- context "when the geometry is a line intersection" do
1010
-
1011
- let(:selection) do
1012
- query.geo_spacial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
1013
- end
1014
-
1015
- it "adds the $geoIntersects expression" do
1016
- expect(selection.selector).to eq({
1017
- "location" => {
1018
- "$geoIntersects" => {
1019
- "$geometry" => {
1020
- "type" => "LineString",
1021
- "coordinates" => [[ 1, 10 ], [ 2, 10 ]]
1022
- }
1023
- }
1024
- }
1025
- })
1026
- end
1027
-
1028
- it_behaves_like "a cloning selection"
1029
- end
1030
-
1031
- context "when the geometry is a polygon intersection" do
1032
-
1033
- let(:selection) do
1034
- query.geo_spacial(
1035
- :location.intersects_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1036
- )
1037
- end
1038
-
1039
- it "adds the $geoIntersects expression" do
1040
- expect(selection.selector).to eq({
1041
- "location" => {
1042
- "$geoIntersects" => {
1043
- "$geometry" => {
1044
- "type" => "Polygon",
1045
- "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1046
- }
1047
- }
1048
- }
1049
- })
1050
- end
1051
-
1052
- it_behaves_like "a cloning selection"
1053
- end
1054
-
1055
- context "when the geometry is within a polygon" do
1056
-
1057
- let(:selection) do
1058
- query.geo_spacial(
1059
- :location.within_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1060
- )
1061
- end
1062
-
1063
- it "adds the $geoIntersects expression" do
1064
- expect(selection.selector).to eq({
1065
- "location" => {
1066
- "$geoWithin" => {
1067
- "$geometry" => {
1068
- "type" => "Polygon",
1069
- "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
1070
- }
1071
- }
1072
- }
1073
- })
1074
- end
1075
-
1076
- it_behaves_like "a cloning selection"
1077
- end
1078
- end
1079
- end
1080
-
1081
- describe "#gt" do
1082
-
1083
- context "when provided no criterion" do
1084
-
1085
- let(:selection) do
1086
- query.gt
1087
- end
1088
-
1089
- it "does not add any criterion" do
1090
- expect(selection.selector).to eq({})
1091
- end
1092
-
1093
- it "returns the query" do
1094
- expect(selection).to eq(query)
1095
- end
1096
-
1097
- it "returns a cloned query" do
1098
- expect(selection).to_not equal(query)
1099
- end
1100
- end
1101
-
1102
- context "when provided nil" do
1103
-
1104
- let(:selection) do
1105
- query.gt(nil)
1106
- end
1107
-
1108
- it "does not add any criterion" do
1109
- expect(selection.selector).to eq({})
1110
- end
1111
-
1112
- it "returns the query" do
1113
- expect(selection).to eq(query)
1114
- end
1115
-
1116
- it "returns a cloned query" do
1117
- expect(selection).to_not equal(query)
1118
- end
1119
- end
1120
-
1121
- context "when provided a single criterion" do
1122
-
1123
- let(:selection) do
1124
- query.gt(field: 10)
1125
- end
1126
-
1127
- it "adds the $gt selector" do
1128
- expect(selection.selector).to eq({
1129
- "field" => { "$gt" => 10 }
1130
- })
1131
- end
1132
-
1133
- it "returns a cloned query" do
1134
- expect(selection).to_not equal(query)
1135
- end
1136
- end
1137
-
1138
- context "when provided multiple criterion" do
1139
-
1140
- context "when the criterion are for different fields" do
1141
-
1142
- let(:selection) do
1143
- query.gt(first: 10, second: 15)
1144
- end
1145
-
1146
- it "adds the $gt selectors" do
1147
- expect(selection.selector).to eq({
1148
- "first" => { "$gt" => 10 },
1149
- "second" => { "$gt" => 15 }
1150
- })
1151
- end
1152
-
1153
- it "returns a cloned query" do
1154
- expect(selection).to_not equal(query)
1155
- end
1156
- end
1157
- end
1158
-
1159
- context "when chaining the criterion" do
1160
-
1161
- context "when the criterion are for different fields" do
1162
-
1163
- let(:selection) do
1164
- query.gt(first: 10).gt(second: 15)
1165
- end
1166
-
1167
- it "adds the $gt selectors" do
1168
- expect(selection.selector).to eq({
1169
- "first" => { "$gt" => 10 },
1170
- "second" => { "$gt" => 15 }
1171
- })
1172
- end
1173
-
1174
- it "returns a cloned query" do
1175
- expect(selection).to_not equal(query)
1176
- end
1177
- end
1178
-
1179
- context "when the criterion are on the same field" do
1180
-
1181
- let(:selection) do
1182
- query.gt(first: 10).gt(first: 15)
1183
- end
1184
-
1185
- it "overwrites the first $gt selector" do
1186
- expect(selection.selector).to eq({
1187
- "first" => { "$gt" => 15 }
1188
- })
1189
- end
1190
-
1191
- it "returns a cloned query" do
1192
- expect(selection).to_not equal(query)
1193
- end
1194
- end
1195
- end
1196
- end
1197
-
1198
- describe "#gte" do
1199
-
1200
- context "when provided no criterion" do
1201
-
1202
- let(:selection) do
1203
- query.gte
1204
- end
1205
-
1206
- it "does not add any criterion" do
1207
- expect(selection.selector).to eq({})
1208
- end
1209
-
1210
- it "returns the query" do
1211
- expect(selection).to eq(query)
1212
- end
1213
-
1214
- it "returns a cloned query" do
1215
- expect(selection).to_not equal(query)
1216
- end
1217
- end
1218
-
1219
- context "when provided nil" do
1220
-
1221
- let(:selection) do
1222
- query.gte(nil)
1223
- end
1224
-
1225
- it "does not add any criterion" do
1226
- expect(selection.selector).to eq({})
1227
- end
1228
-
1229
- it "returns the query" do
1230
- expect(selection).to eq(query)
1231
- end
1232
-
1233
- it "returns a cloned query" do
1234
- expect(selection).to_not equal(query)
1235
- end
1236
- end
1237
-
1238
- context "when provided a single criterion" do
1239
-
1240
- let(:selection) do
1241
- query.gte(field: 10)
1242
- end
1243
-
1244
- it "adds the $gte selector" do
1245
- expect(selection.selector).to eq({
1246
- "field" => { "$gte" => 10 }
1247
- })
1248
- end
1249
-
1250
- it "returns a cloned query" do
1251
- expect(selection).to_not equal(query)
1252
- end
1253
- end
1254
-
1255
- context "when provided multiple criterion" do
1256
-
1257
- context "when the criterion are for different fields" do
1258
-
1259
- let(:selection) do
1260
- query.gte(first: 10, second: 15)
1261
- end
1262
-
1263
- it "adds the $gte selectors" do
1264
- expect(selection.selector).to eq({
1265
- "first" => { "$gte" => 10 },
1266
- "second" => { "$gte" => 15 }
1267
- })
1268
- end
1269
-
1270
- it "returns a cloned query" do
1271
- expect(selection).to_not equal(query)
1272
- end
1273
- end
1274
- end
1275
-
1276
- context "when chaining the criterion" do
1277
-
1278
- context "when the criterion are for different fields" do
1279
-
1280
- let(:selection) do
1281
- query.gte(first: 10).gte(second: 15)
1282
- end
1283
-
1284
- it "adds the $gte selectors" do
1285
- expect(selection.selector).to eq({
1286
- "first" => { "$gte" => 10 },
1287
- "second" => { "$gte" => 15 }
1288
- })
1289
- end
1290
-
1291
- it "returns a cloned query" do
1292
- expect(selection).to_not equal(query)
1293
- end
1294
- end
1295
-
1296
- context "when the criterion are on the same field" do
1297
-
1298
- let(:selection) do
1299
- query.gte(first: 10).gte(first: 15)
1300
- end
1301
-
1302
- it "overwrites the first $gte selector" do
1303
- expect(selection.selector).to eq({
1304
- "first" => { "$gte" => 15 }
1305
- })
1306
- end
1307
-
1308
- it "returns a cloned query" do
1309
- expect(selection).to_not equal(query)
1310
- end
1311
- end
1312
- end
1313
- end
1314
-
1315
- describe "#in" do
1316
-
1317
- context "when provided no criterion" do
1318
-
1319
- let(:selection) do
1320
- query.in
1321
- end
1322
-
1323
- it "does not add any criterion" do
1324
- expect(selection.selector).to eq({})
1325
- end
1326
-
1327
- it "returns the query" do
1328
- expect(selection).to eq(query)
1329
- end
1330
-
1331
- it "returns a cloned query" do
1332
- expect(selection).to_not equal(query)
1333
- end
1334
- end
1335
-
1336
- context "when provided nil" do
1337
-
1338
- let(:selection) do
1339
- query.in(nil)
1340
- end
1341
-
1342
- it "does not add any criterion" do
1343
- expect(selection.selector).to eq({})
1344
- end
1345
-
1346
- it "returns the query" do
1347
- expect(selection).to eq(query)
1348
- end
1349
-
1350
- it "returns a cloned query" do
1351
- expect(selection).to_not equal(query)
1352
- end
1353
- end
1354
-
1355
- context "when provided a single criterion" do
1356
-
1357
- context "when providing an array" do
1358
-
1359
- let(:selection) do
1360
- query.in(field: [ 1, 2 ])
1361
- end
1362
-
1363
- it "adds the $in selector" do
1364
- expect(selection.selector).to eq({
1365
- "field" => { "$in" => [ 1, 2 ] }
1366
- })
1367
- end
1368
-
1369
- it "returns a cloned query" do
1370
- expect(selection).to_not equal(query)
1371
- end
1372
- end
1373
-
1374
- context "when providing a range" do
1375
-
1376
- let(:selection) do
1377
- query.in(field: 1..3)
1378
- end
1379
-
1380
- it "adds the $in selector with converted range" do
1381
- expect(selection.selector).to eq({
1382
- "field" => { "$in" => [ 1, 2, 3 ] }
1383
- })
1384
- end
1385
-
1386
- it "returns a cloned query" do
1387
- expect(selection).to_not equal(query)
1388
- end
1389
- end
1390
-
1391
- context "when providing a single value" do
1392
-
1393
- let(:selection) do
1394
- query.in(field: 1)
1395
- end
1396
-
1397
- it "adds the $in selector with wrapped value" do
1398
- expect(selection.selector).to eq({
1399
- "field" => { "$in" => [ 1 ] }
1400
- })
1401
- end
1402
-
1403
- it "returns a cloned query" do
1404
- expect(selection).to_not equal(query)
1405
- end
1406
- end
1407
- end
1408
-
1409
- context "when provided multiple criterion" do
1410
-
1411
- context "when the criterion are for different fields" do
1412
-
1413
- let(:selection) do
1414
- query.in(first: [ 1, 2 ], second: 3..4)
1415
- end
1416
-
1417
- it "adds the $in selectors" do
1418
- expect(selection.selector).to eq({
1419
- "first" => { "$in" => [ 1, 2 ] },
1420
- "second" => { "$in" => [ 3, 4 ] }
1421
- })
1422
- end
1423
-
1424
- it "returns a cloned query" do
1425
- expect(selection).to_not equal(query)
1426
- end
1427
- end
1428
- end
1429
-
1430
- context "when chaining the criterion" do
1431
-
1432
- context "when the criterion are for different fields" do
1433
-
1434
- let(:selection) do
1435
- query.in(first: [ 1, 2 ]).in(second: [ 3, 4 ])
1436
- end
1437
-
1438
- it "adds the $in selectors" do
1439
- expect(selection.selector).to eq({
1440
- "first" => { "$in" => [ 1, 2 ] },
1441
- "second" => { "$in" => [ 3, 4 ] }
1442
- })
1443
- end
1444
-
1445
- it "returns a cloned query" do
1446
- expect(selection).to_not equal(query)
1447
- end
1448
- end
1449
-
1450
- context "when the criterion are on the same field" do
1451
-
1452
- context "when the strategy is the default (intersection)" do
1453
-
1454
- let(:selection) do
1455
- query.in(first: [ 1, 2 ].freeze).in(first: [ 2, 3 ])
1456
- end
1457
-
1458
- it "intersects the $in selectors" do
1459
- expect(selection.selector).to eq({
1460
- "first" => { "$in" => [ 2 ] }
1461
- })
1462
- end
1463
-
1464
- it "returns a cloned query" do
1465
- expect(selection).to_not equal(query)
1466
- end
1467
- end
1468
-
1469
- context 'when the field is aliased' do
1470
-
1471
- before(:all) do
1472
- class TestModel
1473
- include Mongoid::Document
1474
- end
1475
- end
1476
-
1477
- after(:all) do
1478
- Object.send(:remove_const, :TestModel)
1479
- end
1480
-
1481
- let(:bson_object_id) do
1482
- BSON::ObjectId.new
1483
- end
1484
-
1485
- let(:selection) do
1486
- TestModel.in(id: [bson_object_id.to_s]).in(id: [bson_object_id.to_s])
1487
- end
1488
-
1489
- it "intersects the $in selectors" do
1490
- expect(selection.selector).to eq("_id" => { "$in" => [ bson_object_id ] })
1491
- end
1492
-
1493
- it "returns a cloned query" do
1494
- expect(selection).to_not equal(query)
1495
- end
1496
- end
1497
-
1498
- context "when the stretegy is intersect" do
1499
-
1500
- let(:selection) do
1501
- query.in(first: [ 1, 2 ]).intersect.in(first: [ 2, 3 ])
1502
- end
1503
-
1504
- it "intersects the $in selectors" do
1505
- expect(selection.selector).to eq({
1506
- "first" => { "$in" => [ 2 ] }
1507
- })
1508
- end
1509
-
1510
- it "returns a cloned query" do
1511
- expect(selection).to_not equal(query)
1512
- end
1513
- end
1514
-
1515
- context "when the strategy is override" do
1516
-
1517
- let(:selection) do
1518
- query.in(first: [ 1, 2 ]).override.in(first: [ 3, 4 ])
1519
- end
1520
-
1521
- it "overwrites the first $in selector" do
1522
- expect(selection.selector).to eq({
1523
- "first" => { "$in" => [ 3, 4 ] }
1524
- })
1525
- end
1526
-
1527
- it "returns a cloned query" do
1528
- expect(selection).to_not equal(query)
1529
- end
1530
- end
1531
-
1532
- context "when the strategy is union" do
1533
-
1534
- let(:selection) do
1535
- query.in(first: [ 1, 2 ]).union.in(first: [ 3, 4 ])
1536
- end
1537
-
1538
- it "unions the $in selectors" do
1539
- expect(selection.selector).to eq({
1540
- "first" => { "$in" => [ 1, 2, 3, 4 ] }
1541
- })
1542
- end
1543
-
1544
- it "returns a cloned query" do
1545
- expect(selection).to_not equal(query)
1546
- end
1547
- end
1548
- end
1549
- end
1550
- end
1551
-
1552
- describe "#lt" do
1553
-
1554
- context "when provided no criterion" do
1555
-
1556
- let(:selection) do
1557
- query.lt
1558
- end
1559
-
1560
- it "does not add any criterion" do
1561
- expect(selection.selector).to eq({})
1562
- end
1563
-
1564
- it "returns the query" do
1565
- expect(selection).to eq(query)
1566
- end
1567
-
1568
- it "returns a cloned query" do
1569
- expect(selection).to_not equal(query)
1570
- end
1571
- end
1572
-
1573
- context "when provided nil" do
1574
-
1575
- let(:selection) do
1576
- query.lt(nil)
1577
- end
1578
-
1579
- it "does not add any criterion" do
1580
- expect(selection.selector).to eq({})
1581
- end
1582
-
1583
- it "returns the query" do
1584
- expect(selection).to eq(query)
1585
- end
1586
-
1587
- it "returns a cloned query" do
1588
- expect(selection).to_not equal(query)
1589
- end
1590
- end
1591
-
1592
- context "when provided a single criterion" do
1593
-
1594
- let(:selection) do
1595
- query.lt(field: 10)
1596
- end
1597
-
1598
- it "adds the $lt selector" do
1599
- expect(selection.selector).to eq({
1600
- "field" => { "$lt" => 10 }
1601
- })
1602
- end
1603
-
1604
- it "returns a cloned query" do
1605
- expect(selection).to_not equal(query)
1606
- end
1607
- end
1608
-
1609
- context "when provided multiple criterion" do
1610
-
1611
- context "when the criterion are for different fields" do
1612
-
1613
- let(:selection) do
1614
- query.lt(first: 10, second: 15)
1615
- end
1616
-
1617
- it "adds the $lt selectors" do
1618
- expect(selection.selector).to eq({
1619
- "first" => { "$lt" => 10 },
1620
- "second" => { "$lt" => 15 }
1621
- })
1622
- end
1623
-
1624
- it "returns a cloned query" do
1625
- expect(selection).to_not equal(query)
1626
- end
1627
- end
1628
- end
1629
-
1630
- context "when chaining the criterion" do
1631
-
1632
- context "when the criterion are for different fields" do
1633
-
1634
- let(:selection) do
1635
- query.lt(first: 10).lt(second: 15)
1636
- end
1637
-
1638
- it "adds the $lt selectors" do
1639
- expect(selection.selector).to eq({
1640
- "first" => { "$lt" => 10 },
1641
- "second" => { "$lt" => 15 }
1642
- })
1643
- end
1644
-
1645
- it "returns a cloned query" do
1646
- expect(selection).to_not equal(query)
1647
- end
1648
- end
1649
-
1650
- context "when the criterion are on the same field" do
1651
-
1652
- let(:selection) do
1653
- query.lt(first: 10).lt(first: 15)
1654
- end
1655
-
1656
- it "overwrites the first $lt selector" do
1657
- expect(selection.selector).to eq({
1658
- "first" => { "$lt" => 15 }
1659
- })
1660
- end
1661
-
1662
- it "returns a cloned query" do
1663
- expect(selection).to_not equal(query)
1664
- end
1665
- end
1666
- end
1667
- end
1668
-
1669
- describe "#lte" do
1670
-
1671
- context "when provided no criterion" do
1672
-
1673
- let(:selection) do
1674
- query.lte
1675
- end
1676
-
1677
- it "does not add any criterion" do
1678
- expect(selection.selector).to eq({})
1679
- end
1680
-
1681
- it "returns the query" do
1682
- expect(selection).to eq(query)
1683
- end
1684
-
1685
- it "returns a cloned query" do
1686
- expect(selection).to_not equal(query)
1687
- end
1688
- end
1689
-
1690
- context "when provided nil" do
1691
-
1692
- let(:selection) do
1693
- query.lte(nil)
1694
- end
1695
-
1696
- it "does not add any criterion" do
1697
- expect(selection.selector).to eq({})
1698
- end
1699
-
1700
- it "returns the query" do
1701
- expect(selection).to eq(query)
1702
- end
1703
-
1704
- it "returns a cloned query" do
1705
- expect(selection).to_not equal(query)
1706
- end
1707
- end
1708
-
1709
- context "when provided a single criterion" do
1710
-
1711
- let(:selection) do
1712
- query.lte(field: 10)
1713
- end
1714
-
1715
- it "adds the $lte selector" do
1716
- expect(selection.selector).to eq({
1717
- "field" => { "$lte" => 10 }
1718
- })
1719
- end
1720
-
1721
- it "returns a cloned query" do
1722
- expect(selection).to_not equal(query)
1723
- end
1724
- end
1725
-
1726
- context "when provided multiple criterion" do
1727
-
1728
- context "when the criterion are for different fields" do
1729
-
1730
- let(:selection) do
1731
- query.lte(first: 10, second: 15)
1732
- end
1733
-
1734
- it "adds the $lte selectors" do
1735
- expect(selection.selector).to eq({
1736
- "first" => { "$lte" => 10 },
1737
- "second" => { "$lte" => 15 }
1738
- })
1739
- end
1740
-
1741
- it "returns a cloned query" do
1742
- expect(selection).to_not equal(query)
1743
- end
1744
- end
1745
- end
1746
-
1747
- context "when chaining the criterion" do
1748
-
1749
- context "when the criterion are for different fields" do
1750
-
1751
- let(:selection) do
1752
- query.lte(first: 10).lte(second: 15)
1753
- end
1754
-
1755
- it "adds the $lte selectors" do
1756
- expect(selection.selector).to eq({
1757
- "first" => { "$lte" => 10 },
1758
- "second" => { "$lte" => 15 }
1759
- })
1760
- end
1761
-
1762
- it "returns a cloned query" do
1763
- expect(selection).to_not equal(query)
1764
- end
1765
- end
1766
-
1767
- context "when the criterion are on the same field" do
1768
-
1769
- let(:selection) do
1770
- query.lte(first: 10).lte(first: 15)
1771
- end
1772
-
1773
- it "overwrites the first $lte selector" do
1774
- expect(selection.selector).to eq({
1775
- "first" => { "$lte" => 15 }
1776
- })
1777
- end
1778
-
1779
- it "returns a cloned query" do
1780
- expect(selection).to_not equal(query)
1781
- end
1782
- end
1783
- end
1784
- end
1785
-
1786
- describe "#max_distance" do
1787
-
1788
- context "when provided no criterion" do
1789
-
1790
- let(:selection) do
1791
- query.max_distance
1792
- end
1793
-
1794
- it "does not add any criterion" do
1795
- expect(selection.selector).to eq({})
1796
- end
1797
-
1798
- it "returns the query" do
1799
- expect(selection).to eq(query)
1800
- end
1801
-
1802
- it "returns a cloned query" do
1803
- expect(selection).to_not equal(query)
1804
- end
1805
- end
1806
-
1807
- context "when provided nil" do
1808
-
1809
- let(:selection) do
1810
- query.max_distance(nil)
1811
- end
1812
-
1813
- it "does not add any criterion" do
1814
- expect(selection.selector).to eq({})
1815
- end
1816
-
1817
- it "returns the query" do
1818
- expect(selection).to eq(query)
1819
- end
1820
-
1821
- it "returns a cloned query" do
1822
- expect(selection).to_not equal(query)
1823
- end
1824
- end
1825
-
1826
- context "when provided a criterion" do
1827
-
1828
- context "when a $near criterion exists on the same field" do
1829
-
1830
- let(:selection) do
1831
- query.near(location: [ 1, 1 ]).max_distance(location: 50)
1832
- end
1833
-
1834
- it "adds the $maxDistance expression" do
1835
- expect(selection.selector).to eq({
1836
- "location" => { "$near" => [ 1, 1 ], "$maxDistance" => 50 }
1837
- })
1838
- end
1839
-
1840
- it "returns a cloned query" do
1841
- expect(selection).to_not equal(query)
1842
- end
1843
- end
1844
- end
1845
- end
1846
-
1847
- describe "#mod" do
1848
-
1849
- context "when provided no criterion" do
1850
-
1851
- let(:selection) do
1852
- query.mod
1853
- end
1854
-
1855
- it "does not add any criterion" do
1856
- expect(selection.selector).to eq({})
1857
- end
1858
-
1859
- it "returns the query" do
1860
- expect(selection).to eq(query)
1861
- end
1862
-
1863
- it "returns a cloned query" do
1864
- expect(selection).to_not equal(query)
1865
- end
1866
- end
1867
-
1868
- context "when provided nil" do
1869
-
1870
- let(:selection) do
1871
- query.mod(nil)
1872
- end
1873
-
1874
- it "does not add any criterion" do
1875
- expect(selection.selector).to eq({})
1876
- end
1877
-
1878
- it "returns the query" do
1879
- expect(selection).to eq(query)
1880
- end
1881
-
1882
- it "returns a cloned query" do
1883
- expect(selection).to_not equal(query)
1884
- end
1885
- end
1886
-
1887
- context "when provided a criterion" do
1888
-
1889
- let(:selection) do
1890
- query.mod(value: [ 10, 1 ])
1891
- end
1892
-
1893
- it "adds the $mod expression" do
1894
- expect(selection.selector).to eq({
1895
- "value" => { "$mod" => [ 10, 1 ] }
1896
- })
1897
- end
1898
-
1899
- it "returns a cloned query" do
1900
- expect(selection).to_not equal(query)
1901
- end
1902
- end
1903
-
1904
- context "when providing multiple criteria" do
1905
-
1906
- context "when the fields differ" do
1907
-
1908
- let(:selection) do
1909
- query.mod(
1910
- value: [ 10, 1 ],
1911
- comments: [ 10, 1 ]
1912
- )
1913
- end
1914
-
1915
- it "adds the $mod expression" do
1916
- expect(selection.selector).to eq({
1917
- "value" => { "$mod" => [ 10, 1 ] },
1918
- "comments" => { "$mod" => [ 10, 1 ] }
1919
- })
1920
- end
1921
-
1922
- it "returns a cloned query" do
1923
- expect(selection).to_not equal(query)
1924
- end
1925
- end
1926
- end
1927
-
1928
- context "when chaining multiple criteria" do
1929
-
1930
- context "when the fields differ" do
1931
-
1932
- let(:selection) do
1933
- query.
1934
- mod(value: [ 10, 1 ]).
1935
- mod(result: [ 10, 1 ])
1936
- end
1937
-
1938
- it "adds the $mod expression" do
1939
- expect(selection.selector).to eq({
1940
- "value" => { "$mod" => [ 10, 1 ] },
1941
- "result" => { "$mod" => [ 10, 1 ] }
1942
- })
1943
- end
1944
-
1945
- it "returns a cloned query" do
1946
- expect(selection).to_not equal(query)
1947
- end
1948
- end
1949
- end
1950
- end
1951
-
1952
- describe "#ne" do
1953
-
1954
- context "when provided no criterion" do
1955
-
1956
- let(:selection) do
1957
- query.ne
1958
- end
1959
-
1960
- it "does not add any criterion" do
1961
- expect(selection.selector).to eq({})
1962
- end
1963
-
1964
- it "returns the query" do
1965
- expect(selection).to eq(query)
1966
- end
1967
-
1968
- it "returns a cloned query" do
1969
- expect(selection).to_not equal(query)
1970
- end
1971
- end
1972
-
1973
- context "when provided nil" do
1974
-
1975
- let(:selection) do
1976
- query.ne(nil)
1977
- end
1978
-
1979
- it "does not add any criterion" do
1980
- expect(selection.selector).to eq({})
1981
- end
1982
-
1983
- it "returns the query" do
1984
- expect(selection).to eq(query)
1985
- end
1986
-
1987
- it "returns a cloned query" do
1988
- expect(selection).to_not equal(query)
1989
- end
1990
- end
1991
-
1992
- context "when provided a criterion" do
1993
-
1994
- let(:selection) do
1995
- query.ne(value: 10)
1996
- end
1997
-
1998
- it "adds the $ne expression" do
1999
- expect(selection.selector).to eq({
2000
- "value" => { "$ne" => 10 }
2001
- })
2002
- end
2003
-
2004
- it "returns a cloned query" do
2005
- expect(selection).to_not equal(query)
2006
- end
2007
- end
2008
-
2009
- context "when providing multiple criteria" do
2010
-
2011
- context "when the fields differ" do
2012
-
2013
- let(:selection) do
2014
- query.ne(
2015
- value: 10,
2016
- comments: 10
2017
- )
2018
- end
2019
-
2020
- it "adds the $ne expression" do
2021
- expect(selection.selector).to eq({
2022
- "value" => { "$ne" => 10 },
2023
- "comments" => { "$ne" => 10 }
2024
- })
2025
- end
2026
-
2027
- it "returns a cloned query" do
2028
- expect(selection).to_not equal(query)
2029
- end
2030
- end
2031
- end
2032
-
2033
- context "when chaining multiple criteria" do
2034
-
2035
- context "when the fields differ" do
2036
-
2037
- let(:selection) do
2038
- query.
2039
- ne(value: 10).
2040
- ne(result: 10)
2041
- end
2042
-
2043
- it "adds the $ne expression" do
2044
- expect(selection.selector).to eq({
2045
- "value" => { "$ne" => 10 },
2046
- "result" => { "$ne" => 10 }
2047
- })
2048
- end
2049
-
2050
- it "returns a cloned query" do
2051
- expect(selection).to_not equal(query)
2052
- end
2053
- end
2054
- end
2055
- end
2056
-
2057
- describe "#near" do
2058
-
2059
- context "when provided no criterion" do
2060
-
2061
- let(:selection) do
2062
- query.near
2063
- end
2064
-
2065
- it "does not add any criterion" do
2066
- expect(selection.selector).to eq({})
2067
- end
2068
-
2069
- it "returns the query" do
2070
- expect(selection).to eq(query)
2071
- end
2072
-
2073
- it "returns a cloned query" do
2074
- expect(selection).to_not equal(query)
2075
- end
2076
- end
2077
-
2078
- context "when provided nil" do
2079
-
2080
- let(:selection) do
2081
- query.near(nil)
2082
- end
2083
-
2084
- it "does not add any criterion" do
2085
- expect(selection.selector).to eq({})
2086
- end
2087
-
2088
- it "returns the query" do
2089
- expect(selection).to eq(query)
2090
- end
2091
-
2092
- it "returns a cloned query" do
2093
- expect(selection).to_not equal(query)
2094
- end
2095
- end
2096
-
2097
- context "when provided a criterion" do
2098
-
2099
- let(:selection) do
2100
- query.near(location: [ 20, 21 ])
2101
- end
2102
-
2103
- it "adds the $near expression" do
2104
- expect(selection.selector).to eq({
2105
- "location" => { "$near" => [ 20, 21 ] }
2106
- })
2107
- end
2108
-
2109
- it "returns a cloned query" do
2110
- expect(selection).to_not equal(query)
2111
- end
2112
- end
2113
-
2114
- context "when providing multiple criteria" do
2115
-
2116
- context "when the fields differ" do
2117
-
2118
- let(:selection) do
2119
- query.near(
2120
- location: [ 20, 21 ],
2121
- comments: [ 20, 21 ]
2122
- )
2123
- end
2124
-
2125
- it "adds the $near expression" do
2126
- expect(selection.selector).to eq({
2127
- "location" => { "$near" => [ 20, 21 ] },
2128
- "comments" => { "$near" => [ 20, 21 ] }
2129
- })
2130
- end
2131
-
2132
- it "returns a cloned query" do
2133
- expect(selection).to_not equal(query)
2134
- end
2135
- end
2136
- end
2137
-
2138
- context "when chaining multiple criteria" do
2139
-
2140
- context "when the fields differ" do
2141
-
2142
- let(:selection) do
2143
- query.
2144
- near(location: [ 20, 21 ]).
2145
- near(comments: [ 20, 21 ])
2146
- end
2147
-
2148
- it "adds the $near expression" do
2149
- expect(selection.selector).to eq({
2150
- "location" => { "$near" => [ 20, 21 ] },
2151
- "comments" => { "$near" => [ 20, 21 ] }
2152
- })
2153
- end
2154
-
2155
- it "returns a cloned query" do
2156
- expect(selection).to_not equal(query)
2157
- end
2158
- end
2159
- end
2160
- end
2161
-
2162
- describe "#near_sphere" do
2163
-
2164
- context "when provided no criterion" do
2165
-
2166
- let(:selection) do
2167
- query.near_sphere
2168
- end
2169
-
2170
- it "does not add any criterion" do
2171
- expect(selection.selector).to eq({})
2172
- end
2173
-
2174
- it "returns the query" do
2175
- expect(selection).to eq(query)
2176
- end
2177
-
2178
- it "returns a cloned query" do
2179
- expect(selection).to_not equal(query)
2180
- end
2181
- end
2182
-
2183
- context "when provided nil" do
2184
-
2185
- let(:selection) do
2186
- query.near_sphere(nil)
2187
- end
2188
-
2189
- it "does not add any criterion" do
2190
- expect(selection.selector).to eq({})
2191
- end
2192
-
2193
- it "returns the query" do
2194
- expect(selection).to eq(query)
2195
- end
2196
-
2197
- it "returns a cloned query" do
2198
- expect(selection).to_not equal(query)
2199
- end
2200
- end
2201
-
2202
- context "when provided a criterion" do
2203
-
2204
- let(:selection) do
2205
- query.near_sphere(location: [ 20, 21 ])
2206
- end
2207
-
2208
- it "adds the $nearSphere expression" do
2209
- expect(selection.selector).to eq({
2210
- "location" => { "$nearSphere" => [ 20, 21 ] }
2211
- })
2212
- end
2213
-
2214
- it "returns a cloned query" do
2215
- expect(selection).to_not equal(query)
2216
- end
2217
- end
2218
-
2219
- context "when providing multiple criteria" do
2220
-
2221
- context "when the fields differ" do
2222
-
2223
- let(:selection) do
2224
- query.near_sphere(
2225
- location: [ 20, 21 ],
2226
- comments: [ 20, 21 ]
2227
- )
2228
- end
2229
-
2230
- it "adds the $nearSphere expression" do
2231
- expect(selection.selector).to eq({
2232
- "location" => { "$nearSphere" => [ 20, 21 ] },
2233
- "comments" => { "$nearSphere" => [ 20, 21 ] }
2234
- })
495
+ it "adds the $elemMatch expression" do
496
+ expect(selection.selector).to eq({
497
+ "users" => { "$elemMatch" => { name: "value" }}
498
+ })
499
+ end
2235
500
  end
2236
501
 
2237
502
  it "returns a cloned query" do
2238
503
  expect(selection).to_not equal(query)
2239
504
  end
2240
505
  end
2241
- end
2242
506
 
2243
- context "when chaining multiple criteria" do
507
+ context "when there are nested complex keys" do
2244
508
 
2245
- context "when the fields differ" do
509
+ let(:time) do
510
+ Time.now
511
+ end
2246
512
 
2247
513
  let(:selection) do
2248
- query.
2249
- near_sphere(location: [ 20, 21 ]).
2250
- near_sphere(comments: [ 20, 21 ])
514
+ query.elem_match(users: { :time.gt => time })
2251
515
  end
2252
516
 
2253
- it "adds the $nearSphere expression" do
517
+ it "adds the $elemMatch expression" do
2254
518
  expect(selection.selector).to eq({
2255
- "location" => { "$nearSphere" => [ 20, 21 ] },
2256
- "comments" => { "$nearSphere" => [ 20, 21 ] }
519
+ "users" => { "$elemMatch" => { "time" => { "$gt" => time }}}
2257
520
  })
2258
521
  end
2259
522
 
@@ -2262,77 +525,76 @@ describe Mongoid::Criteria::Queryable::Selectable do
2262
525
  end
2263
526
  end
2264
527
  end
2265
- end
2266
-
2267
- describe "#nin" do
2268
-
2269
- context "when provided no criterion" do
2270
-
2271
- let(:selection) do
2272
- query.nin
2273
- end
2274
528
 
2275
- it "does not add any criterion" do
2276
- expect(selection.selector).to eq({})
2277
- end
529
+ context "when providing multiple criteria" do
2278
530
 
2279
- it "returns the query" do
2280
- expect(selection).to eq(query)
2281
- end
531
+ context "when the fields differ" do
2282
532
 
2283
- it "returns a cloned query" do
2284
- expect(selection).to_not equal(query)
2285
- end
2286
- end
533
+ let(:selection) do
534
+ query.elem_match(
535
+ users: { name: "value" },
536
+ comments: { text: "value" }
537
+ )
538
+ end
2287
539
 
2288
- context "when provided nil" do
540
+ context "when overwrite_chained_operators is false" do
541
+ config_override :overwrite_chained_operators, false
2289
542
 
2290
- let(:selection) do
2291
- query.nin(nil)
2292
- end
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
2293
550
 
2294
- it "does not add any criterion" do
2295
- expect(selection.selector).to eq({})
2296
- end
551
+ context "when overwrite_chained_operators is true" do
552
+ config_override :overwrite_chained_operators, true
2297
553
 
2298
- it "returns the query" do
2299
- expect(selection).to eq(query)
2300
- end
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
560
+ end
2301
561
 
2302
- it "returns a cloned query" do
2303
- expect(selection).to_not equal(query)
562
+ it "returns a cloned query" do
563
+ expect(selection).to_not equal(query)
564
+ end
2304
565
  end
2305
566
  end
2306
567
 
2307
- context "when provided a single criterion" do
568
+ context "when chaining multiple criteria" do
2308
569
 
2309
- context "when providing an array" do
570
+ context "when the fields differ" do
2310
571
 
2311
572
  let(:selection) do
2312
- query.nin(field: [ 1, 2 ])
573
+ query.
574
+ elem_match(users: { name: "value" }).
575
+ elem_match(comments: { text: "value" })
2313
576
  end
2314
577
 
2315
- it "adds the $nin selector" do
2316
- expect(selection.selector).to eq({
2317
- "field" => { "$nin" => [ 1, 2 ] }
2318
- })
2319
- end
578
+ context "when overwrite_chained_operators is false" do
579
+ config_override :overwrite_chained_operators, false
2320
580
 
2321
- it "returns a cloned query" do
2322
- 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
2323
587
  end
2324
- end
2325
588
 
2326
- context "when providing a range" do
2327
-
2328
- let(:selection) do
2329
- query.nin(field: 1..3)
2330
- end
589
+ context "when overwrite_chained_operators is true" do
590
+ config_override :overwrite_chained_operators, true
2331
591
 
2332
- it "adds the $nin selector with converted range" do
2333
- expect(selection.selector).to eq({
2334
- "field" => { "$nin" => [ 1, 2, 3 ] }
2335
- })
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
2336
598
  end
2337
599
 
2338
600
  it "returns a cloned query" do
@@ -2340,65 +602,60 @@ describe Mongoid::Criteria::Queryable::Selectable do
2340
602
  end
2341
603
  end
2342
604
 
2343
- context "when providing a single value" do
605
+ context "when the fields are the same" do
2344
606
 
2345
607
  let(:selection) do
2346
- query.nin(field: 1)
608
+ query.
609
+ elem_match(users: { name: "value" }).
610
+ elem_match(users: { state: "new" })
2347
611
  end
2348
612
 
2349
- it "adds the $nin selector with wrapped value" do
2350
- expect(selection.selector).to eq({
2351
- "field" => { "$nin" => [ 1 ] }
2352
- })
2353
- end
613
+ context "when overwrite_chained_operators is false" do
614
+ config_override :overwrite_chained_operators, false
2354
615
 
2355
- it "returns a cloned query" do
2356
- expect(selection).to_not equal(query)
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
2357
622
  end
2358
- end
2359
- end
2360
623
 
2361
- context "when unioning on the same field" do
624
+ context "when overwrite_chained_operators is true" do
625
+ config_override :overwrite_chained_operators, true
2362
626
 
2363
- context "when the field is not aliased" do
2364
-
2365
- let(:selection) do
2366
- query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
627
+ it "overrides the $elemMatch expression" do
628
+ expect(selection.selector).to eq({
629
+ "users" => { "$elemMatch" => { state: "new" }}
630
+ })
631
+ end
2367
632
  end
2368
633
 
2369
- it "unions the selection on the field" do
2370
- expect(selection.selector).to eq(
2371
- { "first" => { "$nin" => [ 1, 2, 3, 4 ]}}
2372
- )
634
+ it "returns a cloned query" do
635
+ expect(selection).to_not equal(query)
2373
636
  end
2374
637
  end
638
+ end
639
+ end
2375
640
 
2376
- context "when the field is aliased" do
641
+ describe "#exists" do
2377
642
 
2378
- let(:selection) do
2379
- query.nin(id: [ 1, 2 ]).union.nin(id: [ 3, 4 ])
2380
- end
643
+ let(:query_method) { :exists }
2381
644
 
2382
- it "unions the selection on the field" do
2383
- expect(selection.selector).to eq(
2384
- { "_id" => { "$nin" => [ 1, 2, 3, 4 ]}}
2385
- )
2386
- end
2387
- end
2388
- end
645
+ it_behaves_like 'requires an argument'
646
+ it_behaves_like 'requires a non-nil argument'
2389
647
 
2390
- context "when provided multiple criterion" do
648
+ context "when provided a criterion" do
2391
649
 
2392
- context "when the criterion are for different fields" do
650
+ context "when provided a boolean" do
2393
651
 
2394
652
  let(:selection) do
2395
- query.nin(first: [ 1, 2 ], second: [ 3, 4 ])
653
+ query.exists(users: true)
2396
654
  end
2397
655
 
2398
- it "adds the $nin selectors" do
656
+ it "adds the $exists expression" do
2399
657
  expect(selection.selector).to eq({
2400
- "first" => { "$nin" => [ 1, 2 ] },
2401
- "second" => { "$nin" => [ 3, 4 ] }
658
+ "users" => { "$exists" => true }
2402
659
  })
2403
660
  end
2404
661
 
@@ -2406,20 +663,16 @@ describe Mongoid::Criteria::Queryable::Selectable do
2406
663
  expect(selection).to_not equal(query)
2407
664
  end
2408
665
  end
2409
- end
2410
-
2411
- context "when chaninning the criterion" do
2412
666
 
2413
- context "when the criterion are for different fields" do
667
+ context "when provided a string" do
2414
668
 
2415
669
  let(:selection) do
2416
- query.nin(first: [ 1, 2 ]).nin(second: [ 3, 4 ])
670
+ query.exists(users: "yes")
2417
671
  end
2418
672
 
2419
- it "adds the $nin selectors" do
673
+ it "adds the $exists expression" do
2420
674
  expect(selection.selector).to eq({
2421
- "first" => { "$nin" => [ 1, 2 ] },
2422
- "second" => { "$nin" => [ 3, 4 ] }
675
+ "users" => { "$exists" => true }
2423
676
  })
2424
677
  end
2425
678
 
@@ -2427,52 +680,25 @@ describe Mongoid::Criteria::Queryable::Selectable do
2427
680
  expect(selection).to_not equal(query)
2428
681
  end
2429
682
  end
683
+ end
2430
684
 
2431
- context "when the criterion are on the same field" do
2432
-
2433
- context "when the stretegy is the default (intersection)" do
2434
-
2435
- let(:selection) do
2436
- query.nin(first: [ 1, 2 ]).nin(first: [ 2, 3 ])
2437
- end
2438
-
2439
- it "intersects the $nin selectors" do
2440
- expect(selection.selector).to eq({
2441
- "first" => { "$nin" => [ 2 ] }
2442
- })
2443
- end
2444
-
2445
- it "returns a cloned query" do
2446
- expect(selection).to_not equal(query)
2447
- end
2448
- end
2449
-
2450
- context "when the stretegy is intersect" do
2451
-
2452
- let(:selection) do
2453
- query.nin(first: [ 1, 2 ]).intersect.nin(first: [ 2, 3 ])
2454
- end
2455
-
2456
- it "intersects the $nin selectors" do
2457
- expect(selection.selector).to eq({
2458
- "first" => { "$nin" => [ 2 ] }
2459
- })
2460
- end
685
+ context "when providing multiple criteria" do
2461
686
 
2462
- it "returns a cloned query" do
2463
- expect(selection).to_not equal(query)
2464
- end
2465
- end
687
+ context "when the fields differ" do
2466
688
 
2467
- context "when the stretegy is override" do
689
+ context "when providing boolean values" do
2468
690
 
2469
691
  let(:selection) do
2470
- query.nin(first: [ 1, 2 ]).override.nin(first: [ 3, 4 ])
692
+ query.exists(
693
+ users: true,
694
+ comments: true
695
+ )
2471
696
  end
2472
697
 
2473
- it "overwrites the first $nin selector" do
698
+ it "adds the $exists expression" do
2474
699
  expect(selection.selector).to eq({
2475
- "first" => { "$nin" => [ 3, 4 ] }
700
+ "users" => { "$exists" => true },
701
+ "comments" => { "$exists" => true }
2476
702
  })
2477
703
  end
2478
704
 
@@ -2481,15 +707,19 @@ describe Mongoid::Criteria::Queryable::Selectable do
2481
707
  end
2482
708
  end
2483
709
 
2484
- context "when the stretegy is union" do
710
+ context "when providing string values" do
2485
711
 
2486
712
  let(:selection) do
2487
- query.nin(first: [ 1, 2 ]).union.nin(first: [ 3, 4 ])
713
+ query.exists(
714
+ users: "y",
715
+ comments: "true"
716
+ )
2488
717
  end
2489
718
 
2490
- it "unions the $nin selectors" do
719
+ it "adds the $exists expression" do
2491
720
  expect(selection.selector).to eq({
2492
- "first" => { "$nin" => [ 1, 2, 3, 4 ] }
721
+ "users" => { "$exists" => true },
722
+ "comments" => { "$exists" => true }
2493
723
  })
2494
724
  end
2495
725
 
@@ -2499,286 +729,270 @@ describe Mongoid::Criteria::Queryable::Selectable do
2499
729
  end
2500
730
  end
2501
731
  end
2502
- end
2503
-
2504
- describe "#nor" do
2505
-
2506
- context "when provided no criterion" do
2507
-
2508
- let(:selection) do
2509
- query.nor
2510
- end
2511
-
2512
- it "does not add any criterion" do
2513
- expect(selection.selector).to eq({})
2514
- end
2515
-
2516
- it "returns the query" do
2517
- expect(selection).to eq(query)
2518
- end
2519
-
2520
- it "returns a cloned query" do
2521
- expect(selection).to_not equal(query)
2522
- end
2523
- end
2524
-
2525
- context "when provided nil" do
2526
-
2527
- let(:selection) do
2528
- query.nor(nil)
2529
- end
2530
-
2531
- it "does not add any criterion" do
2532
- expect(selection.selector).to eq({})
2533
- end
2534
-
2535
- it "returns the query" do
2536
- expect(selection).to eq(query)
2537
- end
2538
732
 
2539
- it "returns a cloned query" do
2540
- expect(selection).to_not equal(query)
2541
- end
2542
- end
733
+ context "when chaining multiple criteria" do
2543
734
 
2544
- context "when provided a single criterion" do
735
+ context "when the fields differ" do
2545
736
 
2546
- let(:selection) do
2547
- query.nor(field: [ 1, 2 ])
2548
- end
737
+ let(:selection) do
738
+ query.
739
+ exists(users: true).
740
+ exists(comments: true)
741
+ end
2549
742
 
2550
- it "adds the $nor selector" do
2551
- expect(selection.selector).to eq({
2552
- "$nor" => [{"field" => [ 1, 2 ] }]
2553
- })
2554
- end
743
+ it "adds the $exists expression" do
744
+ expect(selection.selector).to eq({
745
+ "users" => { "$exists" => true },
746
+ "comments" => { "$exists" => true }
747
+ })
748
+ end
2555
749
 
2556
- it "returns a cloned query" do
2557
- expect(selection).to_not equal(query)
750
+ it "returns a cloned query" do
751
+ expect(selection).to_not equal(query)
752
+ end
2558
753
  end
2559
754
  end
755
+ end
2560
756
 
2561
- context "when provided multiple criterion" do
757
+ describe "#geo_spatial" do
2562
758
 
2563
- context "when the criterion are fnor different fields" do
759
+ let(:query_method) { :geo_spatial }
760
+
761
+ it_behaves_like 'requires an argument'
762
+ it_behaves_like 'requires a non-nil argument'
763
+
764
+ context "when provided a criterion" do
765
+
766
+ context "when the geometry is a point intersection" do
2564
767
 
2565
768
  let(:selection) do
2566
- query.nor({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
769
+ query.geo_spatial(:location.intersects_point => [ 1, 10 ])
2567
770
  end
2568
771
 
2569
- it "adds the $nor selector" do
772
+ it "adds the $geoIntersects expression" do
2570
773
  expect(selection.selector).to eq({
2571
- "$nor" => [
2572
- { "first" => [ 1, 2 ] },
2573
- { "second" => [ 3, 4 ] }
2574
- ]
774
+ "location" => {
775
+ "$geoIntersects" => {
776
+ "$geometry" => {
777
+ "type" => "Point",
778
+ "coordinates" => [ 1, 10 ]
779
+ }
780
+ }
781
+ }
2575
782
  })
2576
783
  end
2577
784
 
2578
- it "returns a cloned query" do
2579
- expect(selection).to_not equal(query)
2580
- end
785
+ it_behaves_like "returns a cloned query"
2581
786
  end
2582
787
 
2583
- context "when the criterion are on the same field" do
788
+ context "when the geometry is a line intersection" do
2584
789
 
2585
790
  let(:selection) do
2586
- query.nor({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
791
+ query.geo_spatial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
2587
792
  end
2588
793
 
2589
- it "appends both $nor expressions" do
794
+ it "adds the $geoIntersects expression" do
2590
795
  expect(selection.selector).to eq({
2591
- "$nor" => [
2592
- { "first" => [ 1, 2 ] },
2593
- { "first" => [ 3, 4 ] }
2594
- ]
796
+ "location" => {
797
+ "$geoIntersects" => {
798
+ "$geometry" => {
799
+ "type" => "LineString",
800
+ "coordinates" => [[ 1, 10 ], [ 2, 10 ]]
801
+ }
802
+ }
803
+ }
2595
804
  })
2596
805
  end
2597
806
 
2598
- it "returns a cloned query" do
2599
- expect(selection).to_not equal(query)
2600
- end
807
+ it_behaves_like "returns a cloned query"
2601
808
  end
2602
- end
2603
809
 
2604
- context "when chaining the criterion" do
2605
-
2606
- context "when the criterion are fnor different fields" do
810
+ context "when the geometry is a polygon intersection" do
2607
811
 
2608
812
  let(:selection) do
2609
- query.nor(first: [ 1, 2 ]).nor(second: [ 3, 4 ])
813
+ query.geo_spatial(:location.intersects_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]])
2610
814
  end
2611
815
 
2612
- it "adds the $nor selectors" do
816
+ it "adds the $geoIntersects expression" do
2613
817
  expect(selection.selector).to eq({
2614
- "$nor" => [
2615
- { "first" => [ 1, 2 ] },
2616
- { "second" => [ 3, 4 ] }
2617
- ]
818
+ "location" => {
819
+ "$geoIntersects" => {
820
+ "$geometry" => {
821
+ "type" => "Polygon",
822
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
823
+ }
824
+ }
825
+ }
2618
826
  })
2619
827
  end
2620
828
 
2621
- it "returns a cloned query" do
2622
- expect(selection).to_not equal(query)
2623
- end
829
+ it_behaves_like "returns a cloned query"
2624
830
  end
2625
831
 
2626
- context "when the criterion are on the same field" do
832
+ context "when the geometry is within a polygon" do
2627
833
 
2628
834
  let(:selection) do
2629
- query.nor(first: [ 1, 2 ]).nor(first: [ 3, 4 ])
835
+ query.geo_spatial(:location.within_polygon => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]])
2630
836
  end
2631
837
 
2632
- it "appends both $nor expressions" do
838
+ it "adds the $geoIntersects expression" do
2633
839
  expect(selection.selector).to eq({
2634
- "$nor" => [
2635
- { "first" => [ 1, 2 ] },
2636
- { "first" => [ 3, 4 ] }
2637
- ]
840
+ "location" => {
841
+ "$geoWithin" => {
842
+ "$geometry" => {
843
+ "type" => "Polygon",
844
+ "coordinates" => [[[ 1, 10 ], [ 2, 10 ], [ 1, 10 ]]]
845
+ }
846
+ }
847
+ }
2638
848
  })
2639
849
  end
2640
850
 
2641
- it "returns a cloned query" do
2642
- 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
2643
867
  end
868
+
869
+ it_behaves_like "returns a cloned query"
2644
870
  end
2645
871
  end
2646
872
  end
2647
873
 
2648
- describe "#not" do
874
+ describe "#gt" do
875
+
876
+ let(:query_method) { :gt }
2649
877
 
2650
- context "when provided no criterion" do
878
+ it_behaves_like 'requires an argument'
879
+ it_behaves_like 'requires a non-nil argument'
880
+
881
+ context "when provided a single criterion" do
2651
882
 
2652
883
  let(:selection) do
2653
- query.not
884
+ query.gt(field: 10)
2654
885
  end
2655
886
 
2656
- it "does not add any criterion" do
2657
- expect(selection.selector).to eq({})
887
+ it "adds the $gt selector" do
888
+ expect(selection.selector).to eq({
889
+ "field" => { "$gt" => 10 }
890
+ })
2658
891
  end
2659
892
 
2660
- it "returns the query" do
2661
- expect(selection).to eq(query)
893
+ it "returns a cloned query" do
894
+ expect(selection).to_not equal(query)
2662
895
  end
896
+ end
2663
897
 
2664
- it "returns a non cloned query" do
2665
- expect(selection).to equal(query)
2666
- end
898
+ context "when provided multiple criterion" do
2667
899
 
2668
- context "when the following criteria is a query method" do
900
+ context "when the criterion are for different fields" do
2669
901
 
2670
902
  let(:selection) do
2671
- query.not.all(field: [ 1, 2 ])
903
+ query.gt(first: 10, second: 15)
2672
904
  end
2673
905
 
2674
- it "negates the all selection" do
2675
- expect(selection.selector).to eq(
2676
- { "field" => { "$not" => { "$all" => [ 1, 2 ] }}}
2677
- )
906
+ it "adds the $gt selectors" do
907
+ expect(selection.selector).to eq({
908
+ "first" => { "$gt" => 10 },
909
+ "second" => { "$gt" => 15 }
910
+ })
2678
911
  end
2679
912
 
2680
913
  it "returns a cloned query" do
2681
914
  expect(selection).to_not equal(query)
2682
915
  end
2683
-
2684
- it "removes the negation on the clone" do
2685
- expect(selection).to_not be_negating
2686
- end
2687
916
  end
917
+ end
2688
918
 
2689
- context "when the following criteria is a gt method" do
2690
-
2691
- let(:selection) do
2692
- query.not.gt(age: 50)
2693
- end
2694
-
2695
- it "negates the gt selection" do
2696
- expect(selection.selector).to eq(
2697
- { "age" => { "$not" => { "$gt" => 50 }}}
2698
- )
2699
- end
2700
-
2701
- it "returns a coned query" do
2702
- expect(selection).to_not eq(query)
2703
- end
2704
-
2705
- it "removes the negation on the clone" do
2706
- expect(selection).to_not be_negating
2707
- end
2708
- end
919
+ context "when chaining the criterion" do
2709
920
 
2710
- context "when the following criteria is a where" do
921
+ context "when the criterion are for different fields" do
2711
922
 
2712
923
  let(:selection) do
2713
- query.not.where(field: 1, :other.in => [ 1, 2 ])
924
+ query.gt(first: 10).gt(second: 15)
2714
925
  end
2715
926
 
2716
- it "negates the selection with an operator" do
2717
- expect(selection.selector).to eq(
2718
- { "field" => { "$ne" => 1 }, "other" => { "$not" => { "$in" => [ 1, 2 ] }}}
2719
- )
927
+ it "adds the $gt selectors" do
928
+ expect(selection.selector).to eq({
929
+ "first" => { "$gt" => 10 },
930
+ "second" => { "$gt" => 15 }
931
+ })
2720
932
  end
2721
933
 
2722
934
  it "returns a cloned query" do
2723
935
  expect(selection).to_not equal(query)
2724
936
  end
2725
-
2726
- it "removes the negation on the clone" do
2727
- expect(selection).to_not be_negating
2728
- end
2729
937
  end
2730
938
 
2731
- context "when the following criteria is a where with a regexp" do
939
+ context "when the criterion are on the same field" do
2732
940
 
2733
- let(:selection) do
2734
- query.not.where(field: 1, other: /test/)
2735
- end
941
+ context "when overwrite_chained_operators is true" do
942
+ config_override :overwrite_chained_operators, true
2736
943
 
2737
- it "negates the selection with an operator" do
2738
- expect(selection.selector).to eq(
2739
- { "field" => { "$ne" => 1 }, "other" => { "$not" => /test/ } }
2740
- )
2741
- end
944
+ let(:selection) do
945
+ query.gt(first: 10).gt(first: 15)
946
+ end
2742
947
 
2743
- it "returns a cloned query" do
2744
- expect(selection).to_not equal(query)
2745
- end
948
+ it "overwrites the first $gt selector" do
949
+ expect(selection.selector).to eq({
950
+ "first" => { "$gt" => 15 },
951
+ })
952
+ end
2746
953
 
2747
- it "removes the negation on the clone" do
2748
- expect(selection).to_not be_negating
954
+ it "returns a cloned query" do
955
+ expect(selection).to_not equal(query)
956
+ end
2749
957
  end
2750
958
 
2751
- end
2752
- end
959
+ context "when overwrite_chained_operators is false" do
960
+ config_override :overwrite_chained_operators, false
961
+ let(:selection) do
962
+ query.gt(first: 10).gt(first: 15)
963
+ end
2753
964
 
2754
- context "when provided nil" do
965
+ it "overwrites the first $gt selector" do
966
+ expect(selection.selector).to eq({
967
+ "first" => { "$gt" => 10 },
968
+ "$and" => [{ "first" => { "$gt" => 15 } }]
969
+ })
970
+ end
2755
971
 
2756
- let(:selection) do
2757
- query.not(nil)
972
+ it "returns a cloned query" do
973
+ expect(selection).to_not equal(query)
974
+ end
975
+ end
2758
976
  end
977
+ end
978
+ end
2759
979
 
2760
- it "does not add any criterion" do
2761
- expect(selection.selector).to eq({})
2762
- end
980
+ describe "#gte" do
2763
981
 
2764
- it "returns the query" do
2765
- expect(selection).to eq(query)
2766
- end
982
+ let(:query_method) { :gte }
2767
983
 
2768
- it "returns a cloned query" do
2769
- expect(selection).to_not equal(query)
2770
- end
2771
- end
984
+ it_behaves_like 'requires an argument'
985
+ it_behaves_like 'requires a non-nil argument'
2772
986
 
2773
987
  context "when provided a single criterion" do
2774
988
 
2775
989
  let(:selection) do
2776
- query.not(field: /test/)
990
+ query.gte(field: 10)
2777
991
  end
2778
992
 
2779
- it "adds the $not selector" do
993
+ it "adds the $gte selector" do
2780
994
  expect(selection.selector).to eq({
2781
- "field" => { "$not" => /test/ }
995
+ "field" => { "$gte" => 10 }
2782
996
  })
2783
997
  end
2784
998
 
@@ -2792,13 +1006,13 @@ describe Mongoid::Criteria::Queryable::Selectable do
2792
1006
  context "when the criterion are for different fields" do
2793
1007
 
2794
1008
  let(:selection) do
2795
- query.not(first: /1/, second: /2/)
1009
+ query.gte(first: 10, second: 15)
2796
1010
  end
2797
1011
 
2798
- it "adds the $not selectors" do
1012
+ it "adds the $gte selectors" do
2799
1013
  expect(selection.selector).to eq({
2800
- "first" => { "$not" => /1/ },
2801
- "second" => { "$not" => /2/ }
1014
+ "first" => { "$gte" => 10 },
1015
+ "second" => { "$gte" => 15 }
2802
1016
  })
2803
1017
  end
2804
1018
 
@@ -2813,13 +1027,13 @@ describe Mongoid::Criteria::Queryable::Selectable do
2813
1027
  context "when the criterion are for different fields" do
2814
1028
 
2815
1029
  let(:selection) do
2816
- query.not(first: /1/).not(second: /2/)
1030
+ query.gte(first: 10).gte(second: 15)
2817
1031
  end
2818
1032
 
2819
- it "adds the $not selectors" do
1033
+ it "adds the $gte selectors" do
2820
1034
  expect(selection.selector).to eq({
2821
- "first" => { "$not" => /1/ },
2822
- "second" => { "$not" => /2/ }
1035
+ "first" => { "$gte" => 10 },
1036
+ "second" => { "$gte" => 15 }
2823
1037
  })
2824
1038
  end
2825
1039
 
@@ -2831,110 +1045,56 @@ describe Mongoid::Criteria::Queryable::Selectable do
2831
1045
  context "when the criterion are on the same field" do
2832
1046
 
2833
1047
  let(:selection) do
2834
- query.not(first: /1/).not(first: /2/)
1048
+ query.gte(first: 10).gte(first: 15)
2835
1049
  end
2836
1050
 
2837
- it "overwrites the first $not selector" do
2838
- expect(selection.selector).to eq({
2839
- "first" => { "$not" => /2/ }
2840
- })
2841
- end
1051
+ context "when overwrite_chained_operators is false" do
1052
+ config_override :overwrite_chained_operators, false
2842
1053
 
2843
- it "returns a cloned query" do
2844
- expect(selection).to_not equal(query)
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
2845
1060
  end
2846
- end
2847
-
2848
- context "when the criterion are a double negative" do
2849
1061
 
2850
- let(:selection) do
2851
- query.not.where(:first.not => /1/)
2852
- end
1062
+ context "when overwrite_chained_operators is true" do
1063
+ config_override :overwrite_chained_operators, true
2853
1064
 
2854
- it "does not double the $not selector" do
2855
- expect(selection.selector).to eq({
2856
- "first" => { "$not" => /1/ }
2857
- })
1065
+ it "overwrites the first $gte selector" do
1066
+ expect(selection.selector).to eq({
1067
+ "first" => { "$gte" => 15 }
1068
+ })
1069
+ end
2858
1070
  end
2859
1071
 
2860
1072
  it "returns a cloned query" do
2861
- expect(selection).to_not equal(query)
2862
- end
2863
- end
2864
- end
2865
- end
2866
-
2867
- describe "#or" do
2868
-
2869
- context "when provided no criterion" do
2870
-
2871
- let(:selection) do
2872
- query.or
2873
- end
2874
-
2875
- it "does not add any criterion" do
2876
- expect(selection.selector).to eq({})
2877
- end
2878
-
2879
- it "returns the query" do
2880
- expect(selection).to eq(query)
2881
- end
2882
-
2883
- it "returns a cloned query" do
2884
- expect(selection).to_not equal(query)
2885
- end
2886
- end
2887
-
2888
- context "when provided nil" do
2889
-
2890
- let(:selection) do
2891
- query.or(nil)
2892
- end
2893
-
2894
- it "does not add any criterion" do
2895
- expect(selection.selector).to eq({})
2896
- end
2897
-
2898
- it "returns the query" do
2899
- expect(selection).to eq(query)
2900
- end
2901
-
2902
- it "returns a cloned query" do
2903
- expect(selection).to_not equal(query)
2904
- end
2905
- end
2906
-
2907
- context "when provided a single criterion" do
2908
-
2909
- let(:selection) do
2910
- query.or(field: [ 1, 2 ])
2911
- end
2912
-
2913
- it "adds the $or selector" do
2914
- expect(selection.selector).to eq({
2915
- "$or" => [{ "field" => [ 1, 2 ] }]
2916
- })
2917
- end
2918
-
2919
- it "returns a cloned query" do
2920
- expect(selection).to_not equal(query)
1073
+ expect(selection).to_not equal(query)
1074
+ end
2921
1075
  end
2922
1076
  end
1077
+ end
2923
1078
 
2924
- context "when provided multiple criterion" do
1079
+ describe "#in" do
2925
1080
 
2926
- context "when the criterion are for different fields" do
1081
+ let(:query_method) { :in }
1082
+ let(:operator) { '$in' }
1083
+
1084
+ it_behaves_like 'requires an argument'
1085
+ it_behaves_like 'requires a non-nil argument'
1086
+
1087
+ context "when provided a single criterion" do
1088
+
1089
+ context "when providing an array" do
2927
1090
 
2928
1091
  let(:selection) do
2929
- query.or({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
1092
+ query.in(field: [ 1, 2 ])
2930
1093
  end
2931
1094
 
2932
- it "adds the $or selector" do
1095
+ it "adds the $in selector" do
2933
1096
  expect(selection.selector).to eq({
2934
- "$or" => [
2935
- { "first" => [ 1, 2 ] },
2936
- { "second" => [ 3, 4 ] }
2937
- ]
1097
+ "field" => { "$in" => [ 1, 2 ] }
2938
1098
  })
2939
1099
  end
2940
1100
 
@@ -2943,18 +1103,15 @@ describe Mongoid::Criteria::Queryable::Selectable do
2943
1103
  end
2944
1104
  end
2945
1105
 
2946
- context "when a criterion has a selectable key" do
1106
+ context "when providing a single value" do
2947
1107
 
2948
1108
  let(:selection) do
2949
- query.or({ first: [ 1, 2 ] }, { :second.gt => 3 })
1109
+ query.in(field: 1)
2950
1110
  end
2951
1111
 
2952
- it "adds the $or selector" do
1112
+ it "adds the $in selector with wrapped value" do
2953
1113
  expect(selection.selector).to eq({
2954
- "$or" => [
2955
- { "first" => [ 1, 2 ] },
2956
- { "second" => { "$gt" => 3 }}
2957
- ]
1114
+ "field" => { "$in" => [ 1 ] }
2958
1115
  })
2959
1116
  end
2960
1117
 
@@ -2962,16 +1119,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
2962
1119
  expect(selection).to_not equal(query)
2963
1120
  end
2964
1121
  end
1122
+ end
1123
+
1124
+ context "when provided multiple criterion" do
2965
1125
 
2966
- context "when the criterion has an aliased field" do
1126
+ context "when the criterion are for different fields" do
2967
1127
 
2968
1128
  let(:selection) do
2969
- query.or({ id: 1 })
1129
+ query.in(first: [ 1, 2 ], second: 3..4)
2970
1130
  end
2971
1131
 
2972
- it "adds the $or selector and aliases the field" do
1132
+ it "adds the $in selectors" do
2973
1133
  expect(selection.selector).to eq({
2974
- "$or" => [ { "_id" => 1 } ]
1134
+ "first" => { "$in" => [ 1, 2 ] },
1135
+ "second" => { "$in" => [ 3, 4 ] }
2975
1136
  })
2976
1137
  end
2977
1138
 
@@ -2979,19 +1140,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
2979
1140
  expect(selection).to_not equal(query)
2980
1141
  end
2981
1142
  end
1143
+ end
1144
+
1145
+ context "when chaining the criterion" do
2982
1146
 
2983
- context "when a criterion is wrapped in an array" do
1147
+ context "when the criterion are for different fields" do
2984
1148
 
2985
1149
  let(:selection) do
2986
- query.or([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
1150
+ query.in(first: [ 1, 2 ]).in(second: [ 3, 4 ])
2987
1151
  end
2988
1152
 
2989
- it "adds the $or selector" do
1153
+ it "adds the $in selectors" do
2990
1154
  expect(selection.selector).to eq({
2991
- "$or" => [
2992
- { "first" => [ 1, 2 ] },
2993
- { "second" => { "$gt" => 3 }}
2994
- ]
1155
+ "first" => { "$in" => [ 1, 2 ] },
1156
+ "second" => { "$in" => [ 3, 4 ] }
2995
1157
  })
2996
1158
  end
2997
1159
 
@@ -3002,16 +1164,47 @@ describe Mongoid::Criteria::Queryable::Selectable do
3002
1164
 
3003
1165
  context "when the criterion are on the same field" do
3004
1166
 
1167
+ it_behaves_like 'supports merge strategies'
1168
+ end
1169
+ end
1170
+ end
1171
+
1172
+ describe "#lt" do
1173
+
1174
+ let(:query_method) { :lt }
1175
+
1176
+ it_behaves_like 'requires an argument'
1177
+ it_behaves_like 'requires a non-nil argument'
1178
+
1179
+ context "when provided a single criterion" do
1180
+
1181
+ let(:selection) do
1182
+ query.lt(field: 10)
1183
+ end
1184
+
1185
+ it "adds the $lt selector" do
1186
+ expect(selection.selector).to eq({
1187
+ "field" => { "$lt" => 10 }
1188
+ })
1189
+ end
1190
+
1191
+ it "returns a cloned query" do
1192
+ expect(selection).to_not equal(query)
1193
+ end
1194
+ end
1195
+
1196
+ context "when provided multiple criterion" do
1197
+
1198
+ context "when the criterion are for different fields" do
1199
+
3005
1200
  let(:selection) do
3006
- query.or({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
1201
+ query.lt(first: 10, second: 15)
3007
1202
  end
3008
1203
 
3009
- it "appends both $or expressions" do
1204
+ it "adds the $lt selectors" do
3010
1205
  expect(selection.selector).to eq({
3011
- "$or" => [
3012
- { "first" => [ 1, 2 ] },
3013
- { "first" => [ 3, 4 ] }
3014
- ]
1206
+ "first" => { "$lt" => 10 },
1207
+ "second" => { "$lt" => 15 }
3015
1208
  })
3016
1209
  end
3017
1210
 
@@ -3026,15 +1219,13 @@ describe Mongoid::Criteria::Queryable::Selectable do
3026
1219
  context "when the criterion are for different fields" do
3027
1220
 
3028
1221
  let(:selection) do
3029
- query.or(first: [ 1, 2 ]).or(second: [ 3, 4 ])
1222
+ query.lt(first: 10).lt(second: 15)
3030
1223
  end
3031
1224
 
3032
- it "adds the $or selectors" do
1225
+ it "adds the $lt selectors" do
3033
1226
  expect(selection.selector).to eq({
3034
- "$or" => [
3035
- { "first" => [ 1, 2 ] },
3036
- { "second" => [ 3, 4 ] }
3037
- ]
1227
+ "first" => { "$lt" => 10 },
1228
+ "second" => { "$lt" => 15 }
3038
1229
  })
3039
1230
  end
3040
1231
 
@@ -3046,16 +1237,28 @@ describe Mongoid::Criteria::Queryable::Selectable do
3046
1237
  context "when the criterion are on the same field" do
3047
1238
 
3048
1239
  let(:selection) do
3049
- query.or(first: [ 1, 2 ]).or(first: [ 3, 4 ])
1240
+ query.lt(first: 10).lt(first: 15)
3050
1241
  end
3051
1242
 
3052
- it "appends both $or expressions" do
3053
- expect(selection.selector).to eq({
3054
- "$or" => [
3055
- { "first" => [ 1, 2 ] },
3056
- { "first" => [ 3, 4 ] }
3057
- ]
3058
- })
1243
+ context "when overwrite_chained_operators is false" do
1244
+ config_override :overwrite_chained_operators, false
1245
+
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
1253
+
1254
+ context "when overwrite_chained_operators is true" do
1255
+ config_override :overwrite_chained_operators, true
1256
+
1257
+ it "overwrites the first $lt selector" do
1258
+ expect(selection.selector).to eq({
1259
+ "first" => { "$lt" => 15 }
1260
+ })
1261
+ end
3059
1262
  end
3060
1263
 
3061
1264
  it "returns a cloned query" do
@@ -3065,39 +1268,23 @@ describe Mongoid::Criteria::Queryable::Selectable do
3065
1268
  end
3066
1269
  end
3067
1270
 
3068
- describe "#with_size" do
3069
-
3070
- context "when provided no criterion" do
3071
-
3072
- let(:selection) do
3073
- query.with_size
3074
- end
3075
-
3076
- it "does not add any criterion" do
3077
- expect(selection.selector).to eq({})
3078
- end
1271
+ describe "#lte" do
3079
1272
 
3080
- it "returns the query" do
3081
- expect(selection).to eq(query)
3082
- end
1273
+ let(:query_method) { :lte }
3083
1274
 
3084
- it "returns a cloned query" do
3085
- expect(selection).to_not equal(query)
3086
- end
3087
- end
1275
+ it_behaves_like 'requires an argument'
1276
+ it_behaves_like 'requires a non-nil argument'
3088
1277
 
3089
- context "when provided nil" do
1278
+ context "when provided a single criterion" do
3090
1279
 
3091
1280
  let(:selection) do
3092
- query.with_size(nil)
3093
- end
3094
-
3095
- it "does not add any criterion" do
3096
- expect(selection.selector).to eq({})
1281
+ query.lte(field: 10)
3097
1282
  end
3098
1283
 
3099
- it "returns the query" do
3100
- expect(selection).to eq(query)
1284
+ it "adds the $lte selector" do
1285
+ expect(selection.selector).to eq({
1286
+ "field" => { "$lte" => 10 }
1287
+ })
3101
1288
  end
3102
1289
 
3103
1290
  it "returns a cloned query" do
@@ -3105,17 +1292,18 @@ describe Mongoid::Criteria::Queryable::Selectable do
3105
1292
  end
3106
1293
  end
3107
1294
 
3108
- context "when provided a single criterion" do
1295
+ context "when provided multiple criterion" do
3109
1296
 
3110
- context "when provided an integer" do
1297
+ context "when the criterion are for different fields" do
3111
1298
 
3112
1299
  let(:selection) do
3113
- query.with_size(field: 10)
1300
+ query.lte(first: 10, second: 15)
3114
1301
  end
3115
1302
 
3116
- it "adds the $size selector" do
1303
+ it "adds the $lte selectors" do
3117
1304
  expect(selection.selector).to eq({
3118
- "field" => { "$size" => 10 }
1305
+ "first" => { "$lte" => 10 },
1306
+ "second" => { "$lte" => 15 }
3119
1307
  })
3120
1308
  end
3121
1309
 
@@ -3123,16 +1311,20 @@ describe Mongoid::Criteria::Queryable::Selectable do
3123
1311
  expect(selection).to_not equal(query)
3124
1312
  end
3125
1313
  end
1314
+ end
3126
1315
 
3127
- context "when provided a string" do
1316
+ context "when chaining the criterion" do
1317
+
1318
+ context "when the criterion are for different fields" do
3128
1319
 
3129
1320
  let(:selection) do
3130
- query.with_size(field: "10")
1321
+ query.lte(first: 10).lte(second: 15)
3131
1322
  end
3132
1323
 
3133
- it "adds the $size selector with an integer" do
1324
+ it "adds the $lte selectors" do
3134
1325
  expect(selection.selector).to eq({
3135
- "field" => { "$size" => 10 }
1326
+ "first" => { "$lte" => 10 },
1327
+ "second" => { "$lte" => 15 }
3136
1328
  })
3137
1329
  end
3138
1330
 
@@ -3140,62 +1332,59 @@ describe Mongoid::Criteria::Queryable::Selectable do
3140
1332
  expect(selection).to_not equal(query)
3141
1333
  end
3142
1334
  end
3143
- end
3144
-
3145
- context "when provided multiple criterion" do
3146
1335
 
3147
- context "when the criterion are for different fields" do
1336
+ context "when the criterion are on the same field" do
3148
1337
 
3149
- context "when provided integers" do
1338
+ let(:selection) do
1339
+ query.lte(first: 10).lte(first: 15)
1340
+ end
3150
1341
 
3151
- let(:selection) do
3152
- query.with_size(first: 10, second: 15)
3153
- end
1342
+ context "when overwrite_chained_operators is false" do
1343
+ config_override :overwrite_chained_operators, false
3154
1344
 
3155
- it "adds the $size selectors" do
1345
+ it "adds a second $lte selector" do
3156
1346
  expect(selection.selector).to eq({
3157
- "first" => { "$size" => 10 },
3158
- "second" => { "$size" => 15 }
1347
+ "first" => { "$lte" => 10 },
1348
+ "$and" => [ { "first" => { "$lte" => 15 } } ]
3159
1349
  })
3160
1350
  end
3161
-
3162
- it "returns a cloned query" do
3163
- expect(selection).to_not equal(query)
3164
- end
3165
1351
  end
3166
1352
 
3167
- context "when provided strings" do
3168
-
3169
- let(:selection) do
3170
- query.with_size(first: "10", second: "15")
3171
- end
1353
+ context "when overwrite_chained_operators is true" do
1354
+ config_override :overwrite_chained_operators, true
3172
1355
 
3173
- it "adds the $size selectors" do
1356
+ it "overwrites the first $lte selector" do
3174
1357
  expect(selection.selector).to eq({
3175
- "first" => { "$size" => 10 },
3176
- "second" => { "$size" => 15 }
1358
+ "first" => { "$lte" => 15 }
3177
1359
  })
3178
1360
  end
1361
+ end
3179
1362
 
3180
- it "returns a cloned query" do
3181
- expect(selection).to_not equal(query)
3182
- end
1363
+ it "returns a cloned query" do
1364
+ expect(selection).to_not equal(query)
3183
1365
  end
3184
1366
  end
3185
1367
  end
1368
+ end
3186
1369
 
3187
- context "when chaining the criterion" do
1370
+ describe "#max_distance" do
3188
1371
 
3189
- context "when the criterion are for different fields" do
1372
+ let(:query_method) { :max_distance }
1373
+
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
3190
1380
 
3191
1381
  let(:selection) do
3192
- query.with_size(first: 10).with_size(second: 15)
1382
+ query.near(location: [ 1, 1 ]).max_distance(location: 50)
3193
1383
  end
3194
1384
 
3195
- it "adds the $size selectors" do
1385
+ it "adds the $maxDistance expression" do
3196
1386
  expect(selection.selector).to eq({
3197
- "first" => { "$size" => 10 },
3198
- "second" => { "$size" => 15 }
1387
+ "location" => { "$near" => [ 1, 1 ], "$maxDistance" => 50 }
3199
1388
  })
3200
1389
  end
3201
1390
 
@@ -3203,16 +1392,48 @@ describe Mongoid::Criteria::Queryable::Selectable do
3203
1392
  expect(selection).to_not equal(query)
3204
1393
  end
3205
1394
  end
1395
+ end
1396
+ end
3206
1397
 
3207
- context "when the criterion are on the same field" do
1398
+ describe "#mod" do
1399
+
1400
+ let(:query_method) { :mod }
1401
+
1402
+ it_behaves_like 'requires an argument'
1403
+ it_behaves_like 'requires a non-nil argument'
1404
+
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)
1419
+ end
1420
+ end
1421
+
1422
+ context "when providing multiple criteria" do
1423
+
1424
+ context "when the fields differ" do
3208
1425
 
3209
1426
  let(:selection) do
3210
- query.with_size(first: 10).with_size(first: 15)
1427
+ query.mod(
1428
+ value: [ 10, 1 ],
1429
+ comments: [ 10, 1 ]
1430
+ )
3211
1431
  end
3212
1432
 
3213
- it "overwrites the first $size selector" do
1433
+ it "adds the $mod expression" do
3214
1434
  expect(selection.selector).to eq({
3215
- "first" => { "$size" => 15 }
1435
+ "value" => { "$mod" => [ 10, 1 ] },
1436
+ "comments" => { "$mod" => [ 10, 1 ] }
3216
1437
  })
3217
1438
  end
3218
1439
 
@@ -3221,41 +1442,48 @@ describe Mongoid::Criteria::Queryable::Selectable do
3221
1442
  end
3222
1443
  end
3223
1444
  end
3224
- end
3225
1445
 
3226
- describe "#type" do
3227
-
3228
- context "when provided no criterion" do
1446
+ context "when chaining multiple criteria" do
3229
1447
 
3230
- let(:selection) do
3231
- query.with_type
3232
- end
1448
+ context "when the fields differ" do
3233
1449
 
3234
- it "does not add any criterion" do
3235
- expect(selection.selector).to eq({})
3236
- end
1450
+ let(:selection) do
1451
+ query.
1452
+ mod(value: [ 10, 1 ]).
1453
+ mod(result: [ 10, 1 ])
1454
+ end
3237
1455
 
3238
- it "returns the query" do
3239
- expect(selection).to eq(query)
3240
- end
1456
+ it "adds the $mod expression" do
1457
+ expect(selection.selector).to eq({
1458
+ "value" => { "$mod" => [ 10, 1 ] },
1459
+ "result" => { "$mod" => [ 10, 1 ] }
1460
+ })
1461
+ end
3241
1462
 
3242
- it "returns a cloned query" do
3243
- expect(selection).to_not equal(query)
1463
+ it "returns a cloned query" do
1464
+ expect(selection).to_not equal(query)
1465
+ end
3244
1466
  end
3245
1467
  end
1468
+ end
1469
+
1470
+ describe "#ne" do
1471
+
1472
+ let(:query_method) { :ne }
3246
1473
 
3247
- context "when provided nil" do
1474
+ it_behaves_like 'requires an argument'
1475
+ it_behaves_like 'requires a non-nil argument'
3248
1476
 
3249
- let(:selection) do
3250
- query.with_type(nil)
3251
- end
1477
+ context "when provided a criterion" do
3252
1478
 
3253
- it "does not add any criterion" do
3254
- expect(selection.selector).to eq({})
1479
+ let(:selection) do
1480
+ query.ne(value: 10)
3255
1481
  end
3256
1482
 
3257
- it "returns the query" do
3258
- expect(selection).to eq(query)
1483
+ it "adds the $ne expression" do
1484
+ expect(selection.selector).to eq({
1485
+ "value" => { "$ne" => 10 }
1486
+ })
3259
1487
  end
3260
1488
 
3261
1489
  it "returns a cloned query" do
@@ -3263,17 +1491,21 @@ describe Mongoid::Criteria::Queryable::Selectable do
3263
1491
  end
3264
1492
  end
3265
1493
 
3266
- context "when provided a single criterion" do
1494
+ context "when providing multiple criteria" do
3267
1495
 
3268
- context "when provided an integer" do
1496
+ context "when the fields differ" do
3269
1497
 
3270
1498
  let(:selection) do
3271
- query.with_type(field: 10)
1499
+ query.ne(
1500
+ value: 10,
1501
+ comments: 10
1502
+ )
3272
1503
  end
3273
1504
 
3274
- it "adds the $type selector" do
1505
+ it "adds the $ne expression" do
3275
1506
  expect(selection.selector).to eq({
3276
- "field" => { "$type" => 10 }
1507
+ "value" => { "$ne" => 10 },
1508
+ "comments" => { "$ne" => 10 }
3277
1509
  })
3278
1510
  end
3279
1511
 
@@ -3281,16 +1513,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
3281
1513
  expect(selection).to_not equal(query)
3282
1514
  end
3283
1515
  end
1516
+ end
3284
1517
 
3285
- context "when provided a string" do
1518
+ context "when chaining multiple criteria" do
1519
+
1520
+ context "when the fields differ" do
3286
1521
 
3287
1522
  let(:selection) do
3288
- query.with_type(field: "10")
1523
+ query.
1524
+ ne(value: 10).
1525
+ ne(result: 10)
3289
1526
  end
3290
1527
 
3291
- it "adds the $type selector" do
1528
+ it "adds the $ne expression" do
3292
1529
  expect(selection.selector).to eq({
3293
- "field" => { "$type" => 10 }
1530
+ "value" => { "$ne" => 10 },
1531
+ "result" => { "$ne" => 10 }
3294
1532
  })
3295
1533
  end
3296
1534
 
@@ -3299,40 +1537,47 @@ describe Mongoid::Criteria::Queryable::Selectable do
3299
1537
  end
3300
1538
  end
3301
1539
  end
1540
+ end
3302
1541
 
3303
- context "when provided multiple criterion" do
1542
+ describe "#near" do
3304
1543
 
3305
- context "when the criterion are for different fields" do
1544
+ let(:query_method) { :near }
3306
1545
 
3307
- let(:selection) do
3308
- query.with_type(first: 10, second: 15)
3309
- end
1546
+ it_behaves_like 'requires an argument'
1547
+ it_behaves_like 'requires a non-nil argument'
3310
1548
 
3311
- it "adds the $type selectors" do
3312
- expect(selection.selector).to eq({
3313
- "first" => { "$type" => 10 },
3314
- "second" => { "$type" => 15 }
3315
- })
3316
- end
1549
+ context "when provided a criterion" do
3317
1550
 
3318
- it "returns a cloned query" do
3319
- expect(selection).to_not equal(query)
3320
- end
1551
+ let(:selection) do
1552
+ query.near(location: [ 20, 21 ])
1553
+ end
1554
+
1555
+ it "adds the $near expression" do
1556
+ expect(selection.selector).to eq({
1557
+ "location" => { "$near" => [ 20, 21 ] }
1558
+ })
1559
+ end
1560
+
1561
+ it "returns a cloned query" do
1562
+ expect(selection).to_not equal(query)
3321
1563
  end
3322
1564
  end
3323
1565
 
3324
- context "when chaining the criterion" do
1566
+ context "when providing multiple criteria" do
3325
1567
 
3326
- context "when the criterion are for different fields" do
1568
+ context "when the fields differ" do
3327
1569
 
3328
1570
  let(:selection) do
3329
- query.with_type(first: 10).with_type(second: 15)
1571
+ query.near(
1572
+ location: [ 20, 21 ],
1573
+ comments: [ 20, 21 ]
1574
+ )
3330
1575
  end
3331
1576
 
3332
- it "adds the $type selectors" do
1577
+ it "adds the $near expression" do
3333
1578
  expect(selection.selector).to eq({
3334
- "first" => { "$type" => 10 },
3335
- "second" => { "$type" => 15 }
1579
+ "location" => { "$near" => [ 20, 21 ] },
1580
+ "comments" => { "$near" => [ 20, 21 ] }
3336
1581
  })
3337
1582
  end
3338
1583
 
@@ -3340,16 +1585,22 @@ describe Mongoid::Criteria::Queryable::Selectable do
3340
1585
  expect(selection).to_not equal(query)
3341
1586
  end
3342
1587
  end
1588
+ end
3343
1589
 
3344
- context "when the criterion are on the same field" do
1590
+ context "when chaining multiple criteria" do
1591
+
1592
+ context "when the fields differ" do
3345
1593
 
3346
1594
  let(:selection) do
3347
- query.with_type(first: 10).with_type(first: 15)
1595
+ query.
1596
+ near(location: [ 20, 21 ]).
1597
+ near(comments: [ 20, 21 ])
3348
1598
  end
3349
1599
 
3350
- it "overwrites the first $type selector" do
1600
+ it "adds the $near expression" do
3351
1601
  expect(selection.selector).to eq({
3352
- "first" => { "$type" => 15 }
1602
+ "location" => { "$near" => [ 20, 21 ] },
1603
+ "comments" => { "$near" => [ 20, 21 ] }
3353
1604
  })
3354
1605
  end
3355
1606
 
@@ -3360,489 +1611,450 @@ describe Mongoid::Criteria::Queryable::Selectable do
3360
1611
  end
3361
1612
  end
3362
1613
 
3363
- describe "#text_search" do
1614
+ describe "#near_sphere" do
3364
1615
 
3365
- context "when providing a search string" do
1616
+ let(:query_method) { :near_sphere }
1617
+
1618
+ it_behaves_like 'requires an argument'
1619
+ it_behaves_like 'requires a non-nil argument'
1620
+
1621
+ context "when provided a criterion" do
3366
1622
 
3367
1623
  let(:selection) do
3368
- query.text_search("testing")
1624
+ query.near_sphere(location: [ 20, 21 ])
3369
1625
  end
3370
1626
 
3371
- it "constructs a text search document" do
3372
- expect(selection.selector).to eq({ :$text => { :$search => "testing" }})
1627
+ it "adds the $nearSphere expression" do
1628
+ expect(selection.selector).to eq({
1629
+ "location" => { "$nearSphere" => [ 20, 21 ] }
1630
+ })
3373
1631
  end
3374
1632
 
3375
- it "returns the cloned selectable" do
3376
- expect(selection).to be_a(Mongoid::Criteria::Queryable::Selectable)
1633
+ it "returns a cloned query" do
1634
+ expect(selection).to_not equal(query)
3377
1635
  end
1636
+ end
3378
1637
 
3379
- context "when providing text search options" do
1638
+ context "when providing multiple criteria" do
1639
+
1640
+ context "when the fields differ" do
3380
1641
 
3381
1642
  let(:selection) do
3382
- query.text_search("essais", { :$language => "fr" })
1643
+ query.near_sphere(
1644
+ location: [ 20, 21 ],
1645
+ comments: [ 20, 21 ]
1646
+ )
3383
1647
  end
3384
1648
 
3385
- it "constructs a text search document" do
3386
- expect(selection.selector[:$text][:$search]).to eq("essais")
1649
+ it "adds the $nearSphere expression" do
1650
+ expect(selection.selector).to eq({
1651
+ "location" => { "$nearSphere" => [ 20, 21 ] },
1652
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
1653
+ })
3387
1654
  end
3388
1655
 
3389
- it "add the options to the text search document" do
3390
- expect(selection.selector[:$text][:$language]).to eq("fr")
1656
+ it "returns a cloned query" do
1657
+ expect(selection).to_not equal(query)
3391
1658
  end
3392
-
3393
- it_behaves_like "a cloning selection"
3394
1659
  end
3395
1660
  end
3396
- end
3397
-
3398
- describe "#where" do
3399
1661
 
3400
- context "when provided no criterion" do
1662
+ context "when chaining multiple criteria" do
3401
1663
 
3402
- let(:selection) do
3403
- query.where
3404
- end
1664
+ context "when the fields differ" do
3405
1665
 
3406
- it "does not add any criterion" do
3407
- expect(selection.selector).to eq({})
3408
- end
1666
+ let(:selection) do
1667
+ query.
1668
+ near_sphere(location: [ 20, 21 ]).
1669
+ near_sphere(comments: [ 20, 21 ])
1670
+ end
3409
1671
 
3410
- it "returns the query" do
3411
- expect(selection).to eq(query)
3412
- end
1672
+ it "adds the $nearSphere expression" do
1673
+ expect(selection.selector).to eq({
1674
+ "location" => { "$nearSphere" => [ 20, 21 ] },
1675
+ "comments" => { "$nearSphere" => [ 20, 21 ] }
1676
+ })
1677
+ end
3413
1678
 
3414
- it "returns a cloned query" do
3415
- expect(selection).to_not equal(query)
1679
+ it "returns a cloned query" do
1680
+ expect(selection).to_not equal(query)
1681
+ end
3416
1682
  end
3417
1683
  end
1684
+ end
3418
1685
 
3419
- context "when provided nil" do
3420
-
3421
- let(:selection) do
3422
- query.where(nil)
3423
- end
1686
+ describe "#nin" do
3424
1687
 
3425
- it "does not add any criterion" do
3426
- expect(selection.selector).to eq({})
3427
- end
1688
+ let(:query_method) { :nin }
1689
+ let(:operator) { '$nin' }
3428
1690
 
3429
- it "returns the query" do
3430
- expect(selection).to eq(query)
3431
- end
1691
+ it_behaves_like 'requires an argument'
1692
+ it_behaves_like 'requires a non-nil argument'
3432
1693
 
3433
- it "returns a cloned query" do
3434
- expect(selection).to_not equal(query)
3435
- end
3436
- end
1694
+ context "when provided a single criterion" do
3437
1695
 
3438
- context "when provided a string" do
1696
+ context "when providing an array" do
3439
1697
 
3440
- let(:selection) do
3441
- query.where("this.value = 10")
3442
- end
1698
+ let(:selection) do
1699
+ query.nin(field: [ 1, 2 ])
1700
+ end
3443
1701
 
3444
- it "adds the $where criterion" do
3445
- expect(selection.selector).to eq({ "$where" => "this.value = 10" })
3446
- end
1702
+ it "adds the $nin selector" do
1703
+ expect(selection.selector).to eq({
1704
+ "field" => { "$nin" => [ 1, 2 ] }
1705
+ })
1706
+ end
3447
1707
 
3448
- it "returns a cloned query" do
3449
- expect(selection).to_not equal(query)
1708
+ it "returns a cloned query" do
1709
+ expect(selection).to_not equal(query)
1710
+ end
3450
1711
  end
3451
- end
3452
-
3453
- context "when provided a single criterion" do
3454
1712
 
3455
- context "when the value needs no evolution" do
1713
+ context "when providing a single value" do
3456
1714
 
3457
1715
  let(:selection) do
3458
- query.where(name: "Syd")
1716
+ query.nin(field: 1)
1717
+ end
1718
+
1719
+ it "adds the $nin selector with wrapped value" do
1720
+ expect(selection.selector).to eq({
1721
+ "field" => { "$nin" => [ 1 ] }
1722
+ })
3459
1723
  end
3460
1724
 
3461
- it "adds the criterion to the selection" do
3462
- expect(selection.selector).to eq({ "name" => "Syd" })
1725
+ it "returns a cloned query" do
1726
+ expect(selection).to_not equal(query)
3463
1727
  end
3464
1728
  end
1729
+ end
3465
1730
 
3466
- context "when the value must be evolved" do
1731
+ context "when provided multiple criterion" do
3467
1732
 
3468
- before(:all) do
3469
- class Document
3470
- def id
3471
- 13
3472
- end
3473
- def self.evolve(object)
3474
- object.id
3475
- end
3476
- end
3477
- end
1733
+ context "when the criterion are for different fields" do
3478
1734
 
3479
- after(:all) do
3480
- Object.send(:remove_const, :Document)
1735
+ let(:selection) do
1736
+ query.nin(first: [ 1, 2 ], second: [ 3, 4 ])
3481
1737
  end
3482
1738
 
3483
- context "when the key needs evolution" do
1739
+ it "adds the $nin selectors" do
1740
+ expect(selection.selector).to eq({
1741
+ "first" => { "$nin" => [ 1, 2 ] },
1742
+ "second" => { "$nin" => [ 3, 4 ] }
1743
+ })
1744
+ end
3484
1745
 
3485
- let(:query) do
3486
- Mongoid::Query.new({ "user" => "user_id" })
3487
- end
1746
+ it "returns a cloned query" do
1747
+ expect(selection).to_not equal(query)
1748
+ end
1749
+ end
1750
+ end
3488
1751
 
3489
- let(:document) do
3490
- Document.new
3491
- end
1752
+ context "when chaining the criterion" do
3492
1753
 
3493
- let(:selection) do
3494
- query.where(user: document)
3495
- end
1754
+ context "when the criterion are for different fields" do
3496
1755
 
3497
- it "alters the key and value" do
3498
- expect(selection.selector).to eq({ "user_id" => document.id })
3499
- end
1756
+ let(:selection) do
1757
+ query.nin(first: [ 1, 2 ]).nin(second: [ 3, 4 ])
3500
1758
  end
3501
1759
 
3502
- context 'when the field is a String and the value is a BSON::Regexp::Raw' do
3503
-
3504
- let(:raw_regexp) do
3505
- BSON::Regexp::Raw.new('^Em')
3506
- end
3507
-
3508
- let(:selection) do
3509
- Login.where(_id: raw_regexp)
3510
- end
1760
+ it "adds the $nin selectors" do
1761
+ expect(selection.selector).to eq({
1762
+ "first" => { "$nin" => [ 1, 2 ] },
1763
+ "second" => { "$nin" => [ 3, 4 ] }
1764
+ })
1765
+ end
3511
1766
 
3512
- it 'does not convert the bson raw regexp object to a String' do
3513
- expect(selection.selector).to eq({ "_id" => raw_regexp })
3514
- end
1767
+ it "returns a cloned query" do
1768
+ expect(selection).to_not equal(query)
3515
1769
  end
3516
1770
  end
3517
- end
3518
-
3519
- context "when provided complex criterion" do
3520
1771
 
3521
- context "when performing an $all" do
1772
+ context "when the criterion are on the same field" do
3522
1773
 
3523
- context "when performing a single query" do
1774
+ it_behaves_like 'supports merge strategies'
1775
+ end
1776
+ end
1777
+ end
3524
1778
 
3525
- let(:selection) do
3526
- query.where(:field.all => [ 1, 2 ])
3527
- end
1779
+ describe "#with_size" do
3528
1780
 
3529
- it "adds the $all criterion" do
3530
- expect(selection.selector).to eq({ "field" => { "$all" => [ 1, 2 ] }})
3531
- end
1781
+ let(:query_method) { :with_size }
3532
1782
 
3533
- it "returns a cloned query" do
3534
- expect(selection).to_not eq(query)
3535
- end
3536
- end
3537
- end
1783
+ it_behaves_like 'requires an argument'
1784
+ it_behaves_like 'requires a non-nil argument'
3538
1785
 
3539
- context "when performing an $elemMatch" do
1786
+ context "when provided a single criterion" do
3540
1787
 
3541
- context "when the value is not complex" do
1788
+ context "when provided an integer" do
3542
1789
 
3543
- let(:selection) do
3544
- query.where(:field.elem_match => { key: 1 })
3545
- end
1790
+ let(:selection) do
1791
+ query.with_size(field: 10)
1792
+ end
3546
1793
 
3547
- it "adds the $elemMatch criterion" do
3548
- expect(selection.selector).to eq(
3549
- { "field" => { "$elemMatch" => { key: 1 } }}
3550
- )
3551
- end
1794
+ it "adds the $size selector" do
1795
+ expect(selection.selector).to eq({
1796
+ "field" => { "$size" => 10 }
1797
+ })
1798
+ end
3552
1799
 
3553
- it "returns a cloned query" do
3554
- expect(selection).to_not eq(query)
3555
- end
1800
+ it "returns a cloned query" do
1801
+ expect(selection).to_not equal(query)
3556
1802
  end
1803
+ end
3557
1804
 
3558
- context "when the value is complex" do
1805
+ context "when provided a string" do
3559
1806
 
3560
- let(:selection) do
3561
- query.where(:field.elem_match => { :key.gt => 1 })
3562
- end
1807
+ let(:selection) do
1808
+ query.with_size(field: "10")
1809
+ end
3563
1810
 
3564
- it "adds the $elemMatch criterion" do
3565
- expect(selection.selector).to eq(
3566
- { "field" => { "$elemMatch" => { "key" => { "$gt" => 1 }}}}
3567
- )
3568
- end
1811
+ it "adds the $size selector with an integer" do
1812
+ expect(selection.selector).to eq({
1813
+ "field" => { "$size" => 10 }
1814
+ })
1815
+ end
3569
1816
 
3570
- it "returns a cloned query" do
3571
- expect(selection).to_not eq(query)
3572
- end
1817
+ it "returns a cloned query" do
1818
+ expect(selection).to_not equal(query)
3573
1819
  end
3574
1820
  end
1821
+ end
1822
+
1823
+ context "when provided multiple criterion" do
3575
1824
 
3576
- context "when performing an $exists" do
1825
+ context "when the criterion are for different fields" do
3577
1826
 
3578
- context "when providing boolean values" do
1827
+ context "when provided integers" do
3579
1828
 
3580
1829
  let(:selection) do
3581
- query.where(:field.exists => true)
1830
+ query.with_size(first: 10, second: 15)
3582
1831
  end
3583
1832
 
3584
- it "adds the $exists criterion" do
3585
- expect(selection.selector).to eq(
3586
- { "field" => { "$exists" => true }}
3587
- )
1833
+ it "adds the $size selectors" do
1834
+ expect(selection.selector).to eq({
1835
+ "first" => { "$size" => 10 },
1836
+ "second" => { "$size" => 15 }
1837
+ })
3588
1838
  end
3589
1839
 
3590
1840
  it "returns a cloned query" do
3591
- expect(selection).to_not eq(query)
1841
+ expect(selection).to_not equal(query)
3592
1842
  end
3593
1843
  end
3594
1844
 
3595
- context "when providing string values" do
1845
+ context "when provided strings" do
3596
1846
 
3597
1847
  let(:selection) do
3598
- query.where(:field.exists => "t")
1848
+ query.with_size(first: "10", second: "15")
3599
1849
  end
3600
1850
 
3601
- it "adds the $exists criterion" do
3602
- expect(selection.selector).to eq(
3603
- { "field" => { "$exists" => true }}
3604
- )
1851
+ it "adds the $size selectors" do
1852
+ expect(selection.selector).to eq({
1853
+ "first" => { "$size" => 10 },
1854
+ "second" => { "$size" => 15 }
1855
+ })
3605
1856
  end
3606
1857
 
3607
1858
  it "returns a cloned query" do
3608
- expect(selection).to_not eq(query)
1859
+ expect(selection).to_not equal(query)
3609
1860
  end
3610
1861
  end
3611
1862
  end
1863
+ end
1864
+
1865
+ context "when chaining the criterion" do
3612
1866
 
3613
- context "when performing a $gt" do
1867
+ context "when the criterion are for different fields" do
3614
1868
 
3615
1869
  let(:selection) do
3616
- query.where(:field.gt => 10)
1870
+ query.with_size(first: 10).with_size(second: 15)
3617
1871
  end
3618
1872
 
3619
- it "adds the $gt criterion" do
3620
- expect(selection.selector).to eq(
3621
- { "field" => { "$gt" => 10 }}
3622
- )
1873
+ it "adds the $size selectors" do
1874
+ expect(selection.selector).to eq({
1875
+ "first" => { "$size" => 10 },
1876
+ "second" => { "$size" => 15 }
1877
+ })
3623
1878
  end
3624
1879
 
3625
1880
  it "returns a cloned query" do
3626
- expect(selection).to_not eq(query)
1881
+ expect(selection).to_not equal(query)
3627
1882
  end
3628
1883
  end
3629
1884
 
3630
- context "when performing a $gte" do
1885
+ context "when the criterion are on the same field" do
3631
1886
 
3632
1887
  let(:selection) do
3633
- query.where(:field.gte => 10)
1888
+ query.with_size(first: 10).with_size(first: 15)
3634
1889
  end
3635
1890
 
3636
- it "adds the $gte criterion" do
3637
- expect(selection.selector).to eq(
3638
- { "field" => { "$gte" => 10 }}
3639
- )
1891
+ it "overwrites the first $size selector" do
1892
+ expect(selection.selector).to eq({
1893
+ "first" => { "$size" => 15 }
1894
+ })
3640
1895
  end
3641
1896
 
3642
1897
  it "returns a cloned query" do
3643
- expect(selection).to_not eq(query)
1898
+ expect(selection).to_not equal(query)
3644
1899
  end
3645
1900
  end
1901
+ end
1902
+ end
3646
1903
 
3647
- context "when performing an $in" do
1904
+ describe "#with_type" do
3648
1905
 
3649
- let(:selection) do
3650
- query.where(:field.in => [ 1, 2 ])
3651
- end
1906
+ let(:query_method) { :with_type }
3652
1907
 
3653
- it "adds the $in criterion" do
3654
- expect(selection.selector).to eq({ "field" => { "$in" => [ 1, 2 ] }})
3655
- end
1908
+ it_behaves_like 'requires an argument'
1909
+ it_behaves_like 'requires a non-nil argument'
3656
1910
 
3657
- it "returns a cloned query" do
3658
- expect(selection).to_not eq(query)
3659
- end
3660
- end
1911
+ context "when provided a single criterion" do
3661
1912
 
3662
- context "when performing a $lt" do
1913
+ context "when provided an integer" do
3663
1914
 
3664
1915
  let(:selection) do
3665
- query.where(:field.lt => 10)
1916
+ query.with_type(field: 10)
3666
1917
  end
3667
1918
 
3668
- it "adds the $lt criterion" do
3669
- expect(selection.selector).to eq(
3670
- { "field" => { "$lt" => 10 }}
3671
- )
1919
+ it "adds the $type selector" do
1920
+ expect(selection.selector).to eq({
1921
+ "field" => { "$type" => 10 }
1922
+ })
3672
1923
  end
3673
1924
 
3674
1925
  it "returns a cloned query" do
3675
- expect(selection).to_not eq(query)
1926
+ expect(selection).to_not equal(query)
3676
1927
  end
3677
1928
  end
3678
1929
 
3679
- context "when performing a $lte" do
1930
+ context "when provided a string" do
3680
1931
 
3681
1932
  let(:selection) do
3682
- query.where(:field.lte => 10)
1933
+ query.with_type(field: "10")
3683
1934
  end
3684
1935
 
3685
- it "adds the $lte criterion" do
3686
- expect(selection.selector).to eq(
3687
- { "field" => { "$lte" => 10 }}
3688
- )
1936
+ it "adds the $type selector" do
1937
+ expect(selection.selector).to eq({
1938
+ "field" => { "$type" => 10 }
1939
+ })
3689
1940
  end
3690
1941
 
3691
1942
  it "returns a cloned query" do
3692
- expect(selection).to_not eq(query)
1943
+ expect(selection).to_not equal(query)
3693
1944
  end
3694
1945
  end
1946
+ end
3695
1947
 
3696
- context "when performing a $mod" do
1948
+ context "when provided multiple criterion" do
1949
+
1950
+ context "when the criterion are for different fields" do
3697
1951
 
3698
1952
  let(:selection) do
3699
- query.where(:field.mod => [ 10, 1 ])
1953
+ query.with_type(first: 10, second: 15)
3700
1954
  end
3701
1955
 
3702
- it "adds the $lte criterion" do
3703
- expect(selection.selector).to eq(
3704
- { "field" => { "$mod" => [ 10, 1 ]}}
3705
- )
1956
+ it "adds the $type selectors" do
1957
+ expect(selection.selector).to eq({
1958
+ "first" => { "$type" => 10 },
1959
+ "second" => { "$type" => 15 }
1960
+ })
3706
1961
  end
3707
1962
 
3708
1963
  it "returns a cloned query" do
3709
- expect(selection).to_not eq(query)
1964
+ expect(selection).to_not equal(query)
3710
1965
  end
3711
1966
  end
1967
+ end
1968
+
1969
+ context "when chaining the criterion" do
3712
1970
 
3713
- context "when performing a $ne" do
1971
+ context "when the criterion are for different fields" do
3714
1972
 
3715
1973
  let(:selection) do
3716
- query.where(:field.ne => 10)
1974
+ query.with_type(first: 10).with_type(second: 15)
3717
1975
  end
3718
1976
 
3719
- it "adds the $ne criterion" do
3720
- expect(selection.selector).to eq(
3721
- { "field" => { "$ne" => 10 }}
3722
- )
1977
+ it "adds the $type selectors" do
1978
+ expect(selection.selector).to eq({
1979
+ "first" => { "$type" => 10 },
1980
+ "second" => { "$type" => 15 }
1981
+ })
3723
1982
  end
3724
1983
 
3725
1984
  it "returns a cloned query" do
3726
- expect(selection).to_not eq(query)
1985
+ expect(selection).to_not equal(query)
3727
1986
  end
3728
1987
  end
3729
1988
 
3730
- context "when performing a $near" do
1989
+ context "when the criterion are on the same field" do
3731
1990
 
3732
1991
  let(:selection) do
3733
- query.where(:field.near => [ 1, 1 ])
1992
+ query.with_type(first: 10).with_type(first: 15)
3734
1993
  end
3735
1994
 
3736
- it "adds the $near criterion" do
3737
- expect(selection.selector).to eq(
3738
- { "field" => { "$near" => [ 1, 1 ] }}
3739
- )
1995
+ it "overwrites the first $type selector" do
1996
+ expect(selection.selector).to eq({
1997
+ "first" => { "$type" => 15 }
1998
+ })
3740
1999
  end
3741
2000
 
3742
2001
  it "returns a cloned query" do
3743
- expect(selection).to_not eq(query)
2002
+ expect(selection).to_not equal(query)
3744
2003
  end
3745
2004
  end
2005
+ end
2006
+ end
3746
2007
 
3747
- context "when performing a $nearSphere" do
3748
-
3749
- let(:selection) do
3750
- query.where(:field.near_sphere => [ 1, 1 ])
3751
- end
2008
+ describe "#text_search" do
3752
2009
 
3753
- it "adds the $nearSphere criterion" do
3754
- expect(selection.selector).to eq(
3755
- { "field" => { "$nearSphere" => [ 1, 1 ] }}
3756
- )
3757
- end
2010
+ context "when providing a search string" do
3758
2011
 
3759
- it "returns a cloned query" do
3760
- expect(selection).to_not eq(query)
3761
- end
2012
+ let(:selection) do
2013
+ query.text_search("testing")
3762
2014
  end
3763
2015
 
3764
- context "when performing a $nin" do
3765
-
3766
- let(:selection) do
3767
- query.where(:field.nin => [ 1, 2 ])
3768
- end
3769
-
3770
- it "adds the $nin criterion" do
3771
- expect(selection.selector).to eq({ "field" => { "$nin" => [ 1, 2 ] }})
3772
- end
2016
+ it "constructs a text search document" do
2017
+ expect(selection.selector).to eq({ '$text' => { '$search' => "testing" }})
2018
+ end
3773
2019
 
3774
- it "returns a cloned query" do
3775
- expect(selection).to_not eq(query)
3776
- end
2020
+ it "returns the cloned selectable" do
2021
+ expect(selection).to be_a(Mongoid::Criteria::Queryable::Selectable)
3777
2022
  end
3778
2023
 
3779
- context "when performing a $not" do
2024
+ context "when providing text search options" do
3780
2025
 
3781
2026
  let(:selection) do
3782
- query.where(:field.not => /test/)
3783
- end
3784
-
3785
- it "adds the $not criterion" do
3786
- expect(selection.selector).to eq({ "field" => { "$not" => /test/ }})
2027
+ query.text_search("essais", { :$language => "fr" })
3787
2028
  end
3788
2029
 
3789
- it "returns a cloned query" do
3790
- expect(selection).to_not eq(query)
2030
+ it "constructs a text search document" do
2031
+ expect(selection.selector['$text']['$search']).to eq("essais")
3791
2032
  end
3792
- end
3793
-
3794
- context "when performing a $size" do
3795
-
3796
- context "when providing an integer" do
3797
2033
 
3798
- let(:selection) do
3799
- query.where(:field.with_size => 10)
3800
- end
3801
-
3802
- it "adds the $size criterion" do
3803
- expect(selection.selector).to eq(
3804
- { "field" => { "$size" => 10 }}
3805
- )
3806
- end
3807
-
3808
- it "returns a cloned query" do
3809
- expect(selection).to_not eq(query)
3810
- end
2034
+ it "add the options to the text search document" do
2035
+ expect(selection.selector['$text'][:$language]).to eq("fr")
3811
2036
  end
3812
2037
 
3813
- context "when providing a string" do
3814
-
3815
- let(:selection) do
3816
- query.where(:field.with_size => "10")
3817
- end
3818
-
3819
- it "adds the $size criterion" do
3820
- expect(selection.selector).to eq(
3821
- { "field" => { "$size" => 10 }}
3822
- )
3823
- end
3824
-
3825
- it "returns a cloned query" do
3826
- expect(selection).to_not eq(query)
3827
- end
3828
- end
2038
+ it_behaves_like "returns a cloned query"
3829
2039
  end
2040
+ end
3830
2041
 
3831
- context "when performing a $type" do
3832
-
3833
- let(:selection) do
3834
- query.where(:field.with_type => 10)
3835
- end
3836
-
3837
- it "adds the $type criterion" do
3838
- expect(selection.selector).to eq(
3839
- { "field" => { "$type" => 10 }}
3840
- )
3841
- end
2042
+ context 'when given more than once' do
2043
+ let(:selection) do
2044
+ query.text_search("one").text_search('two')
2045
+ end
3842
2046
 
3843
- it "returns a cloned query" do
3844
- expect(selection).to_not eq(query)
3845
- 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
+ )
3846
2058
  end
3847
2059
  end
3848
2060
  end
@@ -3855,7 +2067,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3855
2067
  :field.all
3856
2068
  end
3857
2069
 
3858
- it "returns a selecton key" do
2070
+ it "returns a selection key" do
3859
2071
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3860
2072
  end
3861
2073
 
@@ -3874,7 +2086,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3874
2086
  :field.elem_match
3875
2087
  end
3876
2088
 
3877
- it "returns a selecton key" do
2089
+ it "returns a selection key" do
3878
2090
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3879
2091
  end
3880
2092
 
@@ -3893,7 +2105,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3893
2105
  :field.exists
3894
2106
  end
3895
2107
 
3896
- it "returns a selecton key" do
2108
+ it "returns a selection key" do
3897
2109
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3898
2110
  end
3899
2111
 
@@ -3912,7 +2124,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3912
2124
  :field.gt
3913
2125
  end
3914
2126
 
3915
- it "returns a selecton key" do
2127
+ it "returns a selection key" do
3916
2128
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3917
2129
  end
3918
2130
 
@@ -3931,7 +2143,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3931
2143
  :field.gte
3932
2144
  end
3933
2145
 
3934
- it "returns a selecton key" do
2146
+ it "returns a selection key" do
3935
2147
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3936
2148
  end
3937
2149
 
@@ -3950,7 +2162,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3950
2162
  :field.in
3951
2163
  end
3952
2164
 
3953
- it "returns a selecton key" do
2165
+ it "returns a selection key" do
3954
2166
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3955
2167
  end
3956
2168
 
@@ -3969,7 +2181,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3969
2181
  :field.lt
3970
2182
  end
3971
2183
 
3972
- it "returns a selecton key" do
2184
+ it "returns a selection key" do
3973
2185
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3974
2186
  end
3975
2187
 
@@ -3988,7 +2200,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
3988
2200
  :field.lte
3989
2201
  end
3990
2202
 
3991
- it "returns a selecton key" do
2203
+ it "returns a selection key" do
3992
2204
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
3993
2205
  end
3994
2206
 
@@ -4007,7 +2219,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4007
2219
  :field.mod
4008
2220
  end
4009
2221
 
4010
- it "returns a selecton key" do
2222
+ it "returns a selection key" do
4011
2223
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4012
2224
  end
4013
2225
 
@@ -4026,7 +2238,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4026
2238
  :field.ne
4027
2239
  end
4028
2240
 
4029
- it "returns a selecton key" do
2241
+ it "returns a selection key" do
4030
2242
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4031
2243
  end
4032
2244
 
@@ -4045,7 +2257,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4045
2257
  :field.near
4046
2258
  end
4047
2259
 
4048
- it "returns a selecton key" do
2260
+ it "returns a selection key" do
4049
2261
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4050
2262
  end
4051
2263
 
@@ -4064,7 +2276,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4064
2276
  :field.near_sphere
4065
2277
  end
4066
2278
 
4067
- it "returns a selecton key" do
2279
+ it "returns a selection key" do
4068
2280
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4069
2281
  end
4070
2282
 
@@ -4083,7 +2295,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4083
2295
  :field.nin
4084
2296
  end
4085
2297
 
4086
- it "returns a selecton key" do
2298
+ it "returns a selection key" do
4087
2299
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4088
2300
  end
4089
2301
 
@@ -4122,7 +2334,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4122
2334
  :field.with_size
4123
2335
  end
4124
2336
 
4125
- it "returns a selecton key" do
2337
+ it "returns a selection key" do
4126
2338
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4127
2339
  end
4128
2340
 
@@ -4141,7 +2353,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4141
2353
  :field.with_type
4142
2354
  end
4143
2355
 
4144
- it "returns a selecton key" do
2356
+ it "returns a selection key" do
4145
2357
  expect(key).to be_a(Mongoid::Criteria::Queryable::Key)
4146
2358
  end
4147
2359
 
@@ -4159,7 +2371,7 @@ describe Mongoid::Criteria::Queryable::Selectable do
4159
2371
 
4160
2372
  context "when using the strategies via methods" do
4161
2373
 
4162
- context "when the values are a hash" do
2374
+ context "when different operators are specified" do
4163
2375
 
4164
2376
  let(:selection) do
4165
2377
  query.gt(field: 5).lt(field: 10).ne(field: 7)
@@ -4167,26 +2379,26 @@ describe Mongoid::Criteria::Queryable::Selectable do
4167
2379
 
4168
2380
  it "merges the strategies on the same field" do
4169
2381
  expect(selection.selector).to eq(
4170
- { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
2382
+ "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }
4171
2383
  )
4172
2384
  end
4173
2385
  end
4174
2386
 
4175
- context "when the values are not hashes" do
2387
+ context "when the same operator is specified" do
4176
2388
 
4177
2389
  let(:selection) do
4178
2390
  query.where(field: 5).where(field: 10)
4179
2391
  end
4180
2392
 
4181
- it "overrides the previous field" do
4182
- expect(selection.selector).to eq({ "field" => 10 })
2393
+ it "combines conditions" do
2394
+ expect(selection.selector).to eq("field" => 5, '$and' => [{'field' => 10}] )
4183
2395
  end
4184
2396
  end
4185
2397
  end
4186
2398
 
4187
2399
  context "when using the strategies via #where" do
4188
2400
 
4189
- context "when the values are a hash" do
2401
+ context "when using complex keys with different operators" do
4190
2402
 
4191
2403
  let(:selection) do
4192
2404
  query.where(:field.gt => 5, :field.lt => 10, :field.ne => 7)
@@ -4194,10 +2406,57 @@ describe Mongoid::Criteria::Queryable::Selectable do
4194
2406
 
4195
2407
  it "merges the strategies on the same field" do
4196
2408
  expect(selection.selector).to eq(
4197
- { "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }}
2409
+ "field" => { "$gt" => 5, "$lt" => 10, "$ne" => 7 }
4198
2410
  )
4199
2411
  end
4200
2412
  end
4201
2413
  end
4202
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
4203
2462
  end