mongoid 5.4.1 → 7.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1354) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +30 -30
  4. data/LICENSE +1 -0
  5. data/README.md +33 -19
  6. data/Rakefile +75 -5
  7. data/lib/config/locales/en.yml +180 -64
  8. data/lib/mongoid/association/accessors.rb +402 -0
  9. data/lib/mongoid/association/bindable.rb +179 -0
  10. data/lib/mongoid/association/builders.rb +84 -0
  11. data/lib/mongoid/association/constrainable.rb +43 -0
  12. data/lib/mongoid/association/depending.rb +128 -0
  13. data/lib/mongoid/association/eager_loadable.rb +35 -0
  14. data/lib/mongoid/association/embedded/batchable.rb +358 -0
  15. data/lib/mongoid/association/embedded/cyclic.rb +102 -0
  16. data/lib/mongoid/association/embedded/embedded_in/binding.rb +52 -0
  17. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +38 -0
  18. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +111 -0
  19. data/lib/mongoid/association/embedded/embedded_in.rb +134 -0
  20. data/lib/mongoid/association/embedded/embeds_many/binding.rb +41 -0
  21. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +45 -0
  22. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +549 -0
  23. data/lib/mongoid/association/embedded/embeds_many.rb +183 -0
  24. data/lib/mongoid/association/embedded/embeds_one/binding.rb +43 -0
  25. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +39 -0
  26. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +145 -0
  27. data/lib/mongoid/association/embedded/embeds_one.rb +150 -0
  28. data/lib/mongoid/association/embedded.rb +6 -0
  29. data/lib/mongoid/association/macros.rb +207 -0
  30. data/lib/mongoid/association/many.rb +198 -0
  31. data/lib/mongoid/association/marshalable.rb +31 -0
  32. data/lib/mongoid/association/nested/many.rb +191 -0
  33. data/lib/mongoid/association/nested/nested_buildable.rb +66 -0
  34. data/lib/mongoid/association/nested/one.rb +116 -0
  35. data/lib/mongoid/association/nested.rb +15 -0
  36. data/lib/mongoid/association/one.rb +53 -0
  37. data/lib/mongoid/association/options.rb +122 -0
  38. data/lib/mongoid/association/proxy.rb +189 -0
  39. data/lib/mongoid/association/referenced/auto_save.rb +73 -0
  40. data/lib/mongoid/association/referenced/belongs_to/binding.rb +82 -0
  41. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +48 -0
  42. data/lib/mongoid/association/referenced/belongs_to/eager.rb +73 -0
  43. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +125 -0
  44. data/lib/mongoid/association/referenced/belongs_to.rb +226 -0
  45. data/lib/mongoid/association/referenced/counter_cache.rb +152 -0
  46. data/lib/mongoid/association/referenced/eager.rb +163 -0
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +72 -0
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +40 -0
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +53 -0
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +292 -0
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +270 -0
  52. data/lib/mongoid/association/referenced/has_many/binding.rb +36 -0
  53. data/lib/mongoid/association/referenced/has_many/buildable.rb +38 -0
  54. data/lib/mongoid/association/referenced/has_many/eager.rb +44 -0
  55. data/lib/mongoid/association/referenced/has_many/enumerable.rb +498 -0
  56. data/lib/mongoid/association/referenced/has_many/proxy.rb +545 -0
  57. data/lib/mongoid/association/referenced/has_many.rb +251 -0
  58. data/lib/mongoid/association/referenced/has_one/binding.rb +42 -0
  59. data/lib/mongoid/association/referenced/has_one/buildable.rb +74 -0
  60. data/lib/mongoid/association/referenced/has_one/eager.rb +36 -0
  61. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +113 -0
  62. data/lib/mongoid/association/referenced/has_one/proxy.rb +111 -0
  63. data/lib/mongoid/association/referenced/has_one.rb +184 -0
  64. data/lib/mongoid/association/referenced/syncable.rb +155 -0
  65. data/lib/mongoid/association/referenced.rb +9 -0
  66. data/lib/mongoid/association/reflections.rb +69 -0
  67. data/lib/mongoid/association/relatable.rb +455 -0
  68. data/lib/mongoid/association.rb +135 -0
  69. data/lib/mongoid/atomic/modifiers.rb +29 -53
  70. data/lib/mongoid/atomic/paths/embedded/many.rb +5 -8
  71. data/lib/mongoid/atomic/paths/embedded/one.rb +5 -8
  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 +47 -52
  76. data/lib/mongoid/attributes/dynamic.rb +19 -33
  77. data/lib/mongoid/attributes/nested.rb +29 -21
  78. data/lib/mongoid/attributes/processing.rb +11 -26
  79. data/lib/mongoid/attributes/projector.rb +119 -0
  80. data/lib/mongoid/attributes/readonly.rb +24 -7
  81. data/lib/mongoid/attributes.rb +110 -106
  82. data/lib/mongoid/cacheable.rb +33 -0
  83. data/lib/mongoid/changeable.rb +39 -57
  84. data/lib/mongoid/clients/factory.rb +42 -17
  85. data/lib/mongoid/clients/options.rb +62 -258
  86. data/lib/mongoid/clients/sessions.rb +125 -0
  87. data/lib/mongoid/clients/storage_options.rb +9 -81
  88. data/lib/mongoid/clients/validators/storage.rb +2 -9
  89. data/lib/mongoid/clients/validators.rb +2 -1
  90. data/lib/mongoid/clients.rb +13 -73
  91. data/lib/mongoid/composable.rb +33 -10
  92. data/lib/mongoid/config/environment.rb +36 -14
  93. data/lib/mongoid/config/options.rb +20 -23
  94. data/lib/mongoid/config/validators/client.rb +2 -17
  95. data/lib/mongoid/config/validators/option.rb +2 -3
  96. data/lib/mongoid/config/validators.rb +2 -1
  97. data/lib/mongoid/config.rb +112 -39
  98. data/lib/mongoid/contextual/aggregable/memory.rb +17 -12
  99. data/lib/mongoid/contextual/aggregable/mongo.rb +26 -27
  100. data/lib/mongoid/contextual/aggregable/none.rb +65 -0
  101. data/lib/mongoid/contextual/aggregable.rb +17 -0
  102. data/lib/mongoid/contextual/atomic.rb +31 -33
  103. data/lib/mongoid/contextual/command.rb +2 -5
  104. data/lib/mongoid/contextual/geo_near.rb +7 -38
  105. data/lib/mongoid/contextual/map_reduce.rb +12 -36
  106. data/lib/mongoid/contextual/memory.rb +34 -64
  107. data/lib/mongoid/contextual/mongo.rb +228 -113
  108. data/lib/mongoid/contextual/none.rb +51 -23
  109. data/lib/mongoid/contextual/queryable.rb +2 -3
  110. data/lib/mongoid/contextual.rb +7 -9
  111. data/lib/mongoid/copyable.rb +32 -19
  112. data/lib/mongoid/criteria/findable.rb +12 -15
  113. data/lib/mongoid/criteria/includable.rb +21 -28
  114. data/lib/mongoid/criteria/inspectable.rb +2 -3
  115. data/lib/mongoid/criteria/marshalable.rb +4 -7
  116. data/lib/mongoid/criteria/modifiable.rb +38 -24
  117. data/lib/mongoid/criteria/options.rb +24 -0
  118. data/lib/mongoid/criteria/permission.rb +2 -1
  119. data/lib/mongoid/criteria/queryable/aggregable.rb +109 -0
  120. data/lib/mongoid/criteria/queryable/expandable.rb +68 -0
  121. data/lib/mongoid/criteria/queryable/extensions/array.rb +162 -0
  122. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +36 -0
  123. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +33 -0
  124. data/lib/mongoid/criteria/queryable/extensions/date.rb +58 -0
  125. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +47 -0
  126. data/lib/mongoid/criteria/queryable/extensions/hash.rb +177 -0
  127. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +75 -0
  128. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +81 -0
  129. data/lib/mongoid/criteria/queryable/extensions/object.rb +181 -0
  130. data/lib/mongoid/criteria/queryable/extensions/range.rb +94 -0
  131. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +72 -0
  132. data/lib/mongoid/criteria/queryable/extensions/set.rb +33 -0
  133. data/lib/mongoid/criteria/queryable/extensions/string.rb +122 -0
  134. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +72 -0
  135. data/lib/mongoid/criteria/queryable/extensions/time.rb +55 -0
  136. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +61 -0
  137. data/lib/mongoid/criteria/queryable/extensions.rb +25 -0
  138. data/lib/mongoid/criteria/queryable/key.rb +177 -0
  139. data/lib/mongoid/criteria/queryable/macroable.rb +26 -0
  140. data/lib/mongoid/criteria/queryable/mergeable.rb +413 -0
  141. data/lib/mongoid/criteria/queryable/optional.rb +386 -0
  142. data/lib/mongoid/criteria/queryable/options.rb +136 -0
  143. data/lib/mongoid/criteria/queryable/pipeline.rb +106 -0
  144. data/lib/mongoid/criteria/queryable/selectable.rb +943 -0
  145. data/lib/mongoid/criteria/queryable/selector.rb +202 -0
  146. data/lib/mongoid/criteria/queryable/smash.rb +95 -0
  147. data/lib/mongoid/criteria/queryable/storable.rb +237 -0
  148. data/lib/mongoid/criteria/queryable.rb +85 -0
  149. data/lib/mongoid/criteria/scopable.rb +27 -19
  150. data/lib/mongoid/criteria.rb +93 -76
  151. data/lib/mongoid/document.rb +62 -109
  152. data/lib/mongoid/equality.rb +29 -12
  153. data/lib/mongoid/errors/ambiguous_relationship.rb +5 -6
  154. data/lib/mongoid/errors/callback.rb +2 -3
  155. data/lib/mongoid/errors/criteria_argument_required.rb +18 -0
  156. data/lib/mongoid/errors/delete_restriction.rb +10 -13
  157. data/lib/mongoid/errors/document_not_destroyed.rb +4 -7
  158. data/lib/mongoid/errors/document_not_found.rb +2 -9
  159. data/lib/mongoid/errors/eager_load.rb +6 -5
  160. data/lib/mongoid/errors/empty_config_file.rb +25 -0
  161. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +2 -3
  162. data/lib/mongoid/errors/invalid_collection.rb +2 -1
  163. data/lib/mongoid/errors/invalid_config_file.rb +25 -0
  164. data/lib/mongoid/errors/invalid_config_option.rb +2 -3
  165. data/lib/mongoid/errors/invalid_dependent_strategy.rb +31 -0
  166. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +24 -0
  167. data/lib/mongoid/errors/invalid_elem_match_operator.rb +32 -0
  168. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +25 -0
  169. data/lib/mongoid/errors/invalid_expression_operator.rb +27 -0
  170. data/lib/mongoid/errors/invalid_field.rb +4 -7
  171. data/lib/mongoid/errors/invalid_field_operator.rb +32 -0
  172. data/lib/mongoid/errors/invalid_field_option.rb +2 -3
  173. data/lib/mongoid/errors/invalid_find.rb +2 -3
  174. data/lib/mongoid/errors/invalid_includes.rb +2 -3
  175. data/lib/mongoid/errors/invalid_index.rb +2 -3
  176. data/lib/mongoid/errors/invalid_options.rb +4 -5
  177. data/lib/mongoid/errors/invalid_path.rb +2 -3
  178. data/lib/mongoid/errors/invalid_persistence_option.rb +26 -0
  179. data/lib/mongoid/errors/invalid_query.rb +40 -0
  180. data/lib/mongoid/errors/invalid_relation.rb +61 -0
  181. data/lib/mongoid/errors/invalid_relation_option.rb +28 -0
  182. data/lib/mongoid/errors/invalid_scope.rb +2 -3
  183. data/lib/mongoid/errors/invalid_session_use.rb +21 -0
  184. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +6 -5
  185. data/lib/mongoid/errors/invalid_storage_options.rb +2 -3
  186. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -3
  187. data/lib/mongoid/errors/invalid_time.rb +2 -3
  188. data/lib/mongoid/errors/invalid_value.rb +2 -1
  189. data/lib/mongoid/errors/inverse_not_found.rb +3 -4
  190. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -3
  191. data/lib/mongoid/errors/mixed_relations.rb +2 -3
  192. data/lib/mongoid/errors/mongoid_error.rb +3 -10
  193. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +3 -4
  194. data/lib/mongoid/errors/no_client_config.rb +4 -5
  195. data/lib/mongoid/errors/no_client_database.rb +2 -3
  196. data/lib/mongoid/errors/no_client_hosts.rb +2 -3
  197. data/lib/mongoid/errors/no_clients_config.rb +2 -3
  198. data/lib/mongoid/errors/no_default_client.rb +3 -4
  199. data/lib/mongoid/errors/no_environment.rb +2 -3
  200. data/lib/mongoid/errors/no_map_reduce_output.rb +2 -3
  201. data/lib/mongoid/errors/no_metadata.rb +2 -3
  202. data/lib/mongoid/errors/no_parent.rb +2 -3
  203. data/lib/mongoid/errors/readonly_attribute.rb +2 -3
  204. data/lib/mongoid/errors/readonly_document.rb +3 -6
  205. data/lib/mongoid/errors/scope_overwrite.rb +2 -1
  206. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +2 -0
  207. data/lib/mongoid/errors/unknown_attribute.rb +2 -3
  208. data/lib/mongoid/errors/unknown_model.rb +24 -0
  209. data/lib/mongoid/errors/unsaved_document.rb +3 -2
  210. data/lib/mongoid/errors/unsupported_javascript.rb +2 -3
  211. data/lib/mongoid/errors/validations.rb +2 -1
  212. data/lib/mongoid/errors.rb +18 -1
  213. data/lib/mongoid/evolvable.rb +4 -5
  214. data/lib/mongoid/extensions/array.rb +33 -42
  215. data/lib/mongoid/extensions/big_decimal.rb +17 -17
  216. data/lib/mongoid/extensions/boolean.rb +3 -5
  217. data/lib/mongoid/extensions/date.rb +17 -13
  218. data/lib/mongoid/extensions/date_time.rb +4 -12
  219. data/lib/mongoid/extensions/decimal128.rb +3 -6
  220. data/lib/mongoid/extensions/false_class.rb +4 -7
  221. data/lib/mongoid/extensions/float.rb +5 -10
  222. data/lib/mongoid/extensions/hash.rb +57 -38
  223. data/lib/mongoid/extensions/integer.rb +5 -12
  224. data/lib/mongoid/extensions/module.rb +2 -3
  225. data/lib/mongoid/extensions/nil_class.rb +2 -5
  226. data/lib/mongoid/extensions/object.rb +21 -48
  227. data/lib/mongoid/extensions/object_id.rb +2 -7
  228. data/lib/mongoid/extensions/range.rb +3 -11
  229. data/lib/mongoid/extensions/regexp.rb +4 -4
  230. data/lib/mongoid/extensions/set.rb +2 -7
  231. data/lib/mongoid/extensions/string.rb +27 -44
  232. data/lib/mongoid/extensions/symbol.rb +2 -7
  233. data/lib/mongoid/extensions/time.rb +16 -10
  234. data/lib/mongoid/extensions/time_with_zone.rb +25 -7
  235. data/lib/mongoid/extensions/true_class.rb +4 -7
  236. data/lib/mongoid/extensions.rb +18 -11
  237. data/lib/mongoid/factory.rb +60 -10
  238. data/lib/mongoid/fields/foreign_key.rb +8 -27
  239. data/lib/mongoid/fields/localized.rb +2 -11
  240. data/lib/mongoid/fields/standard.rb +8 -50
  241. data/lib/mongoid/fields/validators/macro.rb +50 -14
  242. data/lib/mongoid/fields/validators.rb +2 -1
  243. data/lib/mongoid/fields.rb +118 -67
  244. data/lib/mongoid/findable.rb +60 -24
  245. data/lib/mongoid/indexable/specification.rb +3 -16
  246. data/lib/mongoid/indexable/validators/options.rb +2 -7
  247. data/lib/mongoid/indexable.rb +26 -36
  248. data/lib/mongoid/inspectable.rb +4 -11
  249. data/lib/mongoid/interceptable.rb +27 -57
  250. data/lib/mongoid/loggable.rb +13 -16
  251. data/lib/mongoid/matchable.rb +5 -146
  252. data/lib/mongoid/matcher/all.rb +22 -0
  253. data/lib/mongoid/matcher/and.rb +21 -0
  254. data/lib/mongoid/matcher/bits.rb +41 -0
  255. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  256. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  257. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  258. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  259. data/lib/mongoid/matcher/elem_match.rb +36 -0
  260. data/lib/mongoid/matcher/elem_match_expression.rb +20 -0
  261. data/lib/mongoid/matcher/eq.rb +11 -0
  262. data/lib/mongoid/matcher/eq_impl.rb +67 -0
  263. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +26 -0
  264. data/lib/mongoid/matcher/exists.rb +15 -0
  265. data/lib/mongoid/matcher/expression.rb +35 -0
  266. data/lib/mongoid/matcher/expression_operator.rb +19 -0
  267. data/lib/mongoid/matcher/field_expression.rb +62 -0
  268. data/lib/mongoid/matcher/field_operator.rb +54 -0
  269. data/lib/mongoid/matcher/gt.rb +17 -0
  270. data/lib/mongoid/matcher/gte.rb +17 -0
  271. data/lib/mongoid/matcher/in.rb +25 -0
  272. data/lib/mongoid/matcher/lt.rb +17 -0
  273. data/lib/mongoid/matcher/lte.rb +17 -0
  274. data/lib/mongoid/matcher/mod.rb +17 -0
  275. data/lib/mongoid/matcher/ne.rb +16 -0
  276. data/lib/mongoid/matcher/nin.rb +11 -0
  277. data/lib/mongoid/matcher/nor.rb +25 -0
  278. data/lib/mongoid/matcher/not.rb +29 -0
  279. data/lib/mongoid/matcher/or.rb +21 -0
  280. data/lib/mongoid/matcher/regex.rb +41 -0
  281. data/lib/mongoid/matcher/size.rb +26 -0
  282. data/lib/mongoid/matcher/type.rb +99 -0
  283. data/lib/mongoid/matcher.rb +110 -0
  284. data/lib/mongoid/persistable/creatable.rb +9 -24
  285. data/lib/mongoid/persistable/deletable.rb +16 -29
  286. data/lib/mongoid/persistable/destroyable.rb +12 -15
  287. data/lib/mongoid/persistable/incrementable.rb +7 -8
  288. data/lib/mongoid/persistable/logical.rb +5 -7
  289. data/lib/mongoid/persistable/poppable.rb +3 -6
  290. data/lib/mongoid/persistable/pullable.rb +3 -8
  291. data/lib/mongoid/persistable/pushable.rb +14 -10
  292. data/lib/mongoid/persistable/renamable.rb +10 -8
  293. data/lib/mongoid/persistable/savable.rb +3 -8
  294. data/lib/mongoid/persistable/settable.rb +61 -19
  295. data/lib/mongoid/persistable/unsettable.rb +8 -8
  296. data/lib/mongoid/persistable/updatable.rb +38 -33
  297. data/lib/mongoid/persistable/upsertable.rb +5 -9
  298. data/lib/mongoid/persistable.rb +137 -45
  299. data/lib/mongoid/persistence_context.rb +222 -0
  300. data/lib/mongoid/positional.rb +3 -6
  301. data/lib/mongoid/query_cache.rb +141 -110
  302. data/lib/mongoid/railtie.rb +20 -17
  303. data/lib/mongoid/railties/controller_runtime.rb +88 -0
  304. data/lib/mongoid/railties/database.rake +9 -0
  305. data/lib/mongoid/reloadable.rb +14 -19
  306. data/lib/mongoid/scopable.rb +11 -38
  307. data/lib/mongoid/selectable.rb +8 -17
  308. data/lib/mongoid/serializable.rb +29 -34
  309. data/lib/mongoid/shardable.rb +80 -17
  310. data/lib/mongoid/stateful.rb +4 -10
  311. data/lib/mongoid/stringified_symbol.rb +52 -0
  312. data/lib/mongoid/tasks/database.rake +12 -5
  313. data/lib/mongoid/tasks/database.rb +88 -7
  314. data/lib/mongoid/threaded/lifecycle.rb +2 -21
  315. data/lib/mongoid/threaded.rb +70 -49
  316. data/lib/mongoid/timestamps/created/short.rb +2 -1
  317. data/lib/mongoid/timestamps/created.rb +3 -2
  318. data/lib/mongoid/timestamps/short.rb +2 -1
  319. data/lib/mongoid/timestamps/timeless.rb +6 -9
  320. data/lib/mongoid/timestamps/updated/short.rb +2 -1
  321. data/lib/mongoid/timestamps/updated.rb +3 -4
  322. data/lib/mongoid/timestamps.rb +3 -2
  323. data/lib/mongoid/touchable.rb +132 -0
  324. data/lib/mongoid/traversable.rb +181 -61
  325. data/lib/mongoid/validatable/associated.rb +5 -6
  326. data/lib/mongoid/validatable/format.rb +2 -1
  327. data/lib/mongoid/validatable/length.rb +2 -1
  328. data/lib/mongoid/validatable/localizable.rb +2 -3
  329. data/lib/mongoid/validatable/macros.rb +3 -8
  330. data/lib/mongoid/validatable/presence.rb +10 -15
  331. data/lib/mongoid/validatable/queryable.rb +2 -3
  332. data/lib/mongoid/validatable/uniqueness.rb +26 -40
  333. data/lib/mongoid/validatable.rb +16 -35
  334. data/lib/mongoid/version.rb +3 -2
  335. data/lib/mongoid.rb +35 -17
  336. data/lib/rails/generators/mongoid/config/config_generator.rb +10 -2
  337. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +54 -21
  338. data/lib/rails/generators/mongoid/model/model_generator.rb +3 -2
  339. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  340. data/lib/rails/generators/mongoid_generator.rb +2 -1
  341. data/lib/rails/mongoid.rb +4 -5
  342. data/spec/README.md +33 -0
  343. data/spec/config/mongoid.yml +28 -2
  344. data/spec/integration/app_spec.rb +343 -0
  345. data/spec/integration/associations/belongs_to_spec.rb +15 -0
  346. data/spec/integration/associations/embedded_dirty_spec.rb +29 -0
  347. data/spec/integration/associations/embedded_spec.rb +268 -0
  348. data/spec/integration/associations/embeds_many_spec.rb +206 -0
  349. data/spec/integration/associations/embeds_one_spec.rb +23 -0
  350. data/spec/integration/associations/foreign_key_spec.rb +98 -0
  351. data/spec/integration/associations/foreign_key_spec_models.rb +64 -0
  352. data/spec/integration/associations/has_many_spec.rb +128 -0
  353. data/spec/integration/associations/has_one_spec.rb +176 -0
  354. data/spec/integration/associations/nested_attributes_assignment_spec.rb +115 -0
  355. data/spec/integration/associations/reverse_population_spec.rb +34 -0
  356. data/spec/integration/associations/reverse_population_spec_models.rb +36 -0
  357. data/spec/integration/associations/scope_option_spec.rb +101 -0
  358. data/spec/integration/atomic/modifiers_spec.rb +116 -0
  359. data/spec/integration/bson_regexp_raw_spec.rb +19 -0
  360. data/spec/integration/callbacks_models.rb +61 -0
  361. data/spec/integration/callbacks_spec.rb +228 -0
  362. data/spec/integration/contextual/empty_spec.rb +141 -0
  363. data/spec/integration/criteria/alias_query_spec.rb +161 -0
  364. data/spec/integration/criteria/date_field_spec.rb +40 -0
  365. data/spec/integration/criteria/default_scope_spec.rb +72 -0
  366. data/spec/integration/criteria/logical_spec.rb +124 -0
  367. data/spec/integration/criteria/range_spec.rb +265 -0
  368. data/spec/integration/criteria/time_with_zone_spec.rb +142 -0
  369. data/spec/integration/discriminator_key_spec.rb +353 -0
  370. data/spec/integration/discriminator_value_spec.rb +206 -0
  371. data/spec/integration/document_spec.rb +51 -0
  372. data/spec/integration/i18n_fallbacks_spec.rb +89 -0
  373. data/spec/integration/matcher_examples_spec.rb +758 -0
  374. data/spec/integration/matcher_operator_data/all.yml +140 -0
  375. data/spec/integration/matcher_operator_data/and.yml +93 -0
  376. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  377. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  378. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  379. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  380. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  381. data/spec/integration/matcher_operator_data/elem_match.yml +409 -0
  382. data/spec/integration/matcher_operator_data/elem_match_expr.yml +213 -0
  383. data/spec/integration/matcher_operator_data/eq.yml +191 -0
  384. data/spec/integration/matcher_operator_data/exists.yml +213 -0
  385. data/spec/integration/matcher_operator_data/generic_op.yml +17 -0
  386. data/spec/integration/matcher_operator_data/gt.yml +132 -0
  387. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  388. data/spec/integration/matcher_operator_data/gte.yml +132 -0
  389. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  390. data/spec/integration/matcher_operator_data/implicit.yml +331 -0
  391. data/spec/integration/matcher_operator_data/implicit_traversal.yml +112 -0
  392. data/spec/integration/matcher_operator_data/in.yml +210 -0
  393. data/spec/integration/matcher_operator_data/invalid_op.yml +59 -0
  394. data/spec/integration/matcher_operator_data/invalid_syntax.yml +39 -0
  395. data/spec/integration/matcher_operator_data/lt.yml +132 -0
  396. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  397. data/spec/integration/matcher_operator_data/lte.yml +132 -0
  398. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  399. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  400. data/spec/integration/matcher_operator_data/multiple.yml +29 -0
  401. data/spec/integration/matcher_operator_data/ne.yml +150 -0
  402. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  403. data/spec/integration/matcher_operator_data/nin.yml +114 -0
  404. data/spec/integration/matcher_operator_data/nor.yml +126 -0
  405. data/spec/integration/matcher_operator_data/not.yml +196 -0
  406. data/spec/integration/matcher_operator_data/or.yml +137 -0
  407. data/spec/integration/matcher_operator_data/regex.yml +174 -0
  408. data/spec/integration/matcher_operator_data/regex_options.yml +72 -0
  409. data/spec/integration/matcher_operator_data/size.yml +174 -0
  410. data/spec/integration/matcher_operator_data/type.yml +70 -0
  411. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  412. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  413. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  414. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  415. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  416. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  417. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  418. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  419. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  420. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  421. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  422. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  423. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  424. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  425. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  426. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  427. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  428. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  429. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  430. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  431. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  432. data/spec/integration/matcher_operator_spec.rb +124 -0
  433. data/spec/integration/matcher_spec.rb +283 -0
  434. data/spec/integration/server_query_spec.rb +141 -0
  435. data/spec/integration/shardable_spec.rb +148 -0
  436. data/spec/integration/stringified_symbol_field_spec.rb +203 -0
  437. data/spec/lite_spec_helper.rb +83 -0
  438. data/spec/mongoid/association/accessors_spec.rb +1067 -0
  439. data/spec/mongoid/association/auto_save_spec.rb +403 -0
  440. data/spec/mongoid/association/builders_spec.rb +255 -0
  441. data/spec/mongoid/association/constrainable_spec.rb +117 -0
  442. data/spec/mongoid/association/counter_cache_spec.rb +452 -0
  443. data/spec/mongoid/association/depending_spec.rb +959 -0
  444. data/spec/mongoid/association/eager_spec.rb +281 -0
  445. data/spec/mongoid/association/embedded/cyclic_spec.rb +180 -0
  446. data/spec/mongoid/association/embedded/dirty_spec.rb +67 -0
  447. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +173 -0
  448. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +36 -0
  449. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +559 -0
  450. data/spec/mongoid/association/embedded/embedded_in_spec.rb +903 -0
  451. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +56 -0
  452. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +106 -0
  453. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +4652 -0
  454. data/spec/mongoid/association/embedded/embeds_many_models.rb +69 -0
  455. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +51 -0
  456. data/spec/mongoid/association/embedded/embeds_many_spec.rb +864 -0
  457. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +79 -0
  458. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +81 -0
  459. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +1025 -0
  460. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +8 -0
  461. data/spec/mongoid/association/embedded/embeds_one_models.rb +54 -0
  462. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +28 -0
  463. data/spec/mongoid/association/embedded/embeds_one_spec.rb +956 -0
  464. data/spec/mongoid/association/macros_spec.rb +1116 -0
  465. data/spec/mongoid/association/nested/many_spec.rb +232 -0
  466. data/spec/mongoid/association/nested/one_spec.rb +253 -0
  467. data/spec/mongoid/association/options_spec.rb +1323 -0
  468. data/spec/mongoid/association/polymorphic_spec.rb +162 -0
  469. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +243 -0
  470. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +238 -0
  471. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +412 -0
  472. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +1373 -0
  473. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +57 -0
  474. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2046 -0
  475. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +180 -0
  476. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +148 -0
  477. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +196 -0
  478. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +76 -0
  479. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +3773 -0
  480. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +67 -0
  481. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +39 -0
  482. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1071 -0
  483. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +155 -0
  484. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +142 -0
  485. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +290 -0
  486. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2232 -0
  487. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
  488. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +4092 -0
  489. data/spec/mongoid/association/referenced/has_many_models.rb +95 -0
  490. data/spec/mongoid/association/referenced/has_many_query_spec.rb +37 -0
  491. data/spec/mongoid/association/referenced/has_many_spec.rb +1248 -0
  492. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +133 -0
  493. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +159 -0
  494. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +193 -0
  495. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +1142 -0
  496. data/spec/mongoid/association/referenced/has_one_models.rb +97 -0
  497. data/spec/mongoid/association/referenced/has_one_query_spec.rb +37 -0
  498. data/spec/mongoid/association/referenced/has_one_spec.rb +1383 -0
  499. data/spec/mongoid/association/reflections_spec.rb +92 -0
  500. data/spec/mongoid/association/syncable_spec.rb +499 -0
  501. data/spec/mongoid/association_spec.rb +191 -0
  502. data/spec/mongoid/atomic/modifiers_spec.rb +52 -3
  503. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +2 -0
  504. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +2 -0
  505. data/spec/mongoid/atomic/paths/root_spec.rb +2 -0
  506. data/spec/mongoid/atomic/paths_spec.rb +107 -12
  507. data/spec/mongoid/atomic_spec.rb +36 -11
  508. data/spec/mongoid/attributes/dynamic_spec.rb +152 -0
  509. data/spec/mongoid/attributes/nested_spec.rb +115 -91
  510. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  511. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  512. data/spec/mongoid/attributes/projector_spec.rb +44 -0
  513. data/spec/mongoid/attributes/readonly_spec.rb +111 -111
  514. data/spec/mongoid/attributes_spec.rb +501 -33
  515. data/spec/mongoid/cacheable_spec.rb +114 -0
  516. data/spec/mongoid/changeable_spec.rb +118 -35
  517. data/spec/mongoid/clients/factory_spec.rb +176 -34
  518. data/spec/mongoid/clients/options_spec.rb +431 -98
  519. data/spec/mongoid/clients/sessions_spec.rb +335 -0
  520. data/spec/mongoid/clients/transactions_spec.rb +415 -0
  521. data/spec/mongoid/clients_spec.rb +318 -114
  522. data/spec/mongoid/composable_spec.rb +9 -0
  523. data/spec/mongoid/config/environment_spec.rb +88 -8
  524. data/spec/mongoid/config/options_spec.rb +22 -3
  525. data/spec/mongoid/config_spec.rb +371 -13
  526. data/spec/mongoid/contextual/aggregable/memory_spec.rb +53 -11
  527. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +122 -20
  528. data/spec/mongoid/contextual/aggregable/none_spec.rb +60 -0
  529. data/spec/mongoid/contextual/atomic_spec.rb +245 -84
  530. data/spec/mongoid/contextual/geo_near_spec.rb +31 -19
  531. data/spec/mongoid/contextual/map_reduce_spec.rb +24 -7
  532. data/spec/mongoid/contextual/memory_spec.rb +44 -23
  533. data/spec/mongoid/contextual/mongo_spec.rb +780 -155
  534. data/spec/mongoid/contextual/none_spec.rb +14 -71
  535. data/spec/mongoid/copyable_spec.rb +297 -23
  536. data/spec/mongoid/copyable_spec_models.rb +47 -0
  537. data/spec/mongoid/criteria/findable_spec.rb +77 -20
  538. data/spec/mongoid/criteria/inspectable_spec.rb +2 -0
  539. data/spec/mongoid/criteria/marshalable_spec.rb +2 -0
  540. data/spec/mongoid/criteria/modifiable_spec.rb +506 -50
  541. data/spec/mongoid/criteria/options_spec.rb +31 -0
  542. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +372 -0
  543. data/spec/mongoid/criteria/queryable/expandable_spec.rb +61 -0
  544. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +525 -0
  545. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +61 -0
  546. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +60 -0
  547. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +215 -0
  548. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +332 -0
  549. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +423 -0
  550. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +60 -0
  551. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +67 -0
  552. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +329 -0
  553. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +67 -0
  554. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +79 -0
  555. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +53 -0
  556. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +110 -0
  557. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +370 -0
  558. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +91 -0
  559. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +92 -0
  560. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +41 -0
  561. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +347 -0
  562. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +169 -0
  563. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +395 -0
  564. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +376 -0
  565. data/spec/mongoid/criteria/queryable/key_spec.rb +96 -0
  566. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +182 -0
  567. data/spec/mongoid/criteria/queryable/optional_spec.rb +1801 -0
  568. data/spec/mongoid/criteria/queryable/options_spec.rb +362 -0
  569. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +214 -0
  570. data/spec/mongoid/criteria/queryable/queryable_spec.rb +139 -0
  571. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +2069 -0
  572. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +38 -0
  573. data/spec/mongoid/criteria/queryable/selectable_spec.rb +2297 -0
  574. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +589 -0
  575. data/spec/mongoid/criteria/queryable/selector_spec.rb +883 -0
  576. data/spec/mongoid/criteria/queryable/smash_spec.rb +32 -0
  577. data/spec/mongoid/criteria/queryable/storable_spec.rb +226 -0
  578. data/spec/mongoid/criteria/scopable_spec.rb +210 -0
  579. data/spec/mongoid/criteria_projection_spec.rb +410 -0
  580. data/spec/mongoid/criteria_spec.rb +876 -402
  581. data/spec/mongoid/document_fields_spec.rb +113 -0
  582. data/spec/mongoid/document_persistence_context_spec.rb +32 -0
  583. data/spec/mongoid/document_query_spec.rb +89 -0
  584. data/spec/mongoid/document_spec.rb +214 -104
  585. data/spec/mongoid/equality_spec.rb +144 -41
  586. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +5 -3
  587. data/spec/mongoid/errors/callback_spec.rb +2 -0
  588. data/spec/mongoid/errors/delete_restriction_spec.rb +4 -2
  589. data/spec/mongoid/errors/document_not_destroyed_spec.rb +2 -0
  590. data/spec/mongoid/errors/document_not_found_spec.rb +2 -0
  591. data/spec/mongoid/errors/eager_load_spec.rb +2 -0
  592. data/spec/mongoid/errors/invalid_collection_spec.rb +2 -0
  593. data/spec/mongoid/errors/invalid_config_file_spec.rb +31 -0
  594. data/spec/mongoid/errors/invalid_config_option_spec.rb +2 -0
  595. data/spec/mongoid/errors/invalid_field_option_spec.rb +2 -0
  596. data/spec/mongoid/errors/invalid_field_spec.rb +2 -0
  597. data/spec/mongoid/errors/invalid_find_spec.rb +2 -0
  598. data/spec/mongoid/errors/invalid_includes_spec.rb +2 -0
  599. data/spec/mongoid/errors/invalid_index_spec.rb +2 -0
  600. data/spec/mongoid/errors/invalid_options_spec.rb +4 -2
  601. data/spec/mongoid/errors/invalid_path_spec.rb +2 -0
  602. data/spec/mongoid/errors/invalid_relation_spec.rb +39 -0
  603. data/spec/mongoid/errors/invalid_scope_spec.rb +3 -1
  604. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +2 -0
  605. data/spec/mongoid/errors/invalid_storage_options_spec.rb +2 -0
  606. data/spec/mongoid/errors/invalid_time_spec.rb +2 -0
  607. data/spec/mongoid/errors/inverse_not_found_spec.rb +3 -1
  608. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +2 -0
  609. data/spec/mongoid/errors/mixed_relations_spec.rb +2 -0
  610. data/spec/mongoid/errors/mongoid_error_spec.rb +28 -11
  611. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +5 -3
  612. data/spec/mongoid/errors/no_client_config_spec.rb +4 -2
  613. data/spec/mongoid/errors/no_client_database_spec.rb +5 -3
  614. data/spec/mongoid/errors/no_client_hosts_spec.rb +5 -3
  615. data/spec/mongoid/errors/no_clients_config_spec.rb +2 -0
  616. data/spec/mongoid/errors/no_environment_spec.rb +2 -0
  617. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +2 -0
  618. data/spec/mongoid/errors/no_metadata_spec.rb +4 -2
  619. data/spec/mongoid/errors/no_parent_spec.rb +3 -1
  620. data/spec/mongoid/errors/readonly_attribute_spec.rb +2 -0
  621. data/spec/mongoid/errors/readonly_document_spec.rb +2 -0
  622. data/spec/mongoid/errors/scope_overwrite_spec.rb +2 -0
  623. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +2 -0
  624. data/spec/mongoid/errors/unknown_attribute_spec.rb +4 -2
  625. data/spec/mongoid/errors/unsaved_document_spec.rb +3 -1
  626. data/spec/mongoid/errors/unsupported_javascript_spec.rb +2 -0
  627. data/spec/mongoid/errors/validations_spec.rb +2 -0
  628. data/spec/mongoid/extensions/array_spec.rb +36 -58
  629. data/spec/mongoid/extensions/big_decimal_spec.rb +323 -19
  630. data/spec/mongoid/extensions/binary_spec.rb +2 -0
  631. data/spec/mongoid/extensions/boolean_spec.rb +16 -0
  632. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +335 -0
  633. data/spec/mongoid/extensions/date_spec.rb +8 -164
  634. data/spec/mongoid/extensions/date_time_spec.rb +19 -66
  635. data/spec/mongoid/extensions/decimal128_spec.rb +3 -1
  636. data/spec/mongoid/extensions/false_class_spec.rb +3 -1
  637. data/spec/mongoid/extensions/float_spec.rb +25 -4
  638. data/spec/mongoid/extensions/hash_spec.rb +138 -1
  639. data/spec/mongoid/extensions/integer_spec.rb +22 -3
  640. data/spec/mongoid/extensions/module_spec.rb +2 -0
  641. data/spec/mongoid/extensions/nil_class_spec.rb +2 -0
  642. data/spec/mongoid/extensions/object_id_spec.rb +2 -0
  643. data/spec/mongoid/extensions/object_spec.rb +27 -31
  644. data/spec/mongoid/extensions/range_spec.rb +9 -0
  645. data/spec/mongoid/extensions/regexp_spec.rb +25 -0
  646. data/spec/mongoid/extensions/set_spec.rb +2 -0
  647. data/spec/mongoid/extensions/string_spec.rb +113 -31
  648. data/spec/mongoid/extensions/stringified_symbol_spec.rb +84 -0
  649. data/spec/mongoid/extensions/symbol_spec.rb +2 -0
  650. data/spec/mongoid/extensions/time_spec.rb +31 -6
  651. data/spec/mongoid/extensions/time_with_zone_spec.rb +35 -6
  652. data/spec/mongoid/extensions/true_class_spec.rb +3 -1
  653. data/spec/mongoid/extensions_spec.rb +16 -2
  654. data/spec/mongoid/factory_spec.rb +304 -15
  655. data/spec/mongoid/fields/foreign_key_spec.rb +26 -32
  656. data/spec/mongoid/fields/localized_spec.rb +6 -4
  657. data/spec/mongoid/fields/standard_spec.rb +2 -0
  658. data/spec/mongoid/fields_spec.rb +420 -38
  659. data/spec/mongoid/findable_spec.rb +98 -19
  660. data/spec/mongoid/indexable/specification_spec.rb +2 -0
  661. data/spec/mongoid/indexable_spec.rb +69 -17
  662. data/spec/mongoid/inspectable_spec.rb +39 -2
  663. data/spec/mongoid/interceptable_spec.rb +273 -114
  664. data/spec/mongoid/interceptable_spec_models.rb +76 -0
  665. data/spec/mongoid/loggable_spec.rb +2 -0
  666. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  667. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +239 -0
  668. data/spec/mongoid/matcher/extract_attribute_spec.rb +40 -0
  669. data/spec/mongoid/persistable/creatable_spec.rb +119 -29
  670. data/spec/mongoid/persistable/deletable_spec.rb +307 -11
  671. data/spec/mongoid/persistable/destroyable_spec.rb +225 -12
  672. data/spec/mongoid/persistable/incrementable_spec.rb +29 -13
  673. data/spec/mongoid/persistable/logical_spec.rb +19 -3
  674. data/spec/mongoid/persistable/poppable_spec.rb +19 -3
  675. data/spec/mongoid/persistable/pullable_spec.rb +36 -6
  676. data/spec/mongoid/persistable/pushable_spec.rb +91 -7
  677. data/spec/mongoid/persistable/renamable_spec.rb +18 -2
  678. data/spec/mongoid/persistable/savable_spec.rb +218 -50
  679. data/spec/mongoid/persistable/settable_spec.rb +213 -32
  680. data/spec/mongoid/persistable/unsettable_spec.rb +19 -3
  681. data/spec/mongoid/persistable/updatable_spec.rb +222 -21
  682. data/spec/mongoid/persistable/upsertable_spec.rb +4 -2
  683. data/spec/mongoid/persistable_spec.rb +116 -25
  684. data/spec/mongoid/persistence_context_spec.rb +696 -0
  685. data/spec/mongoid/positional_spec.rb +3 -1
  686. data/spec/mongoid/query_cache_middleware_spec.rb +68 -0
  687. data/spec/mongoid/query_cache_spec.rb +647 -45
  688. data/spec/mongoid/relations/proxy_spec.rb +126 -98
  689. data/spec/mongoid/reloadable_spec.rb +346 -17
  690. data/spec/mongoid/scopable_spec.rb +82 -22
  691. data/spec/mongoid/selectable_spec.rb +8 -6
  692. data/spec/mongoid/serializable_spec.rb +160 -79
  693. data/spec/mongoid/shardable_models.rb +61 -0
  694. data/spec/mongoid/shardable_spec.rb +145 -26
  695. data/spec/mongoid/stateful_spec.rb +3 -1
  696. data/spec/mongoid/tasks/database_rake_spec.rb +15 -13
  697. data/spec/mongoid/tasks/database_spec.rb +3 -1
  698. data/spec/mongoid/threaded_spec.rb +72 -2
  699. data/spec/mongoid/timestamps/created/short_spec.rb +3 -1
  700. data/spec/mongoid/timestamps/created_spec.rb +3 -1
  701. data/spec/mongoid/timestamps/timeless_spec.rb +4 -2
  702. data/spec/mongoid/timestamps/updated/short_spec.rb +5 -3
  703. data/spec/mongoid/timestamps/updated_spec.rb +5 -3
  704. data/spec/mongoid/timestamps_spec.rb +8 -6
  705. data/spec/mongoid/touchable_spec.rb +588 -0
  706. data/spec/mongoid/touchable_spec_models.rb +53 -0
  707. data/spec/mongoid/traversable_spec.rb +1167 -1
  708. data/spec/mongoid/validatable/associated_spec.rb +3 -1
  709. data/spec/mongoid/validatable/format_spec.rb +2 -0
  710. data/spec/mongoid/validatable/length_spec.rb +2 -0
  711. data/spec/mongoid/validatable/numericality_spec.rb +2 -0
  712. data/spec/mongoid/validatable/presence_spec.rb +33 -26
  713. data/spec/mongoid/validatable/uniqueness_spec.rb +119 -81
  714. data/spec/mongoid/validatable_spec.rb +21 -3
  715. data/spec/mongoid_spec.rb +2 -0
  716. data/spec/rails/controller_extension/controller_runtime_spec.rb +112 -0
  717. data/spec/rails/mongoid_spec.rb +4 -2
  718. data/spec/shared/LICENSE +20 -0
  719. data/spec/shared/bin/get-mongodb-download-url +17 -0
  720. data/spec/shared/bin/s3-copy +45 -0
  721. data/spec/shared/bin/s3-upload +69 -0
  722. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  723. data/spec/shared/lib/mrss/cluster_config.rb +231 -0
  724. data/spec/shared/lib/mrss/constraints.rb +386 -0
  725. data/spec/shared/lib/mrss/docker_runner.rb +271 -0
  726. data/spec/shared/lib/mrss/event_subscriber.rb +200 -0
  727. data/spec/shared/lib/mrss/lite_constraints.rb +199 -0
  728. data/spec/shared/lib/mrss/server_version_registry.rb +120 -0
  729. data/spec/shared/lib/mrss/session_registry.rb +69 -0
  730. data/spec/shared/lib/mrss/session_registry_legacy.rb +60 -0
  731. data/spec/shared/lib/mrss/spec_organizer.rb +179 -0
  732. data/spec/shared/lib/mrss/utils.rb +15 -0
  733. data/spec/shared/share/Dockerfile.erb +339 -0
  734. data/spec/shared/share/haproxy-1.conf +16 -0
  735. data/spec/shared/share/haproxy-2.conf +17 -0
  736. data/spec/shared/shlib/distro.sh +74 -0
  737. data/spec/shared/shlib/server.sh +379 -0
  738. data/spec/shared/shlib/set_env.sh +132 -0
  739. data/spec/spec_helper.rb +133 -53
  740. data/spec/support/authorization.rb +2 -0
  741. data/spec/support/client_registry.rb +9 -0
  742. data/spec/support/constraints.rb +53 -0
  743. data/spec/support/expectations.rb +21 -3
  744. data/spec/support/helpers.rb +11 -0
  745. data/spec/support/macros.rb +42 -0
  746. data/spec/support/models/account.rb +38 -0
  747. data/spec/support/models/acolyte.rb +19 -0
  748. data/spec/support/models/actor.rb +20 -0
  749. data/spec/support/models/actress.rb +4 -0
  750. data/spec/support/models/address.rb +85 -0
  751. data/spec/support/models/address_component.rb +7 -0
  752. data/spec/support/models/address_number.rb +8 -0
  753. data/spec/support/models/agency.rb +7 -0
  754. data/spec/support/models/agent.rb +18 -0
  755. data/spec/support/models/album.rb +20 -0
  756. data/spec/support/models/alert.rb +9 -0
  757. data/spec/support/models/animal.rb +28 -0
  758. data/spec/support/models/answer.rb +8 -0
  759. data/spec/support/models/appointment.rb +9 -0
  760. data/spec/support/models/armrest.rb +9 -0
  761. data/spec/support/models/array_field.rb +7 -0
  762. data/spec/support/models/article.rb +14 -0
  763. data/spec/support/models/artist.rb +91 -0
  764. data/spec/support/models/artwork.rb +6 -0
  765. data/spec/support/models/audible_sound.rb +3 -0
  766. data/spec/support/models/audio.rb +7 -0
  767. data/spec/support/models/augmentation.rb +13 -0
  768. data/spec/support/models/author.rb +8 -0
  769. data/spec/support/models/baby.rb +6 -0
  770. data/spec/support/models/band.rb +37 -0
  771. data/spec/support/models/bar.rb +12 -0
  772. data/spec/support/models/basic.rb +8 -0
  773. data/spec/support/models/bed.rb +3 -0
  774. data/spec/support/models/big_palette.rb +4 -0
  775. data/spec/support/models/birthday.rb +15 -0
  776. data/spec/support/models/bolt.rb +7 -0
  777. data/spec/support/models/bomb.rb +6 -0
  778. data/spec/support/models/book.rb +18 -0
  779. data/spec/support/models/breed.rb +6 -0
  780. data/spec/support/models/browser.rb +8 -0
  781. data/spec/support/models/building.rb +8 -0
  782. data/spec/support/models/building_address.rb +9 -0
  783. data/spec/support/models/bus.rb +9 -0
  784. data/spec/support/models/business.rb +7 -0
  785. data/spec/support/models/callback_test.rb +11 -0
  786. data/spec/support/models/canvas.rb +27 -0
  787. data/spec/support/models/car.rb +3 -0
  788. data/spec/support/models/cat.rb +10 -0
  789. data/spec/support/models/category.rb +10 -0
  790. data/spec/support/models/child.rb +6 -0
  791. data/spec/support/models/child_doc.rb +24 -0
  792. data/spec/support/models/church.rb +8 -0
  793. data/spec/support/models/circle.rb +5 -0
  794. data/spec/support/models/circuit.rb +6 -0
  795. data/spec/support/models/circus.rb +9 -0
  796. data/spec/support/models/code.rb +13 -0
  797. data/spec/support/models/coding/pull_request.rb +11 -0
  798. data/spec/support/models/coding.rb +3 -0
  799. data/spec/support/models/comment.rb +18 -0
  800. data/spec/support/models/company.rb +7 -0
  801. data/spec/support/models/consumption_period.rb +9 -0
  802. data/spec/support/models/contextable_item.rb +7 -0
  803. data/spec/support/models/contractor.rb +7 -0
  804. data/spec/support/models/cookie.rb +8 -0
  805. data/spec/support/models/country_code.rb +12 -0
  806. data/spec/support/models/courier_job.rb +6 -0
  807. data/spec/support/models/crate.rb +12 -0
  808. data/spec/support/models/customer.rb +10 -0
  809. data/spec/support/models/customer_address.rb +11 -0
  810. data/spec/support/models/deed.rb +7 -0
  811. data/spec/support/models/definition.rb +11 -0
  812. data/spec/support/models/delegating_patient.rb +15 -0
  813. data/spec/support/models/description.rb +13 -0
  814. data/spec/support/models/dictionary.rb +18 -0
  815. data/spec/support/models/division.rb +12 -0
  816. data/spec/support/models/doctor.rb +14 -0
  817. data/spec/support/models/dog.rb +9 -0
  818. data/spec/support/models/dokument.rb +8 -0
  819. data/spec/support/models/draft.rb +11 -0
  820. data/spec/support/models/dragon.rb +6 -0
  821. data/spec/support/models/driver.rb +9 -0
  822. data/spec/support/models/drug.rb +8 -0
  823. data/spec/support/models/dungeon.rb +6 -0
  824. data/spec/support/models/edit.rb +7 -0
  825. data/spec/support/models/email.rb +8 -0
  826. data/spec/support/models/employer.rb +7 -0
  827. data/spec/support/models/entry.rb +8 -0
  828. data/spec/support/models/eraser.rb +3 -0
  829. data/spec/support/models/even.rb +9 -0
  830. data/spec/support/models/event.rb +24 -0
  831. data/spec/support/models/exhibition.rb +6 -0
  832. data/spec/support/models/exhibitor.rb +8 -0
  833. data/spec/support/models/explosion.rb +6 -0
  834. data/spec/support/models/eye.rb +11 -0
  835. data/spec/support/models/eye_bowl.rb +11 -0
  836. data/spec/support/models/face.rb +10 -0
  837. data/spec/support/models/favorite.rb +8 -0
  838. data/spec/support/models/filesystem.rb +7 -0
  839. data/spec/support/models/fire_hydrant.rb +8 -0
  840. data/spec/support/models/firefox.rb +6 -0
  841. data/spec/support/models/fish.rb +9 -0
  842. data/spec/support/models/folder.rb +9 -0
  843. data/spec/support/models/folder_item.rb +11 -0
  844. data/spec/support/models/fruits.rb +36 -0
  845. data/spec/support/models/game.rb +21 -0
  846. data/spec/support/models/ghost.rb +9 -0
  847. data/spec/support/models/guitar.rb +4 -0
  848. data/spec/support/models/hole.rb +12 -0
  849. data/spec/support/models/home.rb +6 -0
  850. data/spec/support/models/house.rb +8 -0
  851. data/spec/support/models/html_writer.rb +5 -0
  852. data/spec/support/models/id_key.rb +8 -0
  853. data/spec/support/models/idnodef.rb +7 -0
  854. data/spec/support/models/image.rb +24 -0
  855. data/spec/support/models/implant.rb +18 -0
  856. data/spec/support/models/instrument.rb +8 -0
  857. data/spec/support/models/item.rb +10 -0
  858. data/spec/support/models/jar.rb +9 -0
  859. data/spec/support/models/kaleidoscope.rb +8 -0
  860. data/spec/support/models/kangaroo.rb +6 -0
  861. data/spec/support/models/label.rb +50 -0
  862. data/spec/support/models/language.rb +7 -0
  863. data/spec/support/models/lat_lng.rb +17 -0
  864. data/spec/support/models/league.rb +13 -0
  865. data/spec/support/models/learner.rb +4 -0
  866. data/spec/support/models/line_item.rb +8 -0
  867. data/spec/support/models/location.rb +10 -0
  868. data/spec/support/models/login.rb +10 -0
  869. data/spec/support/models/manufacturer.rb +9 -0
  870. data/spec/support/models/meat.rb +6 -0
  871. data/spec/support/models/membership.rb +6 -0
  872. data/spec/support/models/message.rb +13 -0
  873. data/spec/support/models/minim.rb +6 -0
  874. data/spec/support/models/mixed_drink.rb +6 -0
  875. data/spec/support/models/mop.rb +24 -0
  876. data/spec/support/models/movie.rb +15 -0
  877. data/spec/support/models/my_hash.rb +4 -0
  878. data/spec/support/models/name.rb +26 -0
  879. data/spec/support/models/name_only.rb +8 -0
  880. data/spec/support/models/node.rb +7 -0
  881. data/spec/support/models/note.rb +19 -0
  882. data/spec/support/models/nut.rb +7 -0
  883. data/spec/support/models/odd.rb +9 -0
  884. data/spec/support/models/order.rb +12 -0
  885. data/spec/support/models/ordered_post.rb +13 -0
  886. data/spec/support/models/ordered_preference.rb +8 -0
  887. data/spec/support/models/oscar.rb +16 -0
  888. data/spec/support/models/other_owner_object.rb +4 -0
  889. data/spec/support/models/override.rb +18 -0
  890. data/spec/support/models/ownable.rb +8 -0
  891. data/spec/support/models/owner.rb +10 -0
  892. data/spec/support/models/pack.rb +5 -0
  893. data/spec/support/models/page.rb +18 -0
  894. data/spec/support/models/page_question.rb +6 -0
  895. data/spec/support/models/palette.rb +9 -0
  896. data/spec/support/models/parent.rb +7 -0
  897. data/spec/support/models/parent_doc.rb +8 -0
  898. data/spec/support/models/passport.rb +13 -0
  899. data/spec/support/models/patient.rb +11 -0
  900. data/spec/support/models/pdf_writer.rb +5 -0
  901. data/spec/support/models/pencil.rb +3 -0
  902. data/spec/support/models/person.rb +230 -0
  903. data/spec/support/models/pet.rb +25 -0
  904. data/spec/support/models/pet_owner.rb +8 -0
  905. data/spec/support/models/phone.rb +13 -0
  906. data/spec/support/models/piano.rb +4 -0
  907. data/spec/support/models/pizza.rb +9 -0
  908. data/spec/support/models/player.rb +37 -0
  909. data/spec/support/models/post.rb +52 -0
  910. data/spec/support/models/post_genre.rb +8 -0
  911. data/spec/support/models/powerup.rb +13 -0
  912. data/spec/support/models/preference.rb +11 -0
  913. data/spec/support/models/princess.rb +12 -0
  914. data/spec/support/models/product.rb +19 -0
  915. data/spec/support/models/profile.rb +17 -0
  916. data/spec/support/models/pronunciation.rb +7 -0
  917. data/spec/support/models/pub.rb +8 -0
  918. data/spec/support/models/publication/encyclopedia.rb +11 -0
  919. data/spec/support/models/publication/review.rb +13 -0
  920. data/spec/support/models/publication.rb +4 -0
  921. data/spec/support/models/purchase.rb +6 -0
  922. data/spec/support/models/purchased_item.rb +10 -0
  923. data/spec/support/models/question.rb +10 -0
  924. data/spec/support/models/quiz.rb +9 -0
  925. data/spec/support/models/rating.rb +10 -0
  926. data/spec/support/models/record.rb +54 -0
  927. data/spec/support/models/registry.rb +6 -0
  928. data/spec/support/models/role.rb +9 -0
  929. data/spec/support/models/root_category.rb +6 -0
  930. data/spec/support/models/sandwich.rb +11 -0
  931. data/spec/support/models/scheduler.rb +9 -0
  932. data/spec/support/models/scribe.rb +7 -0
  933. data/spec/support/models/sealer.rb +7 -0
  934. data/spec/support/models/seat.rb +24 -0
  935. data/spec/support/models/seo.rb +9 -0
  936. data/spec/support/models/series.rb +7 -0
  937. data/spec/support/models/server.rb +15 -0
  938. data/spec/support/models/service.rb +24 -0
  939. data/spec/support/models/shape.rb +14 -0
  940. data/spec/support/models/shelf.rb +7 -0
  941. data/spec/support/models/shipment_address.rb +5 -0
  942. data/spec/support/models/shipping_container.rb +7 -0
  943. data/spec/support/models/shipping_pack.rb +5 -0
  944. data/spec/support/models/shirt.rb +11 -0
  945. data/spec/support/models/shop.rb +8 -0
  946. data/spec/support/models/short_agent.rb +6 -0
  947. data/spec/support/models/short_quiz.rb +7 -0
  948. data/spec/support/models/simple.rb +7 -0
  949. data/spec/support/models/slave.rb +8 -0
  950. data/spec/support/models/song.rb +10 -0
  951. data/spec/support/models/sound.rb +7 -0
  952. data/spec/support/models/spacer.rb +7 -0
  953. data/spec/support/models/square.rb +6 -0
  954. data/spec/support/models/staff.rb +9 -0
  955. data/spec/support/models/store_as_dup_test1.rb +7 -0
  956. data/spec/support/models/store_as_dup_test2.rb +7 -0
  957. data/spec/support/models/store_as_dup_test3.rb +7 -0
  958. data/spec/support/models/store_as_dup_test4.rb +7 -0
  959. data/spec/support/models/strategy.rb +5 -0
  960. data/spec/support/models/sub_item.rb +5 -0
  961. data/spec/support/models/subscription.rb +7 -0
  962. data/spec/support/models/survey.rb +7 -0
  963. data/spec/support/models/symptom.rb +8 -0
  964. data/spec/support/models/system_role.rb +7 -0
  965. data/spec/support/models/tag.rb +10 -0
  966. data/spec/support/models/target.rb +7 -0
  967. data/spec/support/models/template.rb +7 -0
  968. data/spec/support/models/thing.rb +11 -0
  969. data/spec/support/models/threadlocker.rb +7 -0
  970. data/spec/support/models/title.rb +5 -0
  971. data/spec/support/models/tool.rb +10 -0
  972. data/spec/support/models/topping.rb +7 -0
  973. data/spec/support/models/toy.rb +9 -0
  974. data/spec/support/models/track.rb +40 -0
  975. data/spec/support/models/translation.rb +7 -0
  976. data/spec/support/models/tree.rb +11 -0
  977. data/spec/support/models/truck.rb +7 -0
  978. data/spec/support/models/updatable.rb +7 -0
  979. data/spec/support/models/user.rb +23 -0
  980. data/spec/support/models/user_account.rb +12 -0
  981. data/spec/support/models/validation_callback.rb +12 -0
  982. data/spec/support/models/vehicle.rb +18 -0
  983. data/spec/support/models/version.rb +7 -0
  984. data/spec/support/models/vertex.rb +8 -0
  985. data/spec/support/models/vet_visit.rb +7 -0
  986. data/spec/support/models/video.rb +15 -0
  987. data/spec/support/models/video_game.rb +3 -0
  988. data/spec/support/models/washer.rb +7 -0
  989. data/spec/support/models/weapon.rb +13 -0
  990. data/spec/support/models/wiki_page.rb +17 -0
  991. data/spec/support/models/word.rb +17 -0
  992. data/spec/support/models/word_origin.rb +13 -0
  993. data/spec/support/models/writer.rb +13 -0
  994. data/spec/support/shared/time.rb +53 -0
  995. data/spec/support/spec_config.rb +60 -0
  996. data.tar.gz.sig +0 -0
  997. metadata +1347 -813
  998. metadata.gz.sig +0 -0
  999. data/lib/mongoid/clients/thread_options.rb +0 -19
  1000. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  1001. data/lib/mongoid/matchable/all.rb +0 -27
  1002. data/lib/mongoid/matchable/and.rb +0 -30
  1003. data/lib/mongoid/matchable/default.rb +0 -72
  1004. data/lib/mongoid/matchable/exists.rb +0 -23
  1005. data/lib/mongoid/matchable/gt.rb +0 -21
  1006. data/lib/mongoid/matchable/gte.rb +0 -21
  1007. data/lib/mongoid/matchable/in.rb +0 -24
  1008. data/lib/mongoid/matchable/lt.rb +0 -21
  1009. data/lib/mongoid/matchable/lte.rb +0 -21
  1010. data/lib/mongoid/matchable/ne.rb +0 -21
  1011. data/lib/mongoid/matchable/nin.rb +0 -22
  1012. data/lib/mongoid/matchable/or.rb +0 -33
  1013. data/lib/mongoid/matchable/regexp.rb +0 -27
  1014. data/lib/mongoid/matchable/size.rb +0 -21
  1015. data/lib/mongoid/railties/document.rb +0 -12
  1016. data/lib/mongoid/relations/accessors.rb +0 -264
  1017. data/lib/mongoid/relations/auto_save.rb +0 -86
  1018. data/lib/mongoid/relations/binding.rb +0 -218
  1019. data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
  1020. data/lib/mongoid/relations/bindings/embedded/many.rb +0 -43
  1021. data/lib/mongoid/relations/bindings/embedded/one.rb +0 -45
  1022. data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
  1023. data/lib/mongoid/relations/bindings/referenced/many.rb +0 -38
  1024. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
  1025. data/lib/mongoid/relations/bindings/referenced/one.rb +0 -44
  1026. data/lib/mongoid/relations/bindings.rb +0 -9
  1027. data/lib/mongoid/relations/builder.rb +0 -57
  1028. data/lib/mongoid/relations/builders/embedded/in.rb +0 -29
  1029. data/lib/mongoid/relations/builders/embedded/many.rb +0 -36
  1030. data/lib/mongoid/relations/builders/embedded/one.rb +0 -30
  1031. data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
  1032. data/lib/mongoid/relations/builders/nested_attributes/one.rb +0 -126
  1033. data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
  1034. data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
  1035. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
  1036. data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
  1037. data/lib/mongoid/relations/builders.rb +0 -106
  1038. data/lib/mongoid/relations/cascading/delete.rb +0 -44
  1039. data/lib/mongoid/relations/cascading/destroy.rb +0 -43
  1040. data/lib/mongoid/relations/cascading/nullify.rb +0 -35
  1041. data/lib/mongoid/relations/cascading/restrict.rb +0 -39
  1042. data/lib/mongoid/relations/cascading.rb +0 -56
  1043. data/lib/mongoid/relations/constraint.rb +0 -55
  1044. data/lib/mongoid/relations/conversions.rb +0 -34
  1045. data/lib/mongoid/relations/counter_cache.rb +0 -150
  1046. data/lib/mongoid/relations/cyclic.rb +0 -107
  1047. data/lib/mongoid/relations/eager/base.rb +0 -153
  1048. data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
  1049. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
  1050. data/lib/mongoid/relations/eager/has_many.rb +0 -38
  1051. data/lib/mongoid/relations/eager/has_one.rb +0 -30
  1052. data/lib/mongoid/relations/eager.rb +0 -41
  1053. data/lib/mongoid/relations/embedded/batchable.rb +0 -382
  1054. data/lib/mongoid/relations/embedded/in.rb +0 -229
  1055. data/lib/mongoid/relations/embedded/many.rb +0 -642
  1056. data/lib/mongoid/relations/embedded/one.rb +0 -222
  1057. data/lib/mongoid/relations/macros.rb +0 -359
  1058. data/lib/mongoid/relations/many.rb +0 -238
  1059. data/lib/mongoid/relations/marshalable.rb +0 -32
  1060. data/lib/mongoid/relations/metadata.rb +0 -1179
  1061. data/lib/mongoid/relations/nested_builder.rb +0 -74
  1062. data/lib/mongoid/relations/one.rb +0 -60
  1063. data/lib/mongoid/relations/options.rb +0 -49
  1064. data/lib/mongoid/relations/polymorphic.rb +0 -39
  1065. data/lib/mongoid/relations/proxy.rb +0 -245
  1066. data/lib/mongoid/relations/referenced/in.rb +0 -295
  1067. data/lib/mongoid/relations/referenced/many.rb +0 -808
  1068. data/lib/mongoid/relations/referenced/many_to_many.rb +0 -472
  1069. data/lib/mongoid/relations/referenced/one.rb +0 -276
  1070. data/lib/mongoid/relations/reflections.rb +0 -64
  1071. data/lib/mongoid/relations/synchronization.rb +0 -169
  1072. data/lib/mongoid/relations/targets/enumerable.rb +0 -473
  1073. data/lib/mongoid/relations/targets.rb +0 -2
  1074. data/lib/mongoid/relations/touchable.rb +0 -94
  1075. data/lib/mongoid/relations.rb +0 -148
  1076. data/lib/support/ruby_version.rb +0 -26
  1077. data/spec/app/models/account.rb +0 -36
  1078. data/spec/app/models/acolyte.rb +0 -17
  1079. data/spec/app/models/actor.rb +0 -18
  1080. data/spec/app/models/actress.rb +0 -2
  1081. data/spec/app/models/address.rb +0 -79
  1082. data/spec/app/models/address_component.rb +0 -5
  1083. data/spec/app/models/address_number.rb +0 -6
  1084. data/spec/app/models/agency.rb +0 -5
  1085. data/spec/app/models/agent.rb +0 -14
  1086. data/spec/app/models/album.rb +0 -14
  1087. data/spec/app/models/alert.rb +0 -7
  1088. data/spec/app/models/animal.rb +0 -25
  1089. data/spec/app/models/answer.rb +0 -6
  1090. data/spec/app/models/appointment.rb +0 -7
  1091. data/spec/app/models/article.rb +0 -12
  1092. data/spec/app/models/artist.rb +0 -66
  1093. data/spec/app/models/artwork.rb +0 -4
  1094. data/spec/app/models/audio.rb +0 -5
  1095. data/spec/app/models/augmentation.rb +0 -11
  1096. data/spec/app/models/author.rb +0 -6
  1097. data/spec/app/models/baby.rb +0 -4
  1098. data/spec/app/models/band.rb +0 -28
  1099. data/spec/app/models/bar.rb +0 -10
  1100. data/spec/app/models/basic.rb +0 -6
  1101. data/spec/app/models/bed.rb +0 -1
  1102. data/spec/app/models/big_palette.rb +0 -2
  1103. data/spec/app/models/birthday.rb +0 -13
  1104. data/spec/app/models/bomb.rb +0 -4
  1105. data/spec/app/models/book.rb +0 -15
  1106. data/spec/app/models/breed.rb +0 -4
  1107. data/spec/app/models/browser.rb +0 -6
  1108. data/spec/app/models/building.rb +0 -6
  1109. data/spec/app/models/building_address.rb +0 -7
  1110. data/spec/app/models/bus.rb +0 -7
  1111. data/spec/app/models/business.rb +0 -5
  1112. data/spec/app/models/callback_test.rb +0 -9
  1113. data/spec/app/models/canvas.rb +0 -25
  1114. data/spec/app/models/car.rb +0 -1
  1115. data/spec/app/models/cat.rb +0 -8
  1116. data/spec/app/models/category.rb +0 -8
  1117. data/spec/app/models/child.rb +0 -4
  1118. data/spec/app/models/child_doc.rb +0 -22
  1119. data/spec/app/models/church.rb +0 -6
  1120. data/spec/app/models/circle.rb +0 -3
  1121. data/spec/app/models/circuit.rb +0 -4
  1122. data/spec/app/models/circus.rb +0 -7
  1123. data/spec/app/models/code.rb +0 -11
  1124. data/spec/app/models/comment.rb +0 -16
  1125. data/spec/app/models/company.rb +0 -5
  1126. data/spec/app/models/consumption_period.rb +0 -7
  1127. data/spec/app/models/contextable_item.rb +0 -5
  1128. data/spec/app/models/contractor.rb +0 -5
  1129. data/spec/app/models/cookie.rb +0 -6
  1130. data/spec/app/models/country_code.rb +0 -8
  1131. data/spec/app/models/courier_job.rb +0 -4
  1132. data/spec/app/models/definition.rb +0 -9
  1133. data/spec/app/models/description.rb +0 -11
  1134. data/spec/app/models/dictionary.rb +0 -10
  1135. data/spec/app/models/division.rb +0 -10
  1136. data/spec/app/models/doctor.rb +0 -12
  1137. data/spec/app/models/dog.rb +0 -7
  1138. data/spec/app/models/dokument.rb +0 -5
  1139. data/spec/app/models/draft.rb +0 -9
  1140. data/spec/app/models/dragon.rb +0 -4
  1141. data/spec/app/models/driver.rb +0 -7
  1142. data/spec/app/models/drug.rb +0 -6
  1143. data/spec/app/models/dungeon.rb +0 -4
  1144. data/spec/app/models/edit.rb +0 -5
  1145. data/spec/app/models/email.rb +0 -6
  1146. data/spec/app/models/employer.rb +0 -5
  1147. data/spec/app/models/entry.rb +0 -6
  1148. data/spec/app/models/eraser.rb +0 -1
  1149. data/spec/app/models/even.rb +0 -7
  1150. data/spec/app/models/event.rb +0 -22
  1151. data/spec/app/models/exhibition.rb +0 -4
  1152. data/spec/app/models/exhibitor.rb +0 -6
  1153. data/spec/app/models/explosion.rb +0 -4
  1154. data/spec/app/models/eye.rb +0 -9
  1155. data/spec/app/models/eye_bowl.rb +0 -9
  1156. data/spec/app/models/face.rb +0 -8
  1157. data/spec/app/models/favorite.rb +0 -6
  1158. data/spec/app/models/filesystem.rb +0 -5
  1159. data/spec/app/models/fire_hydrant.rb +0 -6
  1160. data/spec/app/models/firefox.rb +0 -4
  1161. data/spec/app/models/fish.rb +0 -7
  1162. data/spec/app/models/folder.rb +0 -7
  1163. data/spec/app/models/folder_item.rb +0 -9
  1164. data/spec/app/models/fruits.rb +0 -34
  1165. data/spec/app/models/game.rb +0 -19
  1166. data/spec/app/models/ghost.rb +0 -7
  1167. data/spec/app/models/home.rb +0 -4
  1168. data/spec/app/models/house.rb +0 -6
  1169. data/spec/app/models/html_writer.rb +0 -3
  1170. data/spec/app/models/id_key.rb +0 -6
  1171. data/spec/app/models/image.rb +0 -22
  1172. data/spec/app/models/implant.rb +0 -16
  1173. data/spec/app/models/item.rb +0 -8
  1174. data/spec/app/models/jar.rb +0 -7
  1175. data/spec/app/models/kaleidoscope.rb +0 -6
  1176. data/spec/app/models/kangaroo.rb +0 -4
  1177. data/spec/app/models/label.rb +0 -47
  1178. data/spec/app/models/language.rb +0 -5
  1179. data/spec/app/models/lat_lng.rb +0 -15
  1180. data/spec/app/models/league.rb +0 -11
  1181. data/spec/app/models/learner.rb +0 -2
  1182. data/spec/app/models/line_item.rb +0 -6
  1183. data/spec/app/models/location.rb +0 -8
  1184. data/spec/app/models/login.rb +0 -8
  1185. data/spec/app/models/manufacturer.rb +0 -7
  1186. data/spec/app/models/meat.rb +0 -4
  1187. data/spec/app/models/membership.rb +0 -4
  1188. data/spec/app/models/message.rb +0 -11
  1189. data/spec/app/models/mixed_drink.rb +0 -4
  1190. data/spec/app/models/movie.rb +0 -13
  1191. data/spec/app/models/my_hash.rb +0 -2
  1192. data/spec/app/models/name.rb +0 -24
  1193. data/spec/app/models/node.rb +0 -5
  1194. data/spec/app/models/note.rb +0 -17
  1195. data/spec/app/models/odd.rb +0 -7
  1196. data/spec/app/models/ordered_post.rb +0 -6
  1197. data/spec/app/models/ordered_preference.rb +0 -6
  1198. data/spec/app/models/oscar.rb +0 -15
  1199. data/spec/app/models/override.rb +0 -16
  1200. data/spec/app/models/ownable.rb +0 -6
  1201. data/spec/app/models/owner.rb +0 -6
  1202. data/spec/app/models/pack.rb +0 -3
  1203. data/spec/app/models/page.rb +0 -16
  1204. data/spec/app/models/page_question.rb +0 -4
  1205. data/spec/app/models/palette.rb +0 -7
  1206. data/spec/app/models/parent.rb +0 -5
  1207. data/spec/app/models/parent_doc.rb +0 -6
  1208. data/spec/app/models/passport.rb +0 -5
  1209. data/spec/app/models/patient.rb +0 -9
  1210. data/spec/app/models/pdf_writer.rb +0 -3
  1211. data/spec/app/models/pencil.rb +0 -1
  1212. data/spec/app/models/person.rb +0 -207
  1213. data/spec/app/models/pet.rb +0 -23
  1214. data/spec/app/models/pet_owner.rb +0 -6
  1215. data/spec/app/models/phone.rb +0 -9
  1216. data/spec/app/models/pizza.rb +0 -7
  1217. data/spec/app/models/player.rb +0 -35
  1218. data/spec/app/models/post.rb +0 -50
  1219. data/spec/app/models/post_genre.rb +0 -6
  1220. data/spec/app/models/powerup.rb +0 -11
  1221. data/spec/app/models/preference.rb +0 -9
  1222. data/spec/app/models/princess.rb +0 -8
  1223. data/spec/app/models/product.rb +0 -17
  1224. data/spec/app/models/profile.rb +0 -5
  1225. data/spec/app/models/pronunciation.rb +0 -5
  1226. data/spec/app/models/pub.rb +0 -6
  1227. data/spec/app/models/purchase.rb +0 -4
  1228. data/spec/app/models/question.rb +0 -8
  1229. data/spec/app/models/quiz.rb +0 -7
  1230. data/spec/app/models/rating.rb +0 -8
  1231. data/spec/app/models/record.rb +0 -51
  1232. data/spec/app/models/registry.rb +0 -4
  1233. data/spec/app/models/role.rb +0 -7
  1234. data/spec/app/models/root_category.rb +0 -4
  1235. data/spec/app/models/sandwich.rb +0 -9
  1236. data/spec/app/models/scheduler.rb +0 -7
  1237. data/spec/app/models/seo.rb +0 -7
  1238. data/spec/app/models/series.rb +0 -4
  1239. data/spec/app/models/server.rb +0 -13
  1240. data/spec/app/models/service.rb +0 -22
  1241. data/spec/app/models/shape.rb +0 -12
  1242. data/spec/app/models/shelf.rb +0 -5
  1243. data/spec/app/models/shipment_address.rb +0 -2
  1244. data/spec/app/models/shipping_container.rb +0 -5
  1245. data/spec/app/models/shipping_pack.rb +0 -3
  1246. data/spec/app/models/shop.rb +0 -6
  1247. data/spec/app/models/short_agent.rb +0 -4
  1248. data/spec/app/models/short_quiz.rb +0 -5
  1249. data/spec/app/models/simple.rb +0 -5
  1250. data/spec/app/models/slave.rb +0 -6
  1251. data/spec/app/models/song.rb +0 -8
  1252. data/spec/app/models/sound.rb +0 -5
  1253. data/spec/app/models/square.rb +0 -4
  1254. data/spec/app/models/staff.rb +0 -7
  1255. data/spec/app/models/store_as_dup_test1.rb +0 -5
  1256. data/spec/app/models/store_as_dup_test2.rb +0 -5
  1257. data/spec/app/models/strategy.rb +0 -3
  1258. data/spec/app/models/sub_item.rb +0 -3
  1259. data/spec/app/models/subscription.rb +0 -4
  1260. data/spec/app/models/survey.rb +0 -5
  1261. data/spec/app/models/symptom.rb +0 -6
  1262. data/spec/app/models/tag.rb +0 -8
  1263. data/spec/app/models/target.rb +0 -5
  1264. data/spec/app/models/template.rb +0 -5
  1265. data/spec/app/models/thing.rb +0 -9
  1266. data/spec/app/models/title.rb +0 -3
  1267. data/spec/app/models/tool.rb +0 -8
  1268. data/spec/app/models/topping.rb +0 -5
  1269. data/spec/app/models/track.rb +0 -38
  1270. data/spec/app/models/translation.rb +0 -5
  1271. data/spec/app/models/tree.rb +0 -9
  1272. data/spec/app/models/truck.rb +0 -3
  1273. data/spec/app/models/user.rb +0 -21
  1274. data/spec/app/models/user_account.rb +0 -10
  1275. data/spec/app/models/validation_callback.rb +0 -10
  1276. data/spec/app/models/vehicle.rb +0 -11
  1277. data/spec/app/models/version.rb +0 -5
  1278. data/spec/app/models/vet_visit.rb +0 -5
  1279. data/spec/app/models/video.rb +0 -13
  1280. data/spec/app/models/video_game.rb +0 -1
  1281. data/spec/app/models/weapon.rb +0 -11
  1282. data/spec/app/models/wiki_page.rb +0 -14
  1283. data/spec/app/models/word.rb +0 -15
  1284. data/spec/app/models/word_origin.rb +0 -11
  1285. data/spec/app/models/writer.rb +0 -11
  1286. data/spec/mongoid/extensions/origin/regexp_raw_spec.rb +0 -89
  1287. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
  1288. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
  1289. data/spec/mongoid/matchable/all_spec.rb +0 -31
  1290. data/spec/mongoid/matchable/and_spec.rb +0 -187
  1291. data/spec/mongoid/matchable/default_spec.rb +0 -130
  1292. data/spec/mongoid/matchable/exists_spec.rb +0 -57
  1293. data/spec/mongoid/matchable/gt_spec.rb +0 -75
  1294. data/spec/mongoid/matchable/gte_spec.rb +0 -74
  1295. data/spec/mongoid/matchable/in_spec.rb +0 -49
  1296. data/spec/mongoid/matchable/lt_spec.rb +0 -74
  1297. data/spec/mongoid/matchable/lte_spec.rb +0 -74
  1298. data/spec/mongoid/matchable/ne_spec.rb +0 -46
  1299. data/spec/mongoid/matchable/nin_spec.rb +0 -48
  1300. data/spec/mongoid/matchable/or_spec.rb +0 -131
  1301. data/spec/mongoid/matchable/regexp_spec.rb +0 -59
  1302. data/spec/mongoid/matchable/size_spec.rb +0 -25
  1303. data/spec/mongoid/matchable_spec.rb +0 -708
  1304. data/spec/mongoid/railties/document_spec.rb +0 -24
  1305. data/spec/mongoid/relations/accessors_spec.rb +0 -821
  1306. data/spec/mongoid/relations/auto_save_spec.rb +0 -281
  1307. data/spec/mongoid/relations/bindings/embedded/in_spec.rb +0 -171
  1308. data/spec/mongoid/relations/bindings/embedded/many_spec.rb +0 -54
  1309. data/spec/mongoid/relations/bindings/embedded/one_spec.rb +0 -77
  1310. data/spec/mongoid/relations/bindings/referenced/in_spec.rb +0 -241
  1311. data/spec/mongoid/relations/bindings/referenced/many_spec.rb +0 -153
  1312. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +0 -178
  1313. data/spec/mongoid/relations/bindings/referenced/one_spec.rb +0 -131
  1314. data/spec/mongoid/relations/builders/embedded/in_spec.rb +0 -34
  1315. data/spec/mongoid/relations/builders/embedded/many_spec.rb +0 -132
  1316. data/spec/mongoid/relations/builders/embedded/one_spec.rb +0 -99
  1317. data/spec/mongoid/relations/builders/nested_attributes/many_spec.rb +0 -233
  1318. data/spec/mongoid/relations/builders/nested_attributes/one_spec.rb +0 -250
  1319. data/spec/mongoid/relations/builders/referenced/in_spec.rb +0 -230
  1320. data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
  1321. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
  1322. data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
  1323. data/spec/mongoid/relations/builders_spec.rb +0 -226
  1324. data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
  1325. data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
  1326. data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
  1327. data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
  1328. data/spec/mongoid/relations/cascading_spec.rb +0 -355
  1329. data/spec/mongoid/relations/constraint_spec.rb +0 -75
  1330. data/spec/mongoid/relations/conversions_spec.rb +0 -128
  1331. data/spec/mongoid/relations/counter_cache_spec.rb +0 -389
  1332. data/spec/mongoid/relations/cyclic_spec.rb +0 -178
  1333. data/spec/mongoid/relations/eager/belongs_to_spec.rb +0 -163
  1334. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +0 -117
  1335. data/spec/mongoid/relations/eager/has_many_spec.rb +0 -244
  1336. data/spec/mongoid/relations/eager/has_one_spec.rb +0 -163
  1337. data/spec/mongoid/relations/eager_spec.rb +0 -239
  1338. data/spec/mongoid/relations/embedded/dirty_spec.rb +0 -65
  1339. data/spec/mongoid/relations/embedded/in_spec.rb +0 -579
  1340. data/spec/mongoid/relations/embedded/many_spec.rb +0 -4166
  1341. data/spec/mongoid/relations/embedded/one_spec.rb +0 -1067
  1342. data/spec/mongoid/relations/macros_spec.rb +0 -631
  1343. data/spec/mongoid/relations/metadata_spec.rb +0 -1971
  1344. data/spec/mongoid/relations/options_spec.rb +0 -35
  1345. data/spec/mongoid/relations/polymorphic_spec.rb +0 -128
  1346. data/spec/mongoid/relations/referenced/in_spec.rb +0 -1326
  1347. data/spec/mongoid/relations/referenced/many_spec.rb +0 -3806
  1348. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +0 -3589
  1349. data/spec/mongoid/relations/referenced/one_spec.rb +0 -1240
  1350. data/spec/mongoid/relations/reflections_spec.rb +0 -101
  1351. data/spec/mongoid/relations/synchronization_spec.rb +0 -449
  1352. data/spec/mongoid/relations/targets/enumerable_spec.rb +0 -1717
  1353. data/spec/mongoid/relations/touchable_spec.rb +0 -362
  1354. data/spec/mongoid/relations_spec.rb +0 -189
@@ -0,0 +1,2069 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "spec_helper"
4
+
5
+ describe Mongoid::Criteria::Queryable::Selectable do
6
+
7
+ let(:query) do
8
+ Mongoid::Query.new("id" => "_id")
9
+ end
10
+
11
+ shared_examples_for 'returns a cloned query' do
12
+
13
+ it "returns a cloned query" do
14
+ expect(selection).to_not equal(query)
15
+ end
16
+ end
17
+
18
+ # Hoisting means the operator can be elided, for example
19
+ # Foo.and(a: 1) produces simply {'a' => 1}.
20
+ shared_examples_for 'a hoisting logical operation' do
21
+
22
+ let(:query) do
23
+ Mongoid::Query.new
24
+ end
25
+
26
+ context "when provided a single criterion" do
27
+
28
+ shared_examples_for 'adds the conditions to top level' do
29
+
30
+ it "adds the conditions to top level" do
31
+ expect(selection.selector).to eq(
32
+ "field" => [ 1, 2 ]
33
+ )
34
+ end
35
+
36
+ it_behaves_like 'returns a cloned query'
37
+ end
38
+
39
+ let(:selection) do
40
+ query.send(tested_method, field: [ 1, 2 ])
41
+ end
42
+
43
+ it_behaves_like 'adds the conditions to top level'
44
+
45
+ context 'when the criterion is wrapped in an array' do
46
+ let(:selection) do
47
+ query.send(tested_method, [{field: [ 1, 2 ] }])
48
+ end
49
+
50
+ it_behaves_like 'adds the conditions to top level'
51
+ end
52
+
53
+ context 'when the criterion is wrapped in a deep array with nil elements' do
54
+ let(:selection) do
55
+ query.send(tested_method, [[[{field: [ 1, 2 ] }]], [nil]])
56
+ end
57
+
58
+ it_behaves_like 'adds the conditions to top level'
59
+ end
60
+ end
61
+
62
+ context 'when argument is a Criteria' do
63
+ let(:base) do
64
+ query.where(hello: 'world')
65
+ end
66
+
67
+ let(:other) do
68
+ query.where(foo: 'bar')
69
+ end
70
+
71
+ let(:result) { base.send(tested_method, other) }
72
+
73
+ it 'combines' do
74
+ expect(result.selector).to eq(
75
+ 'hello' => 'world',
76
+ 'foo' => 'bar',
77
+ )
78
+ end
79
+ end
80
+
81
+ context "when provided a single criterion that is handled via Key" do
82
+
83
+ shared_examples_for 'adds the conditions to top level' do
84
+
85
+ it "adds the conditions to top level" do
86
+ expect(selection.selector).to eq({
87
+ "field" => {'$gt' => 3},
88
+ })
89
+ end
90
+
91
+ it_behaves_like 'returns a cloned query'
92
+ end
93
+
94
+ let(:selection) do
95
+ query.send(tested_method, :field.gt => 3)
96
+ end
97
+
98
+ it_behaves_like 'adds the conditions to top level'
99
+
100
+ context 'when the criterion is wrapped in an array' do
101
+ let(:selection) do
102
+ query.send(tested_method, [{ :field.gt => 3 }])
103
+ end
104
+
105
+ it_behaves_like 'adds the conditions to top level'
106
+ end
107
+
108
+ context 'when the criterion is wrapped in a deep array with nil elements' do
109
+ let(:selection) do
110
+ query.send(tested_method, [[[{ :field.gt => 3 }]], [nil]])
111
+ end
112
+
113
+ it_behaves_like 'adds the conditions to top level'
114
+ end
115
+
116
+ context 'when the criterion is a time' do
117
+ let(:selection) do
118
+ query.send(tested_method, :field.gte => Time.new(2020, 1, 1))
119
+ end
120
+
121
+ it 'adds the conditions' do
122
+ expect(selection.selector).to eq({
123
+ "field" => {'$gte' => Time.new(2020, 1, 1)},
124
+ })
125
+ end
126
+
127
+ it 'keeps argument type' do
128
+ selection.selector['field']['$gte'].should be_a(Time)
129
+ end
130
+ end
131
+
132
+ context 'when the criterion is a datetime' do
133
+ let(:selection) do
134
+ query.send(tested_method, :field.gte => DateTime.new(2020, 1, 1))
135
+ end
136
+
137
+ it 'adds the conditions' do
138
+ expect(selection.selector).to eq({
139
+ "field" => {'$gte' => Time.utc(2020, 1, 1)},
140
+ })
141
+ end
142
+
143
+ it 'converts argument to a time' do
144
+ selection.selector['field']['$gte'].should be_a(Time)
145
+ end
146
+ end
147
+
148
+ context 'when the criterion is a date' do
149
+ let(:selection) do
150
+ query.send(tested_method, :field.gte => Date.new(2020, 1, 1))
151
+ end
152
+
153
+ it 'adds the conditions' do
154
+ expect(selection.selector).to eq({
155
+ "field" => {'$gte' => Time.utc(2020, 1, 1)},
156
+ })
157
+ end
158
+
159
+ it 'converts argument to a time' do
160
+ selection.selector['field']['$gte'].should be_a(Time)
161
+ end
162
+ end
163
+ end
164
+
165
+ context "when provided a nested criterion" do
166
+
167
+ let(:selection) do
168
+ query.send(tested_method, :test.elem_match => { :field.in => [ 1, 2 ] })
169
+ end
170
+
171
+ it "builds the correct selector" do
172
+ expect(selection.selector).to eq({
173
+ "test" => { "$elemMatch" => { "field" => { "$in" => [ 1, 2 ] }}}
174
+ })
175
+ end
176
+
177
+ it_behaves_like 'returns a cloned query'
178
+ end
179
+
180
+ context "when chaining the criteria" do
181
+
182
+ context "when the criteria are for different fields" do
183
+
184
+ let(:selection) do
185
+ query.and(first: [ 1, 2 ]).send(tested_method, second: [ 3, 4 ])
186
+ end
187
+
188
+ it "adds the conditions to top level" do
189
+ expect(selection.selector).to eq({
190
+ "first" => [ 1, 2 ],
191
+ "second" => [ 3, 4 ],
192
+ })
193
+ end
194
+
195
+ it_behaves_like 'returns a cloned query'
196
+ end
197
+
198
+ context "when the criteria are on the same field" do
199
+
200
+ let(:selection) do
201
+ query.and(first: [ 1, 2 ]).send(tested_method, first: [ 3, 4 ])
202
+ end
203
+
204
+ it "combines via $and operator" do
205
+ expect(selection.selector).to eq({
206
+ "first" => [ 1, 2 ],
207
+ "$and" => [
208
+ { "first" => [ 3, 4 ] }
209
+ ]
210
+ })
211
+ end
212
+
213
+ it_behaves_like 'returns a cloned query'
214
+ end
215
+ end
216
+ end
217
+
218
+ # Non-hoisting means the operator is always present, for example
219
+ # Foo.or(a: 1) produces {'$or' => [{'a' => 1}]}.
220
+ shared_examples_for 'a non-hoisting logical operation' do
221
+
222
+ context 'when there is a single predicate' do
223
+ let(:query) do
224
+ Mongoid::Query.new.send(tested_method, hello: 'world')
225
+ end
226
+
227
+ it 'adds the predicate' do
228
+ expect(query.selector).to eq(expected_operator => [{'hello' => 'world'}])
229
+ end
230
+ end
231
+
232
+ context 'when the single predicate is wrapped in an array' do
233
+ let(:query) do
234
+ Mongoid::Query.new.send(tested_method, [{hello: 'world'}])
235
+ end
236
+
237
+ it 'adds the predicate' do
238
+ expect(query.selector).to eq(expected_operator => [{'hello' => 'world'}])
239
+ end
240
+ end
241
+
242
+ context 'when argument is a Criteria' do
243
+ let(:query) do
244
+ Mongoid::Query.new.where(hello: 'world')
245
+ end
246
+
247
+ let(:other) do
248
+ Mongoid::Query.new.where(foo: 'bar')
249
+ end
250
+
251
+ let(:result) { query.send(tested_method, other) }
252
+
253
+ it 'combines' do
254
+ # This is used for $or / $nor, the two conditions should remain
255
+ # as separate hashes
256
+ expect(result.selector).to eq(expected_operator => [{'hello' => 'world'}, {'foo' => 'bar'}])
257
+ end
258
+ end
259
+
260
+ context 'when argument is a mix of Criteria and hashes' do
261
+ let(:query) do
262
+ Mongoid::Query.new.where(hello: 'world')
263
+ end
264
+
265
+ let(:other1) do
266
+ Mongoid::Query.new.where(foo: 'bar')
267
+ end
268
+
269
+ let(:other2) do
270
+ {bar: 42}
271
+ end
272
+
273
+ let(:other3) do
274
+ Mongoid::Query.new.where(a: 2)
275
+ end
276
+
277
+ let(:result) { query.send(tested_method, other1, other2, other3) }
278
+
279
+ it 'combines' do
280
+ expect(result.selector).to eq(expected_operator => [
281
+ {'hello' => 'world'},
282
+ {'foo' => 'bar'},
283
+ {'bar' => 42},
284
+ {'a' => 2},
285
+ ])
286
+ end
287
+ end
288
+ end
289
+
290
+ describe "#and" do
291
+
292
+ let(:tested_method) { :and }
293
+ let(:expected_operator) { '$and' }
294
+
295
+ it_behaves_like 'a hoisting logical operation'
296
+
297
+ context "when provided no criterion" do
298
+
299
+ let(:selection) do
300
+ query.and
301
+ end
302
+
303
+ it "does not add any criterion" do
304
+ expect(selection.selector).to eq({})
305
+ end
306
+
307
+ it "returns the query" do
308
+ expect(selection).to eq(query)
309
+ end
310
+
311
+ it_behaves_like 'returns a cloned query'
312
+ end
313
+
314
+ context "when provided nil" do
315
+
316
+ let(:selection) do
317
+ query.and(nil)
318
+ end
319
+
320
+ it "does not add any criterion" do
321
+ expect(selection.selector).to eq({})
322
+ end
323
+
324
+ it "returns the query" do
325
+ expect(selection).to eq(query)
326
+ end
327
+
328
+ it_behaves_like 'returns a cloned query'
329
+ end
330
+
331
+ context "when provided multiple criteria" do
332
+
333
+ context "when the criterion is already included" do
334
+
335
+ context 'simple criterion' do
336
+ let(:selection) do
337
+ query.and({ first: [ 1, 2 ] }).and({ first: [ 1, 2 ] })
338
+ end
339
+
340
+ it "adds all conditions" do
341
+ expect(selection.selector).to eq({
342
+ 'first' => [1, 2],
343
+ "$and" => [
344
+ { "first" => [ 1, 2 ] }
345
+ ]
346
+ })
347
+ end
348
+
349
+ it_behaves_like 'returns a cloned query'
350
+ end
351
+
352
+ context 'Key criterion' do
353
+ let(:selection) do
354
+ query.and({ first: [ 1, 2 ] }).and(:first.gt => 3)
355
+ end
356
+
357
+ it "adds all conditions" do
358
+ expect(selection.selector).to eq({
359
+ 'first' => [1, 2],
360
+ "$and" => [
361
+ { "first" => {'$gt' => 3} }
362
+ ]
363
+ })
364
+ end
365
+
366
+ it_behaves_like 'returns a cloned query'
367
+ end
368
+
369
+ context 'Key criterion when existing criterion is an operator' do
370
+ let(:selection) do
371
+ query.and(:first.lt => 5).and(:first.gt => 3)
372
+ end
373
+
374
+ it "adds all conditions" do
375
+ expect(selection.selector).to eq({
376
+ 'first' => {'$lt' => 5, '$gt' => 3},
377
+ })
378
+ end
379
+
380
+ it_behaves_like 'returns a cloned query'
381
+ end
382
+ end
383
+
384
+ context "when the new criteria are for different fields" do
385
+
386
+ let(:selection) do
387
+ query.and({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
388
+ end
389
+
390
+ it "adds all conditions to top level" do
391
+ expect(selection.selector).to eq({
392
+ "first" => [ 1, 2 ],
393
+ "second" => [ 3, 4 ],
394
+ })
395
+ end
396
+
397
+ it_behaves_like 'returns a cloned query'
398
+ end
399
+
400
+ context "when the new criteria are for the same field" do
401
+
402
+ context 'when criteria are simple' do
403
+ let(:selection) do
404
+ query.and({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
405
+ end
406
+
407
+ it "combines via $and operator" do
408
+ expect(selection.selector).to eq({
409
+ "first" => [ 1, 2 ],
410
+ "$and" => [
411
+ { "first" => [ 3, 4 ] }
412
+ ]
413
+ })
414
+ end
415
+
416
+ it_behaves_like 'returns a cloned query'
417
+ end
418
+
419
+ context 'when criteria use operators' do
420
+ shared_examples 'behave correctly' do
421
+ let(:selection) do
422
+ query.and(
423
+ { field: {first_operator => [ 1, 2 ] }},
424
+ { field: {second_operator => [ 3, 4 ] }},
425
+ )
426
+ end
427
+
428
+ it "combines via $and operator and stringifies all keys" do
429
+ expect(selection.selector).to eq({
430
+ "field" => {'$in' => [ 1, 2 ]},
431
+ "$and" => [
432
+ { "field" => {'$in' => [ 3, 4 ] }}
433
+ ]
434
+ })
435
+ end
436
+ end
437
+
438
+ [
439
+ ['$in', '$in'],
440
+ [:$in, '$in'],
441
+ ['$in', :$in],
442
+ [:$in, :$in],
443
+ ].each do |first_operator, second_operator|
444
+ context "when first operator is #{first_operator.inspect} and second operator is #{second_operator.inspect}" do
445
+ let(:first_operator) { first_operator }
446
+ let(:second_operator) { second_operator }
447
+
448
+ include_examples 'behave correctly'
449
+ end
450
+ end
451
+ end
452
+
453
+ context 'when criteria are handled via Key' do
454
+ shared_examples_for 'adds the conditions to top level' do
455
+
456
+ it "adds the conditions to top level" do
457
+ expect(selection.selector).to eq({
458
+ "field" => {'$gt' => 3, '$lt' => 5},
459
+ })
460
+ end
461
+
462
+ it_behaves_like 'returns a cloned query'
463
+ end
464
+
465
+ context 'criteria are provided in the same hash' do
466
+ let(:selection) do
467
+ query.send(tested_method, :field.gt => 3, :field.lt => 5)
468
+ end
469
+
470
+ it_behaves_like 'adds the conditions to top level'
471
+ end
472
+
473
+ context 'criteria are provided in separate hashes' do
474
+ let(:selection) do
475
+ query.send(tested_method, {:field.gt => 3}, {:field.lt => 5})
476
+ end
477
+
478
+ it_behaves_like 'adds the conditions to top level'
479
+ end
480
+
481
+ context 'when the criterion is wrapped in an array' do
482
+ let(:selection) do
483
+ query.send(tested_method, [:field.gt => 3], [:field.lt => 5])
484
+ end
485
+
486
+ it_behaves_like 'adds the conditions to top level'
487
+ end
488
+ end
489
+
490
+ context 'when criteria are simple and handled via Key' do
491
+ shared_examples_for 'combines conditions with $and' do
492
+
493
+ it "combines conditions with $and" do
494
+ expect(selection.selector).to eq({
495
+ "field" => 3,
496
+ '$and' => ['field' => {'$lt' => 5}],
497
+ })
498
+ end
499
+
500
+ it_behaves_like 'returns a cloned query'
501
+ end
502
+
503
+ shared_examples_for 'combines conditions with $eq' do
504
+
505
+ it "combines conditions with $eq" do
506
+ expect(selection.selector).to eq({
507
+ "field" => {'$eq' => 3, '$lt' => 5},
508
+ })
509
+ end
510
+
511
+ it_behaves_like 'returns a cloned query'
512
+ end
513
+
514
+ shared_examples_for 'combines conditions with $regex' do
515
+
516
+ it "combines conditions with $regex" do
517
+ expect(selection.selector).to eq({
518
+ "field" => {'$regex' => /t/, '$lt' => 5},
519
+ })
520
+ end
521
+
522
+ it_behaves_like 'returns a cloned query'
523
+ end
524
+
525
+ context 'criteria are provided in the same hash' do
526
+ context 'non-regexp argument' do
527
+ let(:selection) do
528
+ query.send(tested_method, :field => 3, :field.lt => 5)
529
+ end
530
+
531
+ it_behaves_like 'combines conditions with $eq'
532
+ end
533
+
534
+ context 'regexp argument' do
535
+ let(:selection) do
536
+ query.send(tested_method, :field => /t/, :field.lt => 5)
537
+ end
538
+
539
+ it_behaves_like 'combines conditions with $regex'
540
+ end
541
+ end
542
+
543
+ context 'criteria are provided in separate hashes' do
544
+ let(:selection) do
545
+ query.send(tested_method, {:field => 3}, {:field.lt => 5})
546
+ end
547
+
548
+ it_behaves_like 'combines conditions with $and'
549
+ end
550
+
551
+ context 'when the criterion is wrapped in an array' do
552
+ let(:selection) do
553
+ query.send(tested_method, [:field => 3], [:field.lt => 5])
554
+ end
555
+
556
+ it_behaves_like 'combines conditions with $and'
557
+ end
558
+ end
559
+
560
+ context 'when criteria are handled via Key and simple' do
561
+ shared_examples_for 'combines conditions with $and' do
562
+
563
+ it "combines conditions with $and" do
564
+ expect(selection.selector).to eq({
565
+ "field" => {'$gt' => 3},
566
+ '$and' => ['field' => 5],
567
+ })
568
+ end
569
+
570
+ it_behaves_like 'returns a cloned query'
571
+ end
572
+
573
+ shared_examples_for 'combines conditions with $eq' do
574
+
575
+ it "combines conditions with $eq" do
576
+ expect(selection.selector).to eq({
577
+ "field" => {'$gt' => 3, '$eq' => 5},
578
+ })
579
+ end
580
+
581
+ it_behaves_like 'returns a cloned query'
582
+ end
583
+
584
+ shared_examples_for 'combines conditions with $regex' do
585
+
586
+ it "combines conditions with $regex" do
587
+ expect(selection.selector).to eq({
588
+ "field" => {'$gt' => 3, '$regex' => /t/},
589
+ })
590
+ end
591
+
592
+ it_behaves_like 'returns a cloned query'
593
+ end
594
+
595
+ context 'criteria are provided in the same hash' do
596
+ context 'non-regexp argument' do
597
+ let(:selection) do
598
+ query.send(tested_method, :field.gt => 3, :field => 5)
599
+ end
600
+
601
+ it_behaves_like 'combines conditions with $eq'
602
+ end
603
+
604
+ context 'regexp argument' do
605
+ let(:selection) do
606
+ query.send(tested_method, :field.gt => 3, :field => /t/)
607
+ end
608
+
609
+ it_behaves_like 'combines conditions with $regex'
610
+ end
611
+ end
612
+
613
+ context 'criteria are provided in separate hashes' do
614
+ let(:selection) do
615
+ query.send(tested_method, {:field.gt => 3}, {:field => 5})
616
+ end
617
+
618
+ it_behaves_like 'combines conditions with $and'
619
+ end
620
+
621
+ context 'when the criterion is wrapped in an array' do
622
+ let(:selection) do
623
+ query.send(tested_method, [:field.gt => 3], [:field => 5])
624
+ end
625
+
626
+ it_behaves_like 'combines conditions with $and'
627
+ end
628
+ end
629
+ end
630
+ end
631
+
632
+ context 'when argument is a Criteria' do
633
+ let(:query) do
634
+ Mongoid::Query.new.where(hello: 'world')
635
+ end
636
+
637
+ let(:result) { query.and(other) }
638
+
639
+ context 'different fields' do
640
+
641
+ let(:other) do
642
+ Mongoid::Query.new.where(foo: 'bar')
643
+ end
644
+
645
+ it 'combines both fields at top level' do
646
+ expect(result.selector).to eq('hello' => 'world', 'foo' => 'bar')
647
+ end
648
+ end
649
+
650
+ context 'same field' do
651
+
652
+ let(:other) do
653
+ Mongoid::Query.new.where(hello: /bar/)
654
+ end
655
+
656
+ it 'combines fields with $and' do
657
+ expect(result.selector).to eq('hello' => 'world', '$and' => [{'hello' => /bar/}])
658
+ end
659
+ end
660
+ end
661
+
662
+ context 'when argument is a mix of Criteria and hashes' do
663
+ let(:query) do
664
+ Mongoid::Query.new.where(hello: 'world')
665
+ end
666
+
667
+ let(:other1) do
668
+ Mongoid::Query.new.where(foo: 'bar')
669
+ end
670
+
671
+ let(:other2) do
672
+ {bar: 42}
673
+ end
674
+
675
+ let(:other3) do
676
+ Mongoid::Query.new.where(a: 2)
677
+ end
678
+
679
+ let(:result) { query.and(other1, other2, other3) }
680
+
681
+ it 'combines' do
682
+ expect(result.selector).to eq('hello' => 'world',
683
+ 'foo' => 'bar',
684
+ 'bar' => 42,
685
+ 'a' => 2,
686
+ )
687
+ end
688
+ end
689
+
690
+ context 'when Key instances are used and types involved have serializers' do
691
+ let(:time) { Time.now }
692
+
693
+ let(:query) do
694
+ Band.all.and(:created_at.gt => time)
695
+ end
696
+
697
+ let(:expected) do
698
+ {'created_at' => {'$gt' => time.utc}}
699
+ end
700
+
701
+ it 'combines and evolves' do
702
+ expect(query.selector).to eq(expected)
703
+ end
704
+ end
705
+
706
+ describe 'query shape' do
707
+ shared_examples_for 'adds most recent criterion as $and' do
708
+ let(:selector) { scope.selector }
709
+
710
+ it 'adds most recent criterion as $and' do
711
+ expect(selector).to eq('foo' => 1, '$and' => [{'foo' => 2}])
712
+ end
713
+ end
714
+
715
+ context 'and/and' do
716
+ let(:scope) do
717
+ Band.and(foo: 1).and(foo: 2)
718
+ end
719
+
720
+ it_behaves_like 'adds most recent criterion as $and'
721
+ end
722
+
723
+ context 'and/and' do
724
+ let(:scope) do
725
+ Band.and(foo: 1).and(foo: 2)
726
+ end
727
+
728
+ it_behaves_like 'adds most recent criterion as $and'
729
+ end
730
+
731
+ context 'and/where' do
732
+ let(:scope) do
733
+ Band.and(foo: 1).where(foo: 2)
734
+ end
735
+
736
+ it_behaves_like 'adds most recent criterion as $and'
737
+ end
738
+
739
+ context 'where/and' do
740
+ let(:scope) do
741
+ Band.where(foo: 1).and(foo: 2)
742
+ end
743
+
744
+ it_behaves_like 'adds most recent criterion as $and'
745
+ end
746
+
747
+ context 'where/where' do
748
+ let(:scope) do
749
+ Band.where(foo: 1).where(foo: 2)
750
+ end
751
+
752
+ it_behaves_like 'adds most recent criterion as $and'
753
+ end
754
+ end
755
+
756
+ context 'when conditions already exist in criteria' do
757
+ let(:base_selection) do
758
+ query.where(foo: 'bar')
759
+ end
760
+
761
+ context 'when hash conditions are given' do
762
+ let(:selection) do
763
+ base_selection.and(hello: 'world')
764
+ end
765
+
766
+ it 'adds new conditions to top level' do
767
+ selection.selector.should == {
768
+ 'foo' => 'bar',
769
+ 'hello' => 'world',
770
+ }
771
+ end
772
+ end
773
+
774
+ context 'when criteria conditions are given' do
775
+ let(:selection) do
776
+ base_selection.and(query.where(hello: 'world'))
777
+ end
778
+
779
+ it 'adds new conditions to top level' do
780
+ selection.selector.should == {
781
+ 'foo' => 'bar',
782
+ 'hello' => 'world',
783
+ }
784
+ end
785
+ end
786
+
787
+ context 'when complex criteria conditions are given' do
788
+ let(:selection) do
789
+ base_selection.and(query.or([one: 'one'], [two: 'two']))
790
+ end
791
+
792
+ it 'adds new conditions to top level' do
793
+ selection.selector.should == {
794
+ 'foo' => 'bar',
795
+ '$or' => [
796
+ {'one' => 'one'},
797
+ {'two' => 'two'},
798
+ ],
799
+ }
800
+ end
801
+ end
802
+ end
803
+ end
804
+
805
+ shared_examples '$or/$nor' do
806
+
807
+ it_behaves_like 'a non-hoisting logical operation'
808
+
809
+ context "when provided no arguments" do
810
+
811
+ let(:selection) do
812
+ query.send(tested_method)
813
+ end
814
+
815
+ it_behaves_like 'returns a cloned query'
816
+
817
+ it "does not add any criteria" do
818
+ expect(selection.selector).to eq({})
819
+ end
820
+
821
+ it "returns the query" do
822
+ expect(selection).to eq(query)
823
+ end
824
+ end
825
+
826
+ context "when provided nil" do
827
+
828
+ let(:selection) do
829
+ query.send(tested_method, nil)
830
+ end
831
+
832
+ it_behaves_like 'returns a cloned query'
833
+
834
+ it "does not add any criteria" do
835
+ expect(selection.selector).to eq({})
836
+ end
837
+
838
+ it "returns the query" do
839
+ expect(selection).to eq(query)
840
+ end
841
+ end
842
+
843
+ context "when provided a single criterion" do
844
+
845
+ let(:selection) do
846
+ query.send(tested_method, field: [ 1, 2 ])
847
+ end
848
+
849
+ it_behaves_like 'returns a cloned query'
850
+
851
+ it "adds the $or/$nor selector" do
852
+ expect(selection.selector).to eq({
853
+ expected_operator => [{ "field" => [ 1, 2 ] }]
854
+ })
855
+ end
856
+
857
+ context 'when the criterion is wrapped in array' do
858
+
859
+ let(:selection) do
860
+ query.send(tested_method, [{ field: [ 1, 2 ] }])
861
+ end
862
+
863
+ it_behaves_like 'returns a cloned query'
864
+
865
+ it "adds the $or/$nor selector" do
866
+ expect(selection.selector).to eq({
867
+ expected_operator => [{ "field" => [ 1, 2 ] }]
868
+ })
869
+ end
870
+
871
+ context 'when the array has nil as one of the elements' do
872
+
873
+ let(:selection) do
874
+ query.send(tested_method, [{ field: [ 1, 2 ] }, nil])
875
+ end
876
+
877
+ it_behaves_like 'returns a cloned query'
878
+
879
+ it "adds the $or/$nor selector ignoring the nil element" do
880
+ expect(selection.selector).to eq({
881
+ expected_operator => [{ "field" => [ 1, 2 ] }]
882
+ })
883
+ end
884
+ end
885
+ end
886
+
887
+ context 'when query already has a condition on another field' do
888
+
889
+ let(:selection) do
890
+ query.where(foo: 'bar').send(tested_method, field: [ 1, 2 ])
891
+ end
892
+
893
+ it 'moves original conditions under $or/$nor' do
894
+ expect(selection.selector).to eq({
895
+ expected_operator => [{'foo' => 'bar'}, { "field" => [ 1, 2 ] }]
896
+ })
897
+ end
898
+ end
899
+
900
+ context 'when query already has an $or/$nor condition and another condition' do
901
+
902
+ let(:selection) do
903
+ query.send(tested_method, field: [ 1, 2 ]).where(foo: 'bar').send(tested_method, test: 1)
904
+ end
905
+
906
+ it 'unions existing conditions' do
907
+ expect(selection.selector).to eq(
908
+ expected_operator => [
909
+ {
910
+ expected_operator => [{ "field" => [ 1, 2 ] }],
911
+ 'foo' => 'bar',
912
+ },
913
+ {'test' => 1},
914
+ ]
915
+ )
916
+ end
917
+ end
918
+ end
919
+
920
+ context "when provided multiple criteria" do
921
+
922
+ context "when the criteria are for different fields" do
923
+
924
+ let(:selection) do
925
+ query.send(tested_method, { first: [ 1, 2 ] }, { second: [ 3, 4 ] })
926
+ end
927
+
928
+ it_behaves_like 'returns a cloned query'
929
+
930
+ it "adds the $or/$nor selector" do
931
+ expect(selection.selector).to eq({
932
+ expected_operator => [
933
+ { "first" => [ 1, 2 ] },
934
+ { "second" => [ 3, 4 ] }
935
+ ]
936
+ })
937
+ end
938
+ end
939
+
940
+ context "when the criteria uses a Key instance" do
941
+
942
+ let(:selection) do
943
+ query.send(tested_method, { first: [ 1, 2 ] }, { :second.gt => 3 })
944
+ end
945
+
946
+ it "adds the $or/$nor selector" do
947
+ expect(selection.selector).to eq({
948
+ expected_operator => [
949
+ { "first" => [ 1, 2 ] },
950
+ { "second" => { "$gt" => 3 }}
951
+ ]
952
+ })
953
+ end
954
+
955
+ it_behaves_like 'returns a cloned query'
956
+
957
+ context 'when the criterion is a time' do
958
+ let(:selection) do
959
+ query.send(tested_method, :field.gte => Time.new(2020, 1, 1))
960
+ end
961
+
962
+ it 'adds the conditions' do
963
+ expect(selection.selector).to eq(expected_operator => [
964
+ "field" => {'$gte' => Time.new(2020, 1, 1)},
965
+ ])
966
+ end
967
+
968
+ it 'keeps the type' do
969
+ selection.selector[expected_operator].first['field']['$gte'].should be_a(Time)
970
+ end
971
+ end
972
+
973
+ context 'when the criterion is a datetime' do
974
+ let(:selection) do
975
+ query.send(tested_method, :field.gte => DateTime.new(2020, 1, 1))
976
+ end
977
+
978
+ it 'adds the conditions' do
979
+ expect(selection.selector).to eq(expected_operator => [
980
+ "field" => {'$gte' => Time.utc(2020, 1, 1)},
981
+ ])
982
+ end
983
+
984
+ it 'converts argument to a time' do
985
+ selection.selector[expected_operator].first['field']['$gte'].should be_a(Time)
986
+ end
987
+ end
988
+
989
+ context 'when the criterion is a date' do
990
+ let(:selection) do
991
+ query.send(tested_method, :field.gte => Date.new(2020, 1, 1))
992
+ end
993
+
994
+ it 'adds the conditions' do
995
+ expect(selection.selector).to eq(expected_operator => [
996
+ "field" => {'$gte' => Time.utc(2020, 1, 1)},
997
+ ])
998
+ end
999
+
1000
+ it 'converts argument to a time' do
1001
+ selection.selector[expected_operator].first['field']['$gte'].should be_a(Time)
1002
+ end
1003
+ end
1004
+ end
1005
+
1006
+ context "when a criterion has an aliased field" do
1007
+
1008
+ let(:selection) do
1009
+ query.send(tested_method, { id: 1 })
1010
+ end
1011
+
1012
+ it "adds the $or/$nor selector and aliases the field" do
1013
+ expect(selection.selector).to eq({
1014
+ expected_operator => [ { "_id" => 1 } ]
1015
+ })
1016
+ end
1017
+
1018
+ it_behaves_like 'returns a cloned query'
1019
+ end
1020
+
1021
+ context "when a criterion is wrapped in an array" do
1022
+
1023
+ let(:selection) do
1024
+ query.send(tested_method, [{ first: [ 1, 2 ] }, { :second.gt => 3 }])
1025
+ end
1026
+
1027
+ it_behaves_like 'returns a cloned query'
1028
+
1029
+ it "adds the $or/$nor selector" do
1030
+ expect(selection.selector).to eq({
1031
+ expected_operator => [
1032
+ { "first" => [ 1, 2 ] },
1033
+ { "second" => { "$gt" => 3 }}
1034
+ ]
1035
+ })
1036
+ end
1037
+ end
1038
+
1039
+ context "when the criteria are on the same field" do
1040
+
1041
+ context 'simple criteria' do
1042
+ let(:selection) do
1043
+ query.send(tested_method, { first: [ 1, 2 ] }, { first: [ 3, 4 ] })
1044
+ end
1045
+
1046
+ it_behaves_like 'returns a cloned query'
1047
+
1048
+ it "appends both $or/$nor expressions" do
1049
+ expect(selection.selector).to eq({
1050
+ expected_operator => [
1051
+ { "first" => [ 1, 2 ] },
1052
+ { "first" => [ 3, 4 ] }
1053
+ ]
1054
+ })
1055
+ end
1056
+ end
1057
+
1058
+ context 'Key criteria as one argument' do
1059
+ let(:selection) do
1060
+ query.send(tested_method, :first.gt => 3, :first.lt => 5)
1061
+ end
1062
+
1063
+ it_behaves_like 'returns a cloned query'
1064
+
1065
+ it "adds all criteria" do
1066
+ expect(selection.selector).to eq({
1067
+ expected_operator => [
1068
+ { "first" => {'$gt' => 3, '$lt' => 5} },
1069
+ ]
1070
+ })
1071
+ end
1072
+ end
1073
+
1074
+ context 'Key criteria as multiple arguments' do
1075
+ let(:selection) do
1076
+ query.send(tested_method, {:first.gt => 3}, {:first.lt => 5})
1077
+ end
1078
+
1079
+ it_behaves_like 'returns a cloned query'
1080
+
1081
+ it "adds all criteria" do
1082
+ expect(selection.selector).to eq({
1083
+ expected_operator => [
1084
+ { "first" => {'$gt' => 3} },
1085
+ { "first" => {'$lt' => 5} },
1086
+ ]
1087
+ })
1088
+ end
1089
+ end
1090
+ end
1091
+ end
1092
+
1093
+ context "when chaining the criterion" do
1094
+
1095
+ context "when the criterion are for different fields" do
1096
+
1097
+ let(:selection) do
1098
+ query.send(tested_method, first: [ 1, 2 ]).send(tested_method, second: [ 3, 4 ])
1099
+ end
1100
+
1101
+ it_behaves_like 'returns a cloned query'
1102
+
1103
+ it "adds the $or/$nor selectors" do
1104
+ expect(selection.selector).to eq({
1105
+ expected_operator => [
1106
+ { "first" => [ 1, 2 ] },
1107
+ { "second" => [ 3, 4 ] }
1108
+ ]
1109
+ })
1110
+ end
1111
+ end
1112
+
1113
+ context "when the criterion are on the same field" do
1114
+
1115
+ let(:selection) do
1116
+ query.send(tested_method, first: [ 1, 2 ]).send(tested_method, first: [ 3, 4 ])
1117
+ end
1118
+
1119
+ it_behaves_like 'returns a cloned query'
1120
+
1121
+ it "appends both $or/$nor expressions" do
1122
+ expect(selection.selector).to eq({
1123
+ expected_operator => [
1124
+ { "first" => [ 1, 2 ] },
1125
+ { "first" => [ 3, 4 ] }
1126
+ ]
1127
+ })
1128
+ end
1129
+ end
1130
+ end
1131
+
1132
+ context 'when giving multiple conditions in one call on the same key with symbol operator' do
1133
+
1134
+ context 'non-regexp argument' do
1135
+ let(:selection) do
1136
+ query.send(tested_method, field: 1, :field.gt => 0)
1137
+ end
1138
+
1139
+ it 'combines conditions with $eq' do
1140
+ selection.selector.should == {
1141
+ expected_operator => [
1142
+ 'field' => {'$eq' => 1, '$gt' => 0},
1143
+ ]
1144
+ }
1145
+ end
1146
+ end
1147
+
1148
+ context 'regexp argument' do
1149
+ let(:selection) do
1150
+ query.send(tested_method, field: /t/, :field.gt => 0)
1151
+ end
1152
+
1153
+ it 'combines conditions with $regex' do
1154
+ selection.selector.should == {
1155
+ expected_operator => [
1156
+ 'field' => {'$regex' => /t/, '$gt' => 0},
1157
+ ]
1158
+ }
1159
+ end
1160
+ end
1161
+
1162
+ end
1163
+ end
1164
+
1165
+ describe "#or" do
1166
+
1167
+ let(:tested_method) { :or }
1168
+ let(:expected_operator) { '$or' }
1169
+
1170
+ it_behaves_like '$or/$nor'
1171
+ end
1172
+
1173
+ describe "#nor" do
1174
+
1175
+ let(:tested_method) { :nor }
1176
+ let(:expected_operator) { '$nor' }
1177
+
1178
+ it_behaves_like '$or/$nor'
1179
+ end
1180
+
1181
+ describe "#any_of" do
1182
+
1183
+ let(:tested_method) { :any_of }
1184
+ let(:expected_operator) { '$or' }
1185
+
1186
+ it_behaves_like 'a hoisting logical operation'
1187
+
1188
+ # When multiple arguments are given to any_of, it behaves differently
1189
+ # from and.
1190
+ context 'when argument is a mix of Criteria and hashes' do
1191
+ let(:query) do
1192
+ Mongoid::Query.new.where(hello: 'world')
1193
+ end
1194
+
1195
+ let(:other1) do
1196
+ Mongoid::Query.new.where(foo: 'bar')
1197
+ end
1198
+
1199
+ let(:other2) do
1200
+ {bar: 42}
1201
+ end
1202
+
1203
+ let(:other3) do
1204
+ Mongoid::Query.new.where(a: 2)
1205
+ end
1206
+
1207
+ let(:result) { query.send(tested_method, other1, other2, other3) }
1208
+
1209
+ it 'combines' do
1210
+ expect(result.selector).to eq(
1211
+ 'hello' => 'world',
1212
+ expected_operator => [
1213
+ {'foo' => 'bar'},
1214
+ {'bar' => 42},
1215
+ {'a' => 2},
1216
+ ],
1217
+ )
1218
+ end
1219
+ end
1220
+
1221
+ context "when provided no arguments" do
1222
+
1223
+ let(:selection) do
1224
+ query.any_of
1225
+ end
1226
+
1227
+ it_behaves_like 'returns a cloned query'
1228
+
1229
+ it "does not add any criteria" do
1230
+ expect(selection.selector).to eq({})
1231
+ end
1232
+
1233
+ it "returns the query" do
1234
+ expect(selection).to eq(query)
1235
+ end
1236
+ end
1237
+
1238
+ context "when provided nil" do
1239
+
1240
+ let(:selection) do
1241
+ query.any_of(nil)
1242
+ end
1243
+
1244
+ it_behaves_like 'returns a cloned query'
1245
+
1246
+ it "does not add any criteria" do
1247
+ expect(selection.selector).to eq({})
1248
+ end
1249
+
1250
+ it "returns the query" do
1251
+ expect(selection).to eq(query)
1252
+ end
1253
+ end
1254
+
1255
+ context "when provided a single criterion" do
1256
+
1257
+ let(:selection) do
1258
+ query.any_of(field: [ 1, 2 ])
1259
+ end
1260
+
1261
+ it_behaves_like 'returns a cloned query'
1262
+
1263
+ it "adds the $or selector" do
1264
+ expect(selection.selector).to eq(
1265
+ "field" => [ 1, 2 ],
1266
+ )
1267
+ end
1268
+
1269
+ context 'when the criterion is wrapped in array' do
1270
+
1271
+ let(:selection) do
1272
+ query.any_of([{ field: [ 1, 2 ] }])
1273
+ end
1274
+
1275
+ it_behaves_like 'returns a cloned query'
1276
+
1277
+ it "adds the condition" do
1278
+ expect(selection.selector).to eq(
1279
+ "field" => [ 1, 2 ],
1280
+ )
1281
+ end
1282
+
1283
+ context 'when the array has nil as one of the elements' do
1284
+
1285
+ let(:selection) do
1286
+ query.any_of([{ field: [ 1, 2 ] }, nil])
1287
+ end
1288
+
1289
+ it_behaves_like 'returns a cloned query'
1290
+
1291
+ it "adds the $or selector ignoring the nil element" do
1292
+ expect(selection.selector).to eq(
1293
+ "field" => [ 1, 2 ],
1294
+ )
1295
+ end
1296
+ end
1297
+ end
1298
+
1299
+ context 'when query already has a condition on another field' do
1300
+
1301
+ context 'when there is one argument' do
1302
+
1303
+ let(:selection) do
1304
+ query.where(foo: 'bar').any_of(field: [ 1, 2 ])
1305
+ end
1306
+
1307
+ it 'adds the new condition' do
1308
+ expect(selection.selector).to eq(
1309
+ 'foo' => 'bar',
1310
+ 'field' => [1, 2],
1311
+ )
1312
+ end
1313
+ end
1314
+
1315
+ context 'when there are multiple arguments' do
1316
+
1317
+ let(:selection) do
1318
+ query.where(foo: 'bar').any_of({field: [ 1, 2 ]}, {hello: 'world'})
1319
+ end
1320
+
1321
+ it 'adds the new condition' do
1322
+ expect(selection.selector).to eq(
1323
+ 'foo' => 'bar',
1324
+ '$or' => [
1325
+ {'field' => [1, 2]},
1326
+ {'hello' => 'world'},
1327
+ ],
1328
+ )
1329
+ end
1330
+ end
1331
+ end
1332
+
1333
+ context 'when query already has an $or condition and another condition' do
1334
+
1335
+ let(:selection) do
1336
+ query.or(field: [ 1, 2 ]).where(foo: 'bar').any_of(test: 1)
1337
+ end
1338
+
1339
+ it 'adds the new condition' do
1340
+ expect(selection.selector).to eq(
1341
+ '$or' => [{'field' => [1, 2]}],
1342
+ 'foo' => 'bar',
1343
+ 'test' => 1,
1344
+ )
1345
+ end
1346
+ end
1347
+ end
1348
+
1349
+ context "when provided multiple criteria" do
1350
+
1351
+ context "when the criteria are for different fields" do
1352
+
1353
+ let(:selection) do
1354
+ query.any_of({ first: [ 1, 2 ] }, { second: [ 3, 4 ] })
1355
+ end
1356
+
1357
+ it_behaves_like 'returns a cloned query'
1358
+
1359
+ it "adds the $or selector" do
1360
+ expect(selection.selector).to eq({
1361
+ "$or" => [
1362
+ { "first" => [ 1, 2 ] },
1363
+ { "second" => [ 3, 4 ] }
1364
+ ]
1365
+ })
1366
+ end
1367
+ end
1368
+
1369
+ context "when the criteria uses a Key instance" do
1370
+
1371
+ let(:selection) do
1372
+ query.any_of({ first: [ 1, 2 ] }, { :second.gt => 3 })
1373
+ end
1374
+
1375
+ it "adds the $or selector" do
1376
+ expect(selection.selector).to eq({
1377
+ "$or" => [
1378
+ { "first" => [ 1, 2 ] },
1379
+ { "second" => { "$gt" => 3 }}
1380
+ ]
1381
+ })
1382
+ end
1383
+
1384
+ it_behaves_like 'returns a cloned query'
1385
+ end
1386
+
1387
+ context 'when criteria are simple and handled via Key' do
1388
+ shared_examples_for 'adds conditions with $or' do
1389
+
1390
+ it "adds conditions with $or" do
1391
+ expect(selection.selector).to eq({
1392
+ '$or' => [
1393
+ {'field' => 3},
1394
+ {'field' => {'$lt' => 5}},
1395
+ ],
1396
+ })
1397
+ end
1398
+
1399
+ it_behaves_like 'returns a cloned query'
1400
+ end
1401
+
1402
+ shared_examples_for 'combines conditions with $eq' do
1403
+
1404
+ it "combines conditions with $eq" do
1405
+ expect(selection.selector).to eq({
1406
+ 'field' => {
1407
+ '$eq' => 3,
1408
+ '$lt' => 5,
1409
+ },
1410
+ })
1411
+ end
1412
+
1413
+ it_behaves_like 'returns a cloned query'
1414
+ end
1415
+
1416
+ shared_examples_for 'combines conditions with $regex' do
1417
+
1418
+ it "combines conditions with $regex" do
1419
+ expect(selection.selector).to eq({
1420
+ 'field' => {
1421
+ '$regex' => /t/,
1422
+ '$lt' => 5,
1423
+ },
1424
+ })
1425
+ end
1426
+
1427
+ it_behaves_like 'returns a cloned query'
1428
+ end
1429
+
1430
+ context 'criteria are provided in the same hash' do
1431
+ context 'non-regexp argument' do
1432
+ let(:selection) do
1433
+ query.send(tested_method, :field => 3, :field.lt => 5)
1434
+ end
1435
+
1436
+ it_behaves_like 'combines conditions with $eq'
1437
+ end
1438
+
1439
+ context 'regexp argument' do
1440
+ let(:selection) do
1441
+ query.send(tested_method, :field => /t/, :field.lt => 5)
1442
+ end
1443
+
1444
+ it_behaves_like 'combines conditions with $regex'
1445
+ end
1446
+ end
1447
+
1448
+ context 'criteria are provided in separate hashes' do
1449
+ let(:selection) do
1450
+ query.send(tested_method, {:field => 3}, {:field.lt => 5})
1451
+ end
1452
+
1453
+ it_behaves_like 'adds conditions with $or'
1454
+ end
1455
+
1456
+ context 'when the criterion is wrapped in an array' do
1457
+ let(:selection) do
1458
+ query.send(tested_method, [:field => 3], [:field.lt => 5])
1459
+ end
1460
+
1461
+ it_behaves_like 'adds conditions with $or'
1462
+ end
1463
+ end
1464
+
1465
+ context 'when criteria are handled via Key and simple' do
1466
+ shared_examples_for 'adds conditions with $or' do
1467
+
1468
+ it "adds conditions with $or" do
1469
+ expect(selection.selector).to eq({
1470
+ '$or' => [
1471
+ {'field' => {'$gt' => 3}},
1472
+ {'field' => 5},
1473
+ ],
1474
+ })
1475
+ end
1476
+
1477
+ it_behaves_like 'returns a cloned query'
1478
+ end
1479
+
1480
+ shared_examples_for 'combines conditions with $eq' do
1481
+
1482
+ it "combines conditions with $eq" do
1483
+ expect(selection.selector).to eq(
1484
+ 'field' => {'$gt' => 3, '$eq' => 5},
1485
+ )
1486
+ end
1487
+
1488
+ it_behaves_like 'returns a cloned query'
1489
+ end
1490
+
1491
+ shared_examples_for 'combines conditions with $regex' do
1492
+
1493
+ it "combines conditions with $regex" do
1494
+ expect(selection.selector).to eq(
1495
+ 'field' => {'$gt' => 3, '$regex' => /t/},
1496
+ )
1497
+ end
1498
+
1499
+ it_behaves_like 'returns a cloned query'
1500
+ end
1501
+
1502
+ context 'criteria are provided in the same hash' do
1503
+ context 'non-regexp argument' do
1504
+ let(:selection) do
1505
+ query.send(tested_method, :field.gt => 3, :field => 5)
1506
+ end
1507
+
1508
+ it_behaves_like 'combines conditions with $eq'
1509
+ end
1510
+
1511
+ context 'regexp argument' do
1512
+ let(:selection) do
1513
+ query.send(tested_method, :field.gt => 3, :field => /t/)
1514
+ end
1515
+
1516
+ it_behaves_like 'combines conditions with $regex'
1517
+ end
1518
+ end
1519
+
1520
+ context 'criteria are provided in separate hashes' do
1521
+ let(:selection) do
1522
+ query.send(tested_method, {:field.gt => 3}, {:field => 5})
1523
+ end
1524
+
1525
+ it_behaves_like 'adds conditions with $or'
1526
+ end
1527
+
1528
+ context 'when the criterion is wrapped in an array' do
1529
+ let(:selection) do
1530
+ query.send(tested_method, [:field.gt => 3], [:field => 5])
1531
+ end
1532
+
1533
+ it_behaves_like 'adds conditions with $or'
1534
+ end
1535
+ end
1536
+
1537
+ context "when a criterion has an aliased field" do
1538
+
1539
+ let(:selection) do
1540
+ query.any_of({ id: 1 })
1541
+ end
1542
+
1543
+ it "adds the $or selector and aliases the field" do
1544
+ expect(selection.selector).to eq(
1545
+ "_id" => 1,
1546
+ )
1547
+ end
1548
+
1549
+ it_behaves_like 'returns a cloned query'
1550
+ end
1551
+
1552
+ context "when a criterion is wrapped in an array" do
1553
+
1554
+ let(:selection) do
1555
+ query.any_of([{ first: [ 1, 2 ] }, { :second.gt => 3 }])
1556
+ end
1557
+
1558
+ it_behaves_like 'returns a cloned query'
1559
+
1560
+ it "adds the $or selector" do
1561
+ expect(selection.selector).to eq({
1562
+ "$or" => [
1563
+ { "first" => [ 1, 2 ] },
1564
+ { "second" => { "$gt" => 3 }}
1565
+ ]
1566
+ })
1567
+ end
1568
+ end
1569
+
1570
+ context "when the criteria are on the same field" do
1571
+
1572
+ let(:selection) do
1573
+ query.any_of({ first: [ 1, 2 ] }, { first: [ 3, 4 ] })
1574
+ end
1575
+
1576
+ it_behaves_like 'returns a cloned query'
1577
+
1578
+ it "appends both $or expressions" do
1579
+ expect(selection.selector).to eq({
1580
+ "$or" => [
1581
+ { "first" => [ 1, 2 ] },
1582
+ { "first" => [ 3, 4 ] }
1583
+ ]
1584
+ })
1585
+ end
1586
+ end
1587
+ end
1588
+
1589
+ context "when chaining the criteria" do
1590
+
1591
+ context "when the criteria are for different fields" do
1592
+
1593
+ let(:selection) do
1594
+ query.any_of(first: [ 1, 2 ]).any_of(second: [ 3, 4 ])
1595
+ end
1596
+
1597
+ it_behaves_like 'returns a cloned query'
1598
+
1599
+ it "adds the conditions separately" do
1600
+ expect(selection.selector).to eq(
1601
+ "first" => [ 1, 2 ],
1602
+ "second" => [ 3, 4 ],
1603
+ )
1604
+ end
1605
+ end
1606
+
1607
+ context "when the criteria are on the same field" do
1608
+
1609
+ let(:selection) do
1610
+ query.any_of(first: [ 1, 2 ]).any_of(first: [ 3, 4 ])
1611
+ end
1612
+
1613
+ it_behaves_like 'returns a cloned query'
1614
+
1615
+ it "adds the conditions separately" do
1616
+ expect(selection.selector).to eq(
1617
+ "first" => [ 1, 2 ],
1618
+ '$and' => [{"first" => [ 3, 4 ]}],
1619
+ )
1620
+ end
1621
+ end
1622
+ end
1623
+
1624
+ context 'when using multiple criteria and symbol operators' do
1625
+ context 'when using fields that meaningfully evolve values' do
1626
+
1627
+ let(:query) do
1628
+ Dictionary.any_of({a: 1}, :published.gt => Date.new(2020, 2, 3))
1629
+ end
1630
+
1631
+ it 'generates the expected query' do
1632
+ query.selector.should == {'$or' => [
1633
+ {'a' => 1},
1634
+ # Date instance is converted to a Time instance in local time,
1635
+ # because we are querying on a Time field and dates are interpreted
1636
+ # in local time when assigning to Time fields
1637
+ {'published' => {'$gt' => Time.local(2020, 2, 3)}},
1638
+ ]}
1639
+ end
1640
+ end
1641
+
1642
+ context 'when using fields that do not meaningfully evolve values' do
1643
+
1644
+ let(:query) do
1645
+ Dictionary.any_of({a: 1}, :submitted_on.gt => Date.new(2020, 2, 3))
1646
+ end
1647
+
1648
+ it 'generates the expected query' do
1649
+ query.selector.should == {'$or' => [
1650
+ {'a' => 1},
1651
+ # Date instance is converted to a Time instance in UTC,
1652
+ # because we are querying on a Date field and dates are interpreted
1653
+ # in UTC when persisted as dates by Mongoid
1654
+ {'submitted_on' => {'$gt' => Time.utc(2020, 2, 3)}},
1655
+ ]}
1656
+ end
1657
+ end
1658
+ end
1659
+ end
1660
+
1661
+ describe "#not" do
1662
+
1663
+ context "when provided no criterion" do
1664
+
1665
+ let(:selection) do
1666
+ query.not
1667
+ end
1668
+
1669
+ it "does not add any criterion" do
1670
+ expect(selection.selector).to eq({})
1671
+ end
1672
+
1673
+ it "returns the query" do
1674
+ expect(selection).to eq(query)
1675
+ end
1676
+
1677
+ it "returns a cloned query" do
1678
+ expect(selection).not_to equal(query)
1679
+ end
1680
+
1681
+ it 'does not mutate receiver' do
1682
+ expect(query.negating).to be nil
1683
+
1684
+ selection
1685
+ expect(query.negating).to be nil
1686
+ end
1687
+
1688
+ shared_examples_for 'negates the next condition' do
1689
+ let(:selection) do
1690
+ query.not.send(query_method, field: [ 1, 2 ])
1691
+ end
1692
+
1693
+ it "negates the next condition" do
1694
+ expect(selection.selector).to eq(
1695
+ { "field" => { "$not" => { operator => [ 1, 2 ] }}}
1696
+ )
1697
+ end
1698
+
1699
+ it_behaves_like 'returns a cloned query'
1700
+
1701
+ it "removes the negation on the clone" do
1702
+ expect(selection).to_not be_negating
1703
+ end
1704
+ end
1705
+
1706
+ context "when the next condition is #all" do
1707
+ let(:query_method) { :all }
1708
+ let(:operator) { '$all' }
1709
+
1710
+ it_behaves_like 'negates the next condition'
1711
+ end
1712
+
1713
+ context "when the next condition is #in" do
1714
+ let(:query_method) { :in }
1715
+ let(:operator) { '$in' }
1716
+
1717
+ it_behaves_like 'negates the next condition'
1718
+ end
1719
+
1720
+ context "when the next condition is #nin" do
1721
+ let(:query_method) { :nin }
1722
+ let(:operator) { '$nin' }
1723
+
1724
+ it_behaves_like 'negates the next condition'
1725
+ end
1726
+
1727
+ context "when the following criteria is a gt method" do
1728
+
1729
+ let(:selection) do
1730
+ query.not.gt(age: 50)
1731
+ end
1732
+
1733
+ it "negates the gt selection" do
1734
+ expect(selection.selector).to eq(
1735
+ { "age" => { "$not" => { "$gt" => 50 }}}
1736
+ )
1737
+ end
1738
+
1739
+ it_behaves_like 'returns a cloned query'
1740
+
1741
+ it "removes the negation on the clone" do
1742
+ expect(selection).to_not be_negating
1743
+ end
1744
+ end
1745
+
1746
+ context "when the criteria uses Key" do
1747
+
1748
+ let(:selection) do
1749
+ query.not(:age.gt => 50)
1750
+ end
1751
+
1752
+ it "negates the gt selection" do
1753
+ expect(selection.selector).to eq(
1754
+ '$and' => ['$nor' => ['age' => {'$gt' => 50}]]
1755
+ )
1756
+ end
1757
+
1758
+ it_behaves_like 'returns a cloned query'
1759
+
1760
+ it "removes the negation on the clone" do
1761
+ expect(selection).to_not be_negating
1762
+ end
1763
+ end
1764
+
1765
+ context "when the following criteria is a where" do
1766
+
1767
+ let(:selection) do
1768
+ query.not.where(field: 1, :other.in => [ 1, 2 ])
1769
+ end
1770
+
1771
+ it "negates the selection with an operator" do
1772
+ expect(selection.selector).to eq(
1773
+ { "field" => { "$ne" => 1 }, "other" => { "$not" => { "$in" => [ 1, 2 ] }}}
1774
+ )
1775
+ end
1776
+
1777
+ it_behaves_like 'returns a cloned query'
1778
+
1779
+ it "removes the negation on the clone" do
1780
+ expect(selection).to_not be_negating
1781
+ end
1782
+ end
1783
+
1784
+ context "when the following criteria is a where with a regexp" do
1785
+
1786
+ let(:selection) do
1787
+ query.not.where(field: 1, other: /test/)
1788
+ end
1789
+
1790
+ it "negates the selection with an operator" do
1791
+ expect(selection.selector).to eq(
1792
+ { "field" => { "$ne" => 1 }, "other" => { "$not" => /test/ } }
1793
+ )
1794
+ end
1795
+
1796
+ it_behaves_like 'returns a cloned query'
1797
+
1798
+ it "removes the negation on the clone" do
1799
+ expect(selection).to_not be_negating
1800
+ end
1801
+ end
1802
+
1803
+ context 'when the following criteria uses string were form' do
1804
+
1805
+ let(:selection) do
1806
+ query.not.where('hello world')
1807
+ end
1808
+
1809
+ it "negates the selection with an operator" do
1810
+ expect(selection.selector).to eq(
1811
+ '$and' => [{'$nor' => [{'$where' => 'hello world'}]}]
1812
+ )
1813
+ end
1814
+
1815
+ it_behaves_like 'returns a cloned query'
1816
+
1817
+ it "removes the negation on the clone" do
1818
+ expect(selection).to_not be_negating
1819
+ end
1820
+
1821
+ end
1822
+ end
1823
+
1824
+ context "when provided nil" do
1825
+
1826
+ let(:selection) do
1827
+ query.not(nil)
1828
+ end
1829
+
1830
+ it "does not add any criterion" do
1831
+ expect(selection.selector).to eq({})
1832
+ end
1833
+
1834
+ it "returns the query" do
1835
+ expect(selection).to eq(query)
1836
+ end
1837
+
1838
+ it_behaves_like 'returns a cloned query'
1839
+ end
1840
+
1841
+ context "when provided a single criterion" do
1842
+
1843
+ let(:selection) do
1844
+ query.not(field: /test/)
1845
+ end
1846
+
1847
+ it "adds the $not selector" do
1848
+ expect(selection.selector).to eq({
1849
+ "field" => { "$not" => /test/ }
1850
+ })
1851
+ end
1852
+
1853
+ it_behaves_like 'returns a cloned query'
1854
+ end
1855
+
1856
+ context "when negating a field in the original selector" do
1857
+ let(:query) do
1858
+ Mongoid::Query.new("id" => "_id").where(field: 'foo')
1859
+ end
1860
+
1861
+ let(:selection) do
1862
+ query.not(field: 'bar')
1863
+ end
1864
+
1865
+ it "combines the conditions" do
1866
+ expect(selection.selector).to eq({
1867
+ "field" => 'foo',
1868
+ '$and' => [{'$nor' => [{ "field" => 'bar' }]}],
1869
+ })
1870
+ end
1871
+
1872
+ it_behaves_like 'returns a cloned query'
1873
+ end
1874
+
1875
+ context "when provided multiple criteria" do
1876
+
1877
+ context "when the criteria are for different fields" do
1878
+
1879
+ let(:selection) do
1880
+ query.not(first: /1/, second: /2/)
1881
+ end
1882
+
1883
+ it "adds the $not selectors" do
1884
+ expect(selection.selector).to eq({
1885
+ "first" => { "$not" => /1/ },
1886
+ "second" => { "$not" => /2/ }
1887
+ })
1888
+ end
1889
+
1890
+ it_behaves_like 'returns a cloned query'
1891
+ end
1892
+
1893
+ context "when the criteria are given in separate arguments" do
1894
+
1895
+ let(:selection) do
1896
+ query.not({first: /1/}, {second: /2/})
1897
+ end
1898
+
1899
+ it "adds the $not selectors" do
1900
+ expect(selection.selector).to eq({
1901
+ "first" => { "$not" => /1/ },
1902
+ "second" => { "$not" => /2/ }
1903
+ })
1904
+ end
1905
+
1906
+ it_behaves_like 'returns a cloned query'
1907
+ end
1908
+ end
1909
+
1910
+ context "when chaining the criterion" do
1911
+
1912
+ context "when the criterion are for different fields" do
1913
+
1914
+ let(:selection) do
1915
+ query.not(first: /1/).not(second: /2/)
1916
+ end
1917
+
1918
+ it "adds the $not selectors" do
1919
+ expect(selection.selector).to eq({
1920
+ "first" => { "$not" => /1/ },
1921
+ "second" => { "$not" => /2/ }
1922
+ })
1923
+ end
1924
+
1925
+ it_behaves_like 'returns a cloned query'
1926
+ end
1927
+
1928
+ context "when the criterion are on the same field" do
1929
+
1930
+ let(:selection) do
1931
+ query.not(first: /1/).not(first: /2/)
1932
+ end
1933
+
1934
+ it "combines conditions" do
1935
+ expect(selection.selector).to eq(
1936
+ "first" => { "$not" => /1/ },
1937
+ '$and' => [{'$nor' => [{'first' => /2/}]}],
1938
+ )
1939
+ end
1940
+
1941
+ it_behaves_like 'returns a cloned query'
1942
+ end
1943
+
1944
+ context "when the criterion are a double negative" do
1945
+
1946
+ let(:selection) do
1947
+ query.not.where(:first.not => /1/)
1948
+ end
1949
+
1950
+ it "does not double the $not selector" do
1951
+ expect(selection.selector).to eq({
1952
+ "first" => { "$not" => /1/ }
1953
+ })
1954
+ end
1955
+
1956
+ it_behaves_like 'returns a cloned query'
1957
+ end
1958
+ end
1959
+
1960
+ context 'when argument is a Criteria' do
1961
+ let(:query) do
1962
+ Mongoid::Query.new.where(hello: 'world')
1963
+ end
1964
+
1965
+ let(:other) do
1966
+ Mongoid::Query.new.where(foo: 'bar')
1967
+ end
1968
+
1969
+ let(:result) { query.not(other) }
1970
+
1971
+ it 'combines' do
1972
+ expect(result.selector).to eq('hello' => 'world', 'foo' => {'$ne' => 'bar'})
1973
+ end
1974
+ end
1975
+
1976
+ context 'when argument is a simple Criteria with multiple fields' do
1977
+ let(:query) do
1978
+ Mongoid::Query.new.where(hello: 'world')
1979
+ end
1980
+
1981
+ let(:other) do
1982
+ Mongoid::Query.new.where(a: 1, b: 2)
1983
+ end
1984
+
1985
+ let(:result) { query.not(other) }
1986
+
1987
+ it 'combines fields into top level criteria' do
1988
+ expect(result.selector).to eq('hello' => 'world',
1989
+ 'a' => {'$ne' => 1}, 'b' => {'$ne' => 2})
1990
+ end
1991
+ end
1992
+
1993
+ context 'when argument is a complex Criteria' do
1994
+ let(:query) do
1995
+ Mongoid::Query.new.where(hello: 'world')
1996
+ end
1997
+
1998
+ let(:other) do
1999
+ Mongoid::Query.new.where('$nor' => [{a: 1, b: 2}])
2000
+ end
2001
+
2002
+ let(:result) { query.not(other) }
2003
+
2004
+ it 'combines with $and of $nor' do
2005
+ expect(result.selector).to eq('hello' => 'world', '$and' => [{'$nor' => [{
2006
+ '$nor' => [{'a' => 1, 'b' => 2}]}]}])
2007
+ end
2008
+ end
2009
+
2010
+ context 'when argument is a mix of Criteria and hashes' do
2011
+ let(:query) do
2012
+ Mongoid::Query.new.where(hello: 'world')
2013
+ end
2014
+
2015
+ let(:other1) do
2016
+ Mongoid::Query.new.where(foo: 'bar')
2017
+ end
2018
+
2019
+ let(:other2) do
2020
+ {bar: 42}
2021
+ end
2022
+
2023
+ let(:other3) do
2024
+ Mongoid::Query.new.where(a: 2)
2025
+ end
2026
+
2027
+ let(:result) { query.not(other1, other2, other3) }
2028
+
2029
+ it 'combines' do
2030
+ expect(result.selector).to eq('hello' => 'world',
2031
+ 'foo' => {'$ne' => 'bar'},
2032
+ 'bar' => {'$ne' => 42},
2033
+ 'a' => {'$ne' => 2},
2034
+ )
2035
+ end
2036
+ end
2037
+
2038
+ context 'when giving multiple conditions in one call on the same key with symbol operator' do
2039
+
2040
+ context 'non-regexp argument' do
2041
+ let(:selection) do
2042
+ query.not(field: 1, :field.gt => 0)
2043
+ end
2044
+
2045
+ it 'combines conditions with $eq' do
2046
+ selection.selector.should == {
2047
+ '$and' => ['$nor' => [
2048
+ 'field' => {'$eq' => 1, '$gt' => 0},
2049
+ ]]
2050
+ }
2051
+ end
2052
+ end
2053
+
2054
+ context 'regexp argument' do
2055
+ let(:selection) do
2056
+ query.not(field: /t/, :field.gt => 0)
2057
+ end
2058
+
2059
+ it 'combines conditions with $regex' do
2060
+ selection.selector.should == {
2061
+ '$and' => ['$nor' => [
2062
+ 'field' => {'$regex' => /t/, '$gt' => 0},
2063
+ ]]
2064
+ }
2065
+ end
2066
+ end
2067
+ end
2068
+ end
2069
+ end