mongoid 6.4.4 → 7.3.2

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