mongoid 9.0.11 → 9.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1033) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +8 -8
  3. data/README.md +5 -11
  4. data/Rakefile +35 -38
  5. data/lib/config/locales/en.yml +60 -0
  6. data/lib/mongoid/association/accessors.rb +27 -26
  7. data/lib/mongoid/association/bindable.rb +43 -45
  8. data/lib/mongoid/association/builders.rb +18 -15
  9. data/lib/mongoid/association/constrainable.rb +3 -5
  10. data/lib/mongoid/association/depending.rb +43 -43
  11. data/lib/mongoid/association/eager.rb +56 -13
  12. data/lib/mongoid/association/eager_load/discriminated_inclusion.rb +88 -0
  13. data/lib/mongoid/association/eager_load/embedded_distributor.rb +151 -0
  14. data/lib/mongoid/association/eager_load/inclusion.rb +173 -0
  15. data/lib/mongoid/association/eager_load/inclusion_tree.rb +96 -0
  16. data/lib/mongoid/association/eager_load/lookup_pipeline.rb +121 -0
  17. data/lib/mongoid/association/eager_load/polymorphic_preloader.rb +61 -0
  18. data/lib/mongoid/association/eager_load/polymorphic_targets.rb +151 -0
  19. data/lib/mongoid/association/eager_loadable.rb +108 -23
  20. data/lib/mongoid/association/embedded/batchable.rb +28 -30
  21. data/lib/mongoid/association/embedded/cyclic.rb +8 -11
  22. data/lib/mongoid/association/embedded/eager.rb +1 -6
  23. data/lib/mongoid/association/embedded/embedded_in/binding.rb +6 -9
  24. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -3
  25. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -0
  26. data/lib/mongoid/association/embedded/embedded_in.rb +25 -22
  27. data/lib/mongoid/association/embedded/embeds_many/binding.rb +0 -2
  28. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +2 -3
  29. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +7 -2
  30. data/lib/mongoid/association/embedded/embeds_many.rb +24 -21
  31. data/lib/mongoid/association/embedded/embeds_one/binding.rb +0 -2
  32. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +2 -6
  33. data/lib/mongoid/association/embedded/embeds_one.rb +21 -18
  34. data/lib/mongoid/association/embedded.rb +0 -1
  35. data/lib/mongoid/association/macros.rb +16 -8
  36. data/lib/mongoid/association/many.rb +75 -3
  37. data/lib/mongoid/association/marshalable.rb +0 -3
  38. data/lib/mongoid/association/nested/many.rb +52 -18
  39. data/lib/mongoid/association/nested/nested_buildable.rb +20 -9
  40. data/lib/mongoid/association/nested/one.rb +10 -8
  41. data/lib/mongoid/association/nested.rb +1 -3
  42. data/lib/mongoid/association/one.rb +0 -3
  43. data/lib/mongoid/association/options.rb +25 -7
  44. data/lib/mongoid/association/referenced/auto_save.rb +0 -2
  45. data/lib/mongoid/association/referenced/belongs_to/binding.rb +11 -15
  46. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +23 -5
  47. data/lib/mongoid/association/referenced/belongs_to/eager.rb +7 -4
  48. data/lib/mongoid/association/referenced/belongs_to.rb +49 -43
  49. data/lib/mongoid/association/referenced/counter_cache.rb +7 -12
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +0 -2
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +8 -4
  52. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +0 -3
  53. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +57 -47
  54. data/lib/mongoid/association/referenced/has_many/binding.rb +0 -2
  55. data/lib/mongoid/association/referenced/has_many/buildable.rb +11 -5
  56. data/lib/mongoid/association/referenced/has_many/eager.rb +0 -3
  57. data/lib/mongoid/association/referenced/has_many/enumerable.rb +109 -38
  58. data/lib/mongoid/association/referenced/has_many/proxy.rb +110 -7
  59. data/lib/mongoid/association/referenced/has_many.rb +30 -24
  60. data/lib/mongoid/association/referenced/has_many_through/eager.rb +99 -0
  61. data/lib/mongoid/association/referenced/has_many_through/proxy.rb +68 -0
  62. data/lib/mongoid/association/referenced/has_many_through.rb +201 -0
  63. data/lib/mongoid/association/referenced/has_one/binding.rb +0 -2
  64. data/lib/mongoid/association/referenced/has_one/buildable.rb +11 -9
  65. data/lib/mongoid/association/referenced/has_one/eager.rb +0 -3
  66. data/lib/mongoid/association/referenced/has_one.rb +27 -21
  67. data/lib/mongoid/association/referenced/has_one_through/eager.rb +65 -0
  68. data/lib/mongoid/association/referenced/has_one_through/proxy.rb +30 -0
  69. data/lib/mongoid/association/referenced/has_one_through.rb +167 -0
  70. data/lib/mongoid/association/referenced/syncable.rb +30 -34
  71. data/lib/mongoid/association/referenced.rb +2 -1
  72. data/lib/mongoid/association/reflections.rb +0 -3
  73. data/lib/mongoid/association/relatable.rb +108 -65
  74. data/lib/mongoid/association.rb +19 -15
  75. data/lib/mongoid/atomic/modifiers.rb +65 -25
  76. data/lib/mongoid/atomic/paths/embedded/many.rb +4 -7
  77. data/lib/mongoid/atomic/paths/embedded/one.rb +2 -4
  78. data/lib/mongoid/atomic/paths/embedded.rb +3 -6
  79. data/lib/mongoid/atomic/paths/root.rb +1 -4
  80. data/lib/mongoid/atomic/paths.rb +2 -3
  81. data/lib/mongoid/atomic.rb +0 -3
  82. data/lib/mongoid/attributes/dynamic.rb +6 -7
  83. data/lib/mongoid/attributes/nested.rb +8 -10
  84. data/lib/mongoid/attributes/projector.rb +7 -20
  85. data/lib/mongoid/attributes/readonly.rb +6 -11
  86. data/lib/mongoid/attributes.rb +18 -34
  87. data/lib/mongoid/cacheable.rb +24 -6
  88. data/lib/mongoid/clients/factory.rb +13 -22
  89. data/lib/mongoid/clients/options.rb +2 -5
  90. data/lib/mongoid/clients/sessions.rb +50 -60
  91. data/lib/mongoid/clients/storage_options.rb +1 -4
  92. data/lib/mongoid/clients/validators/storage.rb +2 -3
  93. data/lib/mongoid/clients/validators.rb +1 -2
  94. data/lib/mongoid/clients.rb +8 -11
  95. data/lib/mongoid/collection_configurable.rb +18 -14
  96. data/lib/mongoid/composable.rb +30 -34
  97. data/lib/mongoid/config/defaults.rb +6 -4
  98. data/lib/mongoid/config/encryption.rb +36 -21
  99. data/lib/mongoid/config/environment.rb +7 -16
  100. data/lib/mongoid/config/introspection.rb +14 -16
  101. data/lib/mongoid/config/options.rb +16 -10
  102. data/lib/mongoid/config/validators/async_query_executor.rb +3 -6
  103. data/lib/mongoid/config/validators/client.rb +12 -15
  104. data/lib/mongoid/config/validators/option.rb +3 -5
  105. data/lib/mongoid/config/validators.rb +3 -4
  106. data/lib/mongoid/config.rb +188 -47
  107. data/lib/mongoid/contextual/aggregable/memory.rb +7 -5
  108. data/lib/mongoid/contextual/aggregable/mongo.rb +20 -22
  109. data/lib/mongoid/contextual/aggregable/none.rb +2 -4
  110. data/lib/mongoid/contextual/aggregable.rb +5 -7
  111. data/lib/mongoid/contextual/atomic.rb +20 -24
  112. data/lib/mongoid/contextual/command.rb +0 -3
  113. data/lib/mongoid/contextual/map_reduce.rb +12 -16
  114. data/lib/mongoid/contextual/memory.rb +87 -69
  115. data/lib/mongoid/contextual/mongo/documents_loader.rb +2 -3
  116. data/lib/mongoid/contextual/mongo.rb +169 -85
  117. data/lib/mongoid/contextual/none.rb +9 -9
  118. data/lib/mongoid/contextual/queryable.rb +1 -4
  119. data/lib/mongoid/contextual.rb +18 -7
  120. data/lib/mongoid/copyable.rb +7 -9
  121. data/lib/mongoid/criteria/findable.rb +5 -7
  122. data/lib/mongoid/criteria/includable.rb +67 -14
  123. data/lib/mongoid/criteria/inspectable.rb +2 -5
  124. data/lib/mongoid/criteria/marshalable.rb +4 -8
  125. data/lib/mongoid/criteria/modifiable.rb +3 -11
  126. data/lib/mongoid/criteria/options.rb +0 -3
  127. data/lib/mongoid/criteria/permission.rb +34 -37
  128. data/lib/mongoid/criteria/queryable/aggregable.rb +9 -10
  129. data/lib/mongoid/criteria/queryable/expandable.rb +4 -9
  130. data/lib/mongoid/criteria/queryable/extensions/array.rb +7 -10
  131. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +3 -5
  132. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -4
  133. data/lib/mongoid/criteria/queryable/extensions/date.rb +2 -6
  134. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +3 -7
  135. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -4
  136. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +20 -11
  137. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +15 -11
  138. data/lib/mongoid/criteria/queryable/extensions/object.rb +7 -8
  139. data/lib/mongoid/criteria/queryable/extensions/range.rb +6 -9
  140. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +10 -12
  141. data/lib/mongoid/criteria/queryable/extensions/set.rb +4 -6
  142. data/lib/mongoid/criteria/queryable/extensions/string.rb +5 -9
  143. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -7
  144. data/lib/mongoid/criteria/queryable/extensions/time.rb +2 -6
  145. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +2 -12
  146. data/lib/mongoid/criteria/queryable/extensions.rb +18 -21
  147. data/lib/mongoid/criteria/queryable/key.rb +12 -18
  148. data/lib/mongoid/criteria/queryable/macroable.rb +0 -3
  149. data/lib/mongoid/criteria/queryable/mergeable.rb +35 -39
  150. data/lib/mongoid/criteria/queryable/optional.rb +17 -18
  151. data/lib/mongoid/criteria/queryable/options.rb +20 -9
  152. data/lib/mongoid/criteria/queryable/pipeline.rb +6 -9
  153. data/lib/mongoid/criteria/queryable/selectable.rb +253 -199
  154. data/lib/mongoid/criteria/queryable/selector.rb +20 -29
  155. data/lib/mongoid/criteria/queryable/smash.rb +1 -6
  156. data/lib/mongoid/criteria/queryable/storable.rb +20 -39
  157. data/lib/mongoid/criteria/queryable.rb +25 -15
  158. data/lib/mongoid/criteria/scopable.rb +5 -11
  159. data/lib/mongoid/criteria/translator.rb +5 -8
  160. data/lib/mongoid/criteria.rb +109 -54
  161. data/lib/mongoid/deprecable.rb +45 -5
  162. data/lib/mongoid/deprecation.rb +2 -6
  163. data/lib/mongoid/document.rb +1 -1
  164. data/lib/mongoid/encryptable.rb +47 -2
  165. data/lib/mongoid/equality.rb +4 -5
  166. data/lib/mongoid/errors/ambiguous_relationship.rb +2 -5
  167. data/lib/mongoid/errors/attribute_not_loaded.rb +1 -4
  168. data/lib/mongoid/errors/callback.rb +1 -4
  169. data/lib/mongoid/errors/config_redactor.rb +43 -0
  170. data/lib/mongoid/errors/create_collection_failure.rb +8 -11
  171. data/lib/mongoid/errors/criteria_argument_required.rb +2 -5
  172. data/lib/mongoid/errors/delete_restriction.rb +1 -4
  173. data/lib/mongoid/errors/document_not_destroyed.rb +1 -4
  174. data/lib/mongoid/errors/document_not_found.rb +16 -21
  175. data/lib/mongoid/errors/drop_collection_failure.rb +7 -10
  176. data/lib/mongoid/errors/empty_config_file.rb +1 -4
  177. data/lib/mongoid/errors/immutable_attribute.rb +1 -4
  178. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -4
  179. data/lib/mongoid/errors/in_memory_regexp_timeout.rb +26 -0
  180. data/lib/mongoid/errors/invalid_async_query_executor.rb +2 -5
  181. data/lib/mongoid/errors/invalid_auto_encryption_configuration.rb +2 -5
  182. data/lib/mongoid/errors/invalid_collection.rb +1 -3
  183. data/lib/mongoid/errors/invalid_config_file.rb +1 -4
  184. data/lib/mongoid/errors/invalid_config_option.rb +2 -5
  185. data/lib/mongoid/errors/invalid_dependent_strategy.rb +6 -10
  186. data/lib/mongoid/errors/invalid_discriminator_key_target.rb +2 -4
  187. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +1 -4
  188. data/lib/mongoid/errors/invalid_elem_match_operator.rb +5 -9
  189. data/lib/mongoid/errors/invalid_estimated_count_criteria.rb +1 -4
  190. data/lib/mongoid/errors/invalid_estimated_count_scoping.rb +1 -4
  191. data/lib/mongoid/errors/invalid_expression_operator.rb +3 -7
  192. data/lib/mongoid/errors/invalid_field.rb +2 -5
  193. data/lib/mongoid/errors/invalid_field_operator.rb +5 -9
  194. data/lib/mongoid/errors/invalid_field_option.rb +2 -5
  195. data/lib/mongoid/errors/invalid_field_type.rb +1 -4
  196. data/lib/mongoid/errors/invalid_find.rb +1 -4
  197. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +1 -4
  198. data/lib/mongoid/errors/invalid_includes.rb +3 -6
  199. data/lib/mongoid/errors/invalid_index.rb +1 -4
  200. data/lib/mongoid/errors/invalid_options.rb +1 -4
  201. data/lib/mongoid/errors/invalid_path.rb +1 -4
  202. data/lib/mongoid/errors/invalid_persistence_option.rb +4 -7
  203. data/lib/mongoid/errors/invalid_query.rb +6 -11
  204. data/lib/mongoid/errors/invalid_relation.rb +10 -13
  205. data/lib/mongoid/errors/invalid_relation_option.rb +4 -7
  206. data/lib/mongoid/errors/invalid_scope.rb +1 -4
  207. data/lib/mongoid/errors/invalid_session_nesting.rb +0 -3
  208. data/lib/mongoid/errors/invalid_set_polymorphic_relation.rb +2 -4
  209. data/lib/mongoid/errors/invalid_storage_options.rb +1 -4
  210. data/lib/mongoid/errors/invalid_time.rb +1 -4
  211. data/lib/mongoid/errors/invalid_transaction_nesting.rb +0 -3
  212. data/lib/mongoid/errors/inverse_not_found.rb +1 -4
  213. data/lib/mongoid/errors/mixed_client_configuration.rb +2 -5
  214. data/lib/mongoid/errors/mixed_relations.rb +1 -3
  215. data/lib/mongoid/errors/mongoid_error.rb +7 -11
  216. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -4
  217. data/lib/mongoid/errors/no_client_config.rb +1 -4
  218. data/lib/mongoid/errors/no_client_database.rb +2 -5
  219. data/lib/mongoid/errors/no_client_hosts.rb +2 -5
  220. data/lib/mongoid/errors/no_clients_config.rb +1 -4
  221. data/lib/mongoid/errors/no_default_client.rb +1 -4
  222. data/lib/mongoid/errors/no_encryption_schema.rb +28 -0
  223. data/lib/mongoid/errors/no_environment.rb +1 -4
  224. data/lib/mongoid/errors/no_map_reduce_output.rb +1 -4
  225. data/lib/mongoid/errors/no_metadata.rb +1 -4
  226. data/lib/mongoid/errors/no_parent.rb +1 -4
  227. data/lib/mongoid/errors/readonly_association.rb +29 -0
  228. data/lib/mongoid/errors/readonly_attribute.rb +1 -4
  229. data/lib/mongoid/errors/readonly_document.rb +1 -4
  230. data/lib/mongoid/errors/rollback.rb +0 -2
  231. data/lib/mongoid/errors/scope_overwrite.rb +2 -4
  232. data/lib/mongoid/errors/sessions_not_supported.rb +0 -3
  233. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -3
  234. data/lib/mongoid/errors/transaction_error.rb +0 -3
  235. data/lib/mongoid/errors/transactions_not_supported.rb +0 -3
  236. data/lib/mongoid/errors/unknown_attribute.rb +1 -4
  237. data/lib/mongoid/errors/unknown_model.rb +1 -4
  238. data/lib/mongoid/errors/unregistered_class.rb +1 -1
  239. data/lib/mongoid/errors/unsaved_document.rb +1 -3
  240. data/lib/mongoid/errors/unsupported_isolation_level.rb +22 -0
  241. data/lib/mongoid/errors/unsupported_javascript.rb +1 -4
  242. data/lib/mongoid/errors/validations.rb +3 -5
  243. data/lib/mongoid/errors.rb +76 -72
  244. data/lib/mongoid/evolvable.rb +0 -3
  245. data/lib/mongoid/extensions/array.rb +5 -7
  246. data/lib/mongoid/extensions/big_decimal.rb +6 -7
  247. data/lib/mongoid/extensions/binary.rb +3 -6
  248. data/lib/mongoid/extensions/boolean.rb +4 -7
  249. data/lib/mongoid/extensions/bson_document.rb +28 -0
  250. data/lib/mongoid/extensions/date.rb +10 -14
  251. data/lib/mongoid/extensions/date_time.rb +2 -6
  252. data/lib/mongoid/extensions/decimal128.rb +1 -5
  253. data/lib/mongoid/extensions/false_class.rb +3 -5
  254. data/lib/mongoid/extensions/float.rb +5 -10
  255. data/lib/mongoid/extensions/hash.rb +5 -10
  256. data/lib/mongoid/extensions/integer.rb +5 -10
  257. data/lib/mongoid/extensions/module.rb +1 -4
  258. data/lib/mongoid/extensions/nil_class.rb +0 -1
  259. data/lib/mongoid/extensions/object.rb +9 -14
  260. data/lib/mongoid/extensions/object_id.rb +2 -6
  261. data/lib/mongoid/extensions/range.rb +14 -15
  262. data/lib/mongoid/extensions/raw_value.rb +0 -3
  263. data/lib/mongoid/extensions/regexp.rb +3 -6
  264. data/lib/mongoid/extensions/set.rb +3 -4
  265. data/lib/mongoid/extensions/string.rb +8 -12
  266. data/lib/mongoid/extensions/symbol.rb +3 -7
  267. data/lib/mongoid/extensions/time.rb +24 -26
  268. data/lib/mongoid/extensions/time_with_zone.rb +4 -7
  269. data/lib/mongoid/extensions/true_class.rb +3 -5
  270. data/lib/mongoid/extensions/vector.rb +64 -0
  271. data/lib/mongoid/extensions.rb +27 -26
  272. data/lib/mongoid/factory.rb +5 -9
  273. data/lib/mongoid/field_readable.rb +69 -0
  274. data/lib/mongoid/fields/encrypted.rb +0 -1
  275. data/lib/mongoid/fields/foreign_key.rb +9 -10
  276. data/lib/mongoid/fields/localized.rb +12 -12
  277. data/lib/mongoid/fields/standard.rb +5 -7
  278. data/lib/mongoid/fields/validators/macro.rb +23 -34
  279. data/lib/mongoid/fields/validators.rb +1 -2
  280. data/lib/mongoid/fields.rb +151 -58
  281. data/lib/mongoid/findable.rb +82 -53
  282. data/lib/mongoid/indexable/specification.rb +20 -6
  283. data/lib/mongoid/indexable/validators/options.rb +33 -40
  284. data/lib/mongoid/indexable.rb +53 -40
  285. data/lib/mongoid/inspectable.rb +4 -7
  286. data/lib/mongoid/interceptable.rb +41 -40
  287. data/lib/mongoid/loadable.rb +17 -18
  288. data/lib/mongoid/loggable.rb +4 -8
  289. data/lib/mongoid/matchable.rb +6 -3
  290. data/lib/mongoid/matcher/all.rb +2 -5
  291. data/lib/mongoid/matcher/and.rb +0 -3
  292. data/lib/mongoid/matcher/bits.rb +13 -8
  293. data/lib/mongoid/matcher/bits_all_clear.rb +1 -3
  294. data/lib/mongoid/matcher/bits_all_set.rb +1 -3
  295. data/lib/mongoid/matcher/bits_any_clear.rb +1 -3
  296. data/lib/mongoid/matcher/bits_any_set.rb +1 -3
  297. data/lib/mongoid/matcher/elem_match.rb +13 -15
  298. data/lib/mongoid/matcher/elem_match_expression.rb +0 -3
  299. data/lib/mongoid/matcher/eq.rb +0 -3
  300. data/lib/mongoid/matcher/eq_impl.rb +12 -17
  301. data/lib/mongoid/matcher/eq_impl_with_regexp.rb +4 -9
  302. data/lib/mongoid/matcher/exists.rb +1 -4
  303. data/lib/mongoid/matcher/expression.rb +5 -10
  304. data/lib/mongoid/matcher/expression_operator.rb +1 -3
  305. data/lib/mongoid/matcher/field_expression.rb +10 -13
  306. data/lib/mongoid/matcher/field_operator.rb +4 -6
  307. data/lib/mongoid/matcher/gt.rb +0 -3
  308. data/lib/mongoid/matcher/gte.rb +0 -3
  309. data/lib/mongoid/matcher/in.rb +9 -12
  310. data/lib/mongoid/matcher/lt.rb +0 -3
  311. data/lib/mongoid/matcher/lte.rb +0 -3
  312. data/lib/mongoid/matcher/mod.rb +4 -8
  313. data/lib/mongoid/matcher/ne.rb +0 -3
  314. data/lib/mongoid/matcher/nin.rb +0 -3
  315. data/lib/mongoid/matcher/nor.rb +1 -6
  316. data/lib/mongoid/matcher/not.rb +0 -3
  317. data/lib/mongoid/matcher/or.rb +0 -3
  318. data/lib/mongoid/matcher/regex.rb +9 -13
  319. data/lib/mongoid/matcher/regexp_budget.rb +372 -0
  320. data/lib/mongoid/matcher/size.rb +2 -5
  321. data/lib/mongoid/matcher/type.rb +32 -37
  322. data/lib/mongoid/matcher.rb +8 -15
  323. data/lib/mongoid/model_resolver.rb +1 -0
  324. data/lib/mongoid/persistable/creatable.rb +23 -7
  325. data/lib/mongoid/persistable/deletable.rb +6 -7
  326. data/lib/mongoid/persistable/destroyable.rb +2 -6
  327. data/lib/mongoid/persistable/incrementable.rb +1 -3
  328. data/lib/mongoid/persistable/logical.rb +3 -5
  329. data/lib/mongoid/persistable/maxable.rb +2 -4
  330. data/lib/mongoid/persistable/minable.rb +2 -4
  331. data/lib/mongoid/persistable/multipliable.rb +1 -3
  332. data/lib/mongoid/persistable/poppable.rb +2 -4
  333. data/lib/mongoid/persistable/pullable.rb +3 -5
  334. data/lib/mongoid/persistable/pushable.rb +5 -7
  335. data/lib/mongoid/persistable/renamable.rb +1 -3
  336. data/lib/mongoid/persistable/savable.rb +0 -3
  337. data/lib/mongoid/persistable/settable.rb +4 -13
  338. data/lib/mongoid/persistable/unsettable.rb +1 -3
  339. data/lib/mongoid/persistable/updatable.rb +23 -33
  340. data/lib/mongoid/persistable/upsertable.rb +8 -10
  341. data/lib/mongoid/persistable.rb +28 -27
  342. data/lib/mongoid/persistence_context.rb +69 -41
  343. data/lib/mongoid/pluckable.rb +0 -2
  344. data/lib/mongoid/positional.rb +5 -11
  345. data/lib/mongoid/railtie.rb +16 -22
  346. data/lib/mongoid/railties/console_sandbox.rb +6 -8
  347. data/lib/mongoid/railties/controller_runtime.rb +7 -11
  348. data/lib/mongoid/railties/database.rake +42 -44
  349. data/lib/mongoid/scopable.rb +23 -31
  350. data/lib/mongoid/search_indexable.rb +378 -7
  351. data/lib/mongoid/selectable.rb +1 -3
  352. data/lib/mongoid/serializable.rb +18 -12
  353. data/lib/mongoid/shardable.rb +8 -17
  354. data/lib/mongoid/stateful.rb +5 -10
  355. data/lib/mongoid/stringified_symbol.rb +5 -9
  356. data/lib/mongoid/tasks/database.rake +31 -32
  357. data/lib/mongoid/tasks/database.rb +51 -39
  358. data/lib/mongoid/tasks/encryption.rb +10 -15
  359. data/lib/mongoid/threaded/lifecycle.rb +6 -9
  360. data/lib/mongoid/threaded.rb +168 -32
  361. data/lib/mongoid/timestamps/created/short.rb +2 -3
  362. data/lib/mongoid/timestamps/created.rb +1 -2
  363. data/lib/mongoid/timestamps/short.rb +0 -1
  364. data/lib/mongoid/timestamps/timeless.rb +92 -23
  365. data/lib/mongoid/timestamps/updated/short.rb +2 -3
  366. data/lib/mongoid/timestamps/updated.rb +2 -5
  367. data/lib/mongoid/timestamps.rb +4 -6
  368. data/lib/mongoid/touchable.rb +19 -11
  369. data/lib/mongoid/traversable.rb +5 -4
  370. data/lib/mongoid/validatable/associated.rb +19 -7
  371. data/lib/mongoid/validatable/format.rb +0 -2
  372. data/lib/mongoid/validatable/length.rb +0 -2
  373. data/lib/mongoid/validatable/localizable.rb +0 -3
  374. data/lib/mongoid/validatable/macros.rb +0 -2
  375. data/lib/mongoid/validatable/numericality.rb +24 -3
  376. data/lib/mongoid/validatable/presence.rb +8 -10
  377. data/lib/mongoid/validatable/queryable.rb +0 -3
  378. data/lib/mongoid/validatable/uniqueness.rb +12 -14
  379. data/lib/mongoid/validatable.rb +15 -20
  380. data/lib/mongoid/version.rb +1 -1
  381. data/lib/mongoid/warnings.rb +10 -11
  382. data/lib/mongoid.rb +30 -34
  383. data/lib/rails/generators/mongoid/config/config_generator.rb +2 -4
  384. data/lib/rails/generators/mongoid/config/templates/mongoid.rb +4 -5
  385. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +2 -2
  386. data/lib/rails/generators/mongoid/model/model_generator.rb +5 -8
  387. data/lib/rails/generators/mongoid_generator.rb +6 -10
  388. data/lib/rails/mongoid.rb +1 -3
  389. data/spec/integration/active_job_spec.rb +1 -2
  390. data/spec/integration/app_spec.rb +149 -179
  391. data/spec/integration/associations/belongs_to_spec.rb +43 -28
  392. data/spec/integration/associations/embedded_dirty_spec.rb +0 -1
  393. data/spec/integration/associations/embedded_spec.rb +41 -43
  394. data/spec/integration/associations/embeds_many_spec.rb +46 -29
  395. data/spec/integration/associations/embeds_one_spec.rb +2 -1
  396. data/spec/integration/associations/foreign_key_spec.rb +10 -11
  397. data/spec/integration/associations/foreign_key_spec_models.rb +8 -9
  398. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +33 -15
  399. data/spec/integration/associations/has_many_spec.rb +17 -18
  400. data/spec/integration/associations/has_one_spec.rb +42 -45
  401. data/spec/integration/associations/nested_attributes_assignment_spec.rb +36 -39
  402. data/spec/integration/associations/reverse_population_spec.rb +4 -5
  403. data/spec/integration/associations/reverse_population_spec_models.rb +0 -1
  404. data/spec/integration/associations/scope_option_spec.rb +18 -20
  405. data/spec/integration/atomic/modifiers_spec.rb +72 -52
  406. data/spec/integration/bson_regexp_raw_spec.rb +2 -3
  407. data/spec/integration/caching_spec.rb +68 -0
  408. data/spec/integration/callbacks_models.rb +11 -9
  409. data/spec/integration/callbacks_spec.rb +78 -80
  410. data/spec/integration/contextual/empty_spec.rb +19 -20
  411. data/spec/integration/criteria/alias_query_spec.rb +12 -19
  412. data/spec/integration/criteria/date_field_spec.rb +1 -2
  413. data/spec/integration/criteria/default_scope_spec.rb +23 -18
  414. data/spec/integration/criteria/logical_spec.rb +18 -19
  415. data/spec/integration/criteria/range_spec.rb +77 -86
  416. data/spec/integration/criteria/raw_value_spec.rb +122 -109
  417. data/spec/integration/criteria/time_with_zone_spec.rb +33 -24
  418. data/spec/integration/discriminator_key_spec.rb +85 -85
  419. data/spec/integration/discriminator_value_spec.rb +70 -73
  420. data/spec/integration/document_spec.rb +9 -10
  421. data/spec/integration/dots_and_dollars_spec.rb +115 -120
  422. data/spec/integration/encryption_spec.rb +157 -9
  423. data/spec/integration/i18n_fallbacks_spec.rb +7 -8
  424. data/spec/integration/isolation_state_spec.rb +241 -0
  425. data/spec/integration/matcher_examples_spec.rb +145 -168
  426. data/spec/integration/matcher_operator_data/in.yml +6 -6
  427. data/spec/integration/matcher_operator_data/regex.yml +21 -0
  428. data/spec/integration/matcher_operator_spec.rb +16 -26
  429. data/spec/integration/matcher_regexp_timeout_spec.rb +215 -0
  430. data/spec/integration/matcher_spec.rb +31 -32
  431. data/spec/integration/persistence/collection_options_spec.rb +0 -2
  432. data/spec/integration/persistence/range_field_spec.rb +24 -2
  433. data/spec/integration/query_operator_guard_spec.rb +89 -0
  434. data/spec/integration/server_query_spec.rb +43 -37
  435. data/spec/integration/shardable_spec.rb +10 -11
  436. data/spec/integration/stringified_symbol_field_spec.rb +28 -43
  437. data/spec/lite_spec_helper.rb +11 -12
  438. data/spec/mongoid/association/accessors_spec.rb +197 -285
  439. data/spec/mongoid/association/auto_save_spec.rb +62 -93
  440. data/spec/mongoid/association/builders_spec.rb +121 -74
  441. data/spec/mongoid/association/constrainable_spec.rb +9 -22
  442. data/spec/mongoid/association/counter_cache_spec.rb +71 -104
  443. data/spec/mongoid/association/depending_spec.rb +166 -208
  444. data/spec/mongoid/association/eager_loadable_spec.rb +47 -0
  445. data/spec/mongoid/association/eager_spec.rb +416 -80
  446. data/spec/mongoid/association/embedded/cyclic_spec.rb +36 -48
  447. data/spec/mongoid/association/embedded/dirty_spec.rb +15 -20
  448. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +36 -54
  449. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +8 -15
  450. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +135 -175
  451. data/spec/mongoid/association/embedded/embedded_in_spec.rb +25 -127
  452. data/spec/mongoid/association/embedded/embeds_many/binding_spec.rb +9 -14
  453. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +38 -51
  454. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +1184 -1340
  455. data/spec/mongoid/association/embedded/embeds_many_models.rb +17 -17
  456. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +11 -11
  457. data/spec/mongoid/association/embedded/embeds_many_spec.rb +25 -138
  458. data/spec/mongoid/association/embedded/embeds_one/binding_spec.rb +15 -23
  459. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +18 -26
  460. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +204 -273
  461. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +0 -1
  462. data/spec/mongoid/association/embedded/embeds_one_models.rb +0 -1
  463. data/spec/mongoid/association/embedded/embeds_one_query_spec.rb +5 -6
  464. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -143
  465. data/spec/mongoid/association/fallback_spec.rb +425 -0
  466. data/spec/mongoid/association/macros_spec.rb +239 -300
  467. data/spec/mongoid/association/nested/many_spec.rb +51 -73
  468. data/spec/mongoid/association/nested/one_spec.rb +56 -80
  469. data/spec/mongoid/association/options_spec.rb +187 -310
  470. data/spec/mongoid/association/polymorphic_spec.rb +35 -53
  471. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +55 -76
  472. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +36 -41
  473. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +98 -101
  474. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +258 -345
  475. data/spec/mongoid/association/referenced/belongs_to_models.rb +4 -3
  476. data/spec/mongoid/association/referenced/belongs_to_query_spec.rb +3 -4
  477. data/spec/mongoid/association/referenced/belongs_to_spec.rb +91 -294
  478. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +42 -56
  479. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +41 -32
  480. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +36 -42
  481. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +8 -9
  482. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +819 -975
  483. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +9 -9
  484. data/spec/mongoid/association/referenced/has_and_belongs_to_many_query_spec.rb +5 -6
  485. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +109 -177
  486. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +29 -43
  487. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +53 -53
  488. data/spec/mongoid/association/referenced/has_many/eager_spec.rb +137 -67
  489. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +431 -675
  490. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +1 -2
  491. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +318 -11
  492. data/spec/mongoid/association/referenced/has_many_models.rb +1 -2
  493. data/spec/mongoid/association/referenced/has_many_query_spec.rb +3 -4
  494. data/spec/mongoid/association/referenced/has_many_spec.rb +44 -188
  495. data/spec/mongoid/association/referenced/has_many_through/eager_spec.rb +58 -0
  496. data/spec/mongoid/association/referenced/has_many_through/proxy_spec.rb +62 -0
  497. data/spec/mongoid/association/referenced/has_many_through_spec.rb +399 -0
  498. data/spec/mongoid/association/referenced/has_one/binding_spec.rb +26 -38
  499. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +28 -29
  500. data/spec/mongoid/association/referenced/has_one/eager_spec.rb +29 -42
  501. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +270 -332
  502. data/spec/mongoid/association/referenced/has_one_models.rb +1 -2
  503. data/spec/mongoid/association/referenced/has_one_query_spec.rb +3 -4
  504. data/spec/mongoid/association/referenced/has_one_spec.rb +40 -188
  505. data/spec/mongoid/association/referenced/has_one_through/eager_spec.rb +58 -0
  506. data/spec/mongoid/association/referenced/has_one_through/proxy_spec.rb +49 -0
  507. data/spec/mongoid/association/referenced/has_one_through_spec.rb +211 -0
  508. data/spec/mongoid/association/reflections_spec.rb +14 -24
  509. data/spec/mongoid/association/syncable_spec.rb +102 -125
  510. data/spec/mongoid/association_spec.rb +47 -70
  511. data/spec/mongoid/atomic/modifiers_spec.rb +184 -197
  512. data/spec/mongoid/atomic/paths/embedded/many_spec.rb +39 -52
  513. data/spec/mongoid/atomic/paths/embedded/one_spec.rb +35 -49
  514. data/spec/mongoid/atomic/paths/root_spec.rb +9 -15
  515. data/spec/mongoid/atomic/paths_spec.rb +81 -117
  516. data/spec/mongoid/atomic_spec.rb +156 -171
  517. data/spec/mongoid/attributes/dynamic_spec.rb +5 -6
  518. data/spec/mongoid/attributes/nested_spec.rb +1461 -1693
  519. data/spec/mongoid/attributes/nested_spec_models.rb +8 -9
  520. data/spec/mongoid/attributes/projector_spec.rb +2 -6
  521. data/spec/mongoid/attributes/readonly_spec.rb +73 -97
  522. data/spec/mongoid/attributes_spec.rb +669 -826
  523. data/spec/mongoid/cacheable_spec.rb +74 -44
  524. data/spec/mongoid/changeable_spec.rb +591 -733
  525. data/spec/mongoid/clients/factory_spec.rb +122 -154
  526. data/spec/mongoid/clients/options_spec.rb +40 -59
  527. data/spec/mongoid/clients/sessions_spec.rb +25 -44
  528. data/spec/mongoid/clients/transactions_spec.rb +33 -50
  529. data/spec/mongoid/clients/transactions_spec_models.rb +3 -4
  530. data/spec/mongoid/clients_spec.rb +265 -355
  531. data/spec/mongoid/collection_configurable_spec.rb +9 -12
  532. data/spec/mongoid/composable_spec.rb +2 -9
  533. data/spec/mongoid/config/defaults_spec.rb +56 -30
  534. data/spec/mongoid/config/encryption_spec.rb +282 -57
  535. data/spec/mongoid/config/environment_spec.rb +30 -40
  536. data/spec/mongoid/config/introspection_spec.rb +42 -37
  537. data/spec/mongoid/config/options_spec.rb +14 -21
  538. data/spec/mongoid/config_spec.rb +145 -195
  539. data/spec/mongoid/contextual/aggregable/memory_spec.rb +189 -135
  540. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +4 -7
  541. data/spec/mongoid/contextual/aggregable/mongo_spec.rb +149 -187
  542. data/spec/mongoid/contextual/aggregable/none_spec.rb +14 -16
  543. data/spec/mongoid/contextual/atomic_spec.rb +223 -271
  544. data/spec/mongoid/contextual/map_reduce_spec.rb +110 -138
  545. data/spec/mongoid/contextual/memory_spec.rb +883 -854
  546. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +12 -13
  547. data/spec/mongoid/contextual/mongo_spec.rb +1008 -1213
  548. data/spec/mongoid/contextual/none_spec.rb +54 -59
  549. data/spec/mongoid/contextual/short_circuit_spec.rb +139 -0
  550. data/spec/mongoid/copyable_spec.rb +254 -300
  551. data/spec/mongoid/copyable_spec_models.rb +0 -1
  552. data/spec/mongoid/criteria/findable_spec.rb +322 -387
  553. data/spec/mongoid/criteria/includable_spec.rb +1356 -432
  554. data/spec/mongoid/criteria/includable_spec_models.rb +16 -7
  555. data/spec/mongoid/criteria/inspectable_spec.rb +11 -14
  556. data/spec/mongoid/criteria/marshalable_spec.rb +11 -14
  557. data/spec/mongoid/criteria/modifiable_spec.rb +366 -512
  558. data/spec/mongoid/criteria/options_spec.rb +2 -7
  559. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +112 -141
  560. data/spec/mongoid/criteria/queryable/expandable_spec.rb +8 -11
  561. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +127 -184
  562. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +123 -60
  563. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +84 -117
  564. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +44 -65
  565. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +86 -108
  566. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +94 -33
  567. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +103 -138
  568. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +95 -34
  569. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +25 -38
  570. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +26 -28
  571. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +32 -54
  572. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +136 -130
  573. data/spec/mongoid/criteria/queryable/extensions/regexp_raw_spec.rb +16 -24
  574. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +15 -24
  575. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +12 -19
  576. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +46 -63
  577. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +28 -42
  578. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +73 -96
  579. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +71 -92
  580. data/spec/mongoid/criteria/queryable/key_spec.rb +32 -36
  581. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +44 -49
  582. data/spec/mongoid/criteria/queryable/optional_spec.rb +373 -486
  583. data/spec/mongoid/criteria/queryable/options_spec.rb +172 -123
  584. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +65 -87
  585. data/spec/mongoid/criteria/queryable/queryable_spec.rb +41 -53
  586. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +589 -679
  587. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +7 -11
  588. data/spec/mongoid/criteria/queryable/selectable_spec.rb +807 -998
  589. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +354 -190
  590. data/spec/mongoid/criteria/queryable/selector_spec.rb +294 -390
  591. data/spec/mongoid/criteria/queryable/smash_spec.rb +6 -11
  592. data/spec/mongoid/criteria/queryable/storable_spec.rb +54 -81
  593. data/spec/mongoid/criteria/queryable_mql_spec.rb +92 -0
  594. data/spec/mongoid/criteria/scopable_spec.rb +102 -138
  595. data/spec/mongoid/criteria/translator_spec.rb +59 -60
  596. data/spec/mongoid/criteria_projection_spec.rb +81 -99
  597. data/spec/mongoid/criteria_spec.rb +937 -949
  598. data/spec/mongoid/document_fields_spec.rb +28 -30
  599. data/spec/mongoid/document_persistence_context_spec.rb +13 -15
  600. data/spec/mongoid/document_query_spec.rb +9 -12
  601. data/spec/mongoid/document_spec.rb +317 -409
  602. data/spec/mongoid/encryptable_spec.rb +61 -0
  603. data/spec/mongoid/equality_spec.rb +69 -102
  604. data/spec/mongoid/errors/ambiguous_relationship_spec.rb +8 -11
  605. data/spec/mongoid/errors/attribute_not_loaded_spec.rb +7 -10
  606. data/spec/mongoid/errors/callback_spec.rb +8 -11
  607. data/spec/mongoid/errors/config_redactor_spec.rb +112 -0
  608. data/spec/mongoid/errors/delete_restriction_spec.rb +5 -8
  609. data/spec/mongoid/errors/document_not_destroyed_spec.rb +7 -10
  610. data/spec/mongoid/errors/document_not_found_spec.rb +51 -61
  611. data/spec/mongoid/errors/invalid_collection_spec.rb +9 -13
  612. data/spec/mongoid/errors/invalid_config_file_spec.rb +8 -11
  613. data/spec/mongoid/errors/invalid_config_option_spec.rb +8 -11
  614. data/spec/mongoid/errors/invalid_field_option_spec.rb +7 -10
  615. data/spec/mongoid/errors/invalid_field_spec.rb +10 -11
  616. data/spec/mongoid/errors/invalid_field_type_spec.rb +9 -12
  617. data/spec/mongoid/errors/invalid_find_spec.rb +8 -11
  618. data/spec/mongoid/errors/invalid_includes_spec.rb +9 -13
  619. data/spec/mongoid/errors/invalid_index_spec.rb +8 -11
  620. data/spec/mongoid/errors/invalid_options_spec.rb +8 -11
  621. data/spec/mongoid/errors/invalid_path_spec.rb +7 -10
  622. data/spec/mongoid/errors/invalid_relation_spec.rb +15 -16
  623. data/spec/mongoid/errors/invalid_scope_spec.rb +8 -11
  624. data/spec/mongoid/errors/invalid_set_polymorphic_relation_spec.rb +3 -6
  625. data/spec/mongoid/errors/invalid_storage_options_spec.rb +8 -11
  626. data/spec/mongoid/errors/invalid_time_spec.rb +8 -11
  627. data/spec/mongoid/errors/inverse_not_found_spec.rb +9 -12
  628. data/spec/mongoid/errors/mixed_client_configuration_spec.rb +40 -12
  629. data/spec/mongoid/errors/mixed_relations_spec.rb +8 -11
  630. data/spec/mongoid/errors/mongoid_error_spec.rb +21 -24
  631. data/spec/mongoid/errors/nested_attributes_metadata_not_found_spec.rb +6 -9
  632. data/spec/mongoid/errors/no_client_config_spec.rb +7 -10
  633. data/spec/mongoid/errors/no_client_database_spec.rb +38 -12
  634. data/spec/mongoid/errors/no_client_hosts_spec.rb +35 -12
  635. data/spec/mongoid/errors/no_clients_config_spec.rb +7 -10
  636. data/spec/mongoid/errors/no_environment_spec.rb +8 -11
  637. data/spec/mongoid/errors/no_map_reduce_output_spec.rb +8 -11
  638. data/spec/mongoid/errors/no_metadata_spec.rb +7 -10
  639. data/spec/mongoid/errors/no_parent_spec.rb +7 -10
  640. data/spec/mongoid/errors/readonly_association_spec.rb +34 -0
  641. data/spec/mongoid/errors/readonly_attribute_spec.rb +7 -10
  642. data/spec/mongoid/errors/readonly_document_spec.rb +6 -9
  643. data/spec/mongoid/errors/scope_overwrite_spec.rb +9 -12
  644. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +9 -12
  645. data/spec/mongoid/errors/unknown_attribute_spec.rb +5 -8
  646. data/spec/mongoid/errors/unsaved_document_spec.rb +8 -11
  647. data/spec/mongoid/errors/unsupported_javascript_spec.rb +9 -12
  648. data/spec/mongoid/errors/validations_spec.rb +11 -14
  649. data/spec/mongoid/extensions/array_spec.rb +70 -92
  650. data/spec/mongoid/extensions/big_decimal_spec.rb +233 -313
  651. data/spec/mongoid/extensions/binary_spec.rb +21 -32
  652. data/spec/mongoid/extensions/boolean_spec.rb +52 -75
  653. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +43 -54
  654. data/spec/mongoid/extensions/date_spec.rb +26 -38
  655. data/spec/mongoid/extensions/date_time_spec.rb +22 -32
  656. data/spec/mongoid/extensions/decimal128_spec.rb +12 -18
  657. data/spec/mongoid/extensions/false_class_spec.rb +10 -17
  658. data/spec/mongoid/extensions/float_spec.rb +40 -61
  659. data/spec/mongoid/extensions/hash_spec.rb +46 -64
  660. data/spec/mongoid/extensions/integer_spec.rb +40 -61
  661. data/spec/mongoid/extensions/module_spec.rb +13 -18
  662. data/spec/mongoid/extensions/nil_class_spec.rb +2 -5
  663. data/spec/mongoid/extensions/object_id_spec.rb +159 -247
  664. data/spec/mongoid/extensions/object_spec.rb +31 -47
  665. data/spec/mongoid/extensions/range_spec.rb +112 -115
  666. data/spec/mongoid/extensions/raw_value_spec.rb +10 -12
  667. data/spec/mongoid/extensions/regexp_spec.rb +23 -36
  668. data/spec/mongoid/extensions/set_spec.rb +38 -49
  669. data/spec/mongoid/extensions/string_spec.rb +118 -167
  670. data/spec/mongoid/extensions/stringified_symbol_spec.rb +29 -43
  671. data/spec/mongoid/extensions/symbol_spec.rb +12 -20
  672. data/spec/mongoid/extensions/time_spec.rb +160 -202
  673. data/spec/mongoid/extensions/time_with_zone_spec.rb +79 -105
  674. data/spec/mongoid/extensions/true_class_spec.rb +10 -17
  675. data/spec/mongoid/extensions/vector_spec.rb +175 -0
  676. data/spec/mongoid/factory_spec.rb +125 -148
  677. data/spec/mongoid/fields/foreign_key_spec.rb +124 -169
  678. data/spec/mongoid/fields/localized_spec.rb +140 -185
  679. data/spec/mongoid/fields/standard_spec.rb +43 -59
  680. data/spec/mongoid/fields_spec.rb +751 -620
  681. data/spec/mongoid/findable_spec.rb +260 -228
  682. data/spec/mongoid/indexable/specification_spec.rb +42 -58
  683. data/spec/mongoid/indexable_spec.rb +260 -264
  684. data/spec/mongoid/inspectable_spec.rb +45 -55
  685. data/spec/mongoid/interceptable_spec.rb +784 -922
  686. data/spec/mongoid/interceptable_spec_models.rb +35 -35
  687. data/spec/mongoid/loading_spec.rb +47 -43
  688. data/spec/mongoid/loggable_spec.rb +3 -6
  689. data/spec/mongoid/matcher/extract_attribute_spec.rb +2 -6
  690. data/spec/mongoid/matcher/regexp_budget_spec.rb +570 -0
  691. data/spec/mongoid/mongoizable_spec.rb +81 -90
  692. data/spec/mongoid/monkey_patches_spec.rb +4 -0
  693. data/spec/mongoid/persistable/creatable_spec.rb +181 -220
  694. data/spec/mongoid/persistable/deletable_spec.rb +139 -179
  695. data/spec/mongoid/persistable/destroyable_spec.rb +135 -164
  696. data/spec/mongoid/persistable/incrementable_spec.rb +65 -84
  697. data/spec/mongoid/persistable/logical_spec.rb +48 -61
  698. data/spec/mongoid/persistable/maxable_spec.rb +45 -44
  699. data/spec/mongoid/persistable/minable_spec.rb +45 -44
  700. data/spec/mongoid/persistable/multipliable_spec.rb +54 -69
  701. data/spec/mongoid/persistable/poppable_spec.rb +47 -60
  702. data/spec/mongoid/persistable/pullable_spec.rb +79 -103
  703. data/spec/mongoid/persistable/pushable_spec.rb +106 -131
  704. data/spec/mongoid/persistable/renamable_spec.rb +52 -65
  705. data/spec/mongoid/persistable/savable_spec.rb +152 -189
  706. data/spec/mongoid/persistable/settable_spec.rb +121 -145
  707. data/spec/mongoid/persistable/unsettable_spec.rb +56 -73
  708. data/spec/mongoid/persistable/updatable_spec.rb +185 -232
  709. data/spec/mongoid/persistable/upsertable_spec.rb +66 -77
  710. data/spec/mongoid/persistable_spec.rb +132 -139
  711. data/spec/mongoid/persistence_context_spec.rb +31 -89
  712. data/spec/mongoid/positional_spec.rb +67 -79
  713. data/spec/mongoid/railties/bson_object_id_serializer_spec.rb +0 -3
  714. data/spec/mongoid/railties/console_sandbox_spec.rb +0 -1
  715. data/spec/mongoid/relations/proxy_spec.rb +0 -1
  716. data/spec/mongoid/reloadable_spec.rb +250 -145
  717. data/spec/mongoid/scopable_spec.rb +319 -398
  718. data/spec/mongoid/search_indexable_spec.rb +735 -44
  719. data/spec/mongoid/selectable_spec.rb +36 -51
  720. data/spec/mongoid/serializable_spec.rb +269 -312
  721. data/spec/mongoid/shardable_models.rb +5 -5
  722. data/spec/mongoid/shardable_spec.rb +44 -46
  723. data/spec/mongoid/stateful_spec.rb +55 -75
  724. data/spec/mongoid/tasks/database_rake_spec.rb +138 -141
  725. data/spec/mongoid/tasks/database_spec.rb +98 -80
  726. data/spec/mongoid/tasks/encryption_spec.rb +22 -20
  727. data/spec/mongoid/threaded_spec.rb +57 -83
  728. data/spec/mongoid/timestamps/created/short_spec.rb +12 -16
  729. data/spec/mongoid/timestamps/created_spec.rb +16 -20
  730. data/spec/mongoid/timestamps/timeless_spec.rb +228 -48
  731. data/spec/mongoid/timestamps/updated/short_spec.rb +21 -28
  732. data/spec/mongoid/timestamps/updated_spec.rb +18 -25
  733. data/spec/mongoid/timestamps_spec.rb +171 -188
  734. data/spec/mongoid/timestamps_spec_models.rb +12 -13
  735. data/spec/mongoid/touchable_spec.rb +355 -294
  736. data/spec/mongoid/touchable_spec_models.rb +45 -37
  737. data/spec/mongoid/traversable_spec.rb +435 -471
  738. data/spec/mongoid/validatable/associated_spec.rb +60 -59
  739. data/spec/mongoid/validatable/format_spec.rb +24 -34
  740. data/spec/mongoid/validatable/length_spec.rb +62 -86
  741. data/spec/mongoid/validatable/numericality_spec.rb +114 -23
  742. data/spec/mongoid/validatable/presence_spec.rb +149 -203
  743. data/spec/mongoid/validatable/uniqueness_spec.rb +632 -830
  744. data/spec/mongoid/validatable_spec.rb +71 -103
  745. data/spec/mongoid/warnings_spec.rb +5 -9
  746. data/spec/mongoid_spec.rb +25 -41
  747. data/spec/rails/controller_extension/controller_runtime_spec.rb +45 -49
  748. data/spec/rails/mongoid_spec.rb +15 -15
  749. data/spec/shared/lib/mrss/cluster_config.rb +5 -40
  750. data/spec/shared/lib/mrss/constraints.rb +7 -46
  751. data/spec/shared/lib/mrss/docker_runner.rb +10 -21
  752. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -31
  753. data/spec/shared/lib/mrss/release/candidate.rb +18 -12
  754. data/spec/shared/lib/mrss/server_version_registry.rb +1 -5
  755. data/spec/shared/share/Dockerfile.erb +6 -8
  756. data/spec/shared/shlib/server.sh +0 -50
  757. data/spec/shared/shlib/set_env.sh +4 -10
  758. data/spec/spec_helper.rb +59 -32
  759. data/spec/support/authorization.rb +0 -1
  760. data/spec/support/client_registry.rb +1 -2
  761. data/spec/support/constraints.rb +8 -25
  762. data/spec/support/crypt/models.rb +164 -8
  763. data/spec/support/crypt.rb +6 -9
  764. data/spec/support/expectations.rb +21 -7
  765. data/spec/support/feature_sandbox.rb +1 -4
  766. data/spec/support/helpers.rb +0 -1
  767. data/spec/support/immutable_ids.rb +20 -21
  768. data/spec/support/macros.rb +1 -3
  769. data/spec/support/models/account.rb +4 -5
  770. data/spec/support/models/acolyte.rb +5 -5
  771. data/spec/support/models/actor.rb +3 -3
  772. data/spec/support/models/actress.rb +0 -1
  773. data/spec/support/models/address.rb +11 -11
  774. data/spec/support/models/address_component.rb +1 -1
  775. data/spec/support/models/address_number.rb +1 -1
  776. data/spec/support/models/agency.rb +1 -1
  777. data/spec/support/models/agent.rb +1 -1
  778. data/spec/support/models/album.rb +1 -2
  779. data/spec/support/models/alert.rb +1 -1
  780. data/spec/support/models/animal.rb +4 -5
  781. data/spec/support/models/answer.rb +1 -1
  782. data/spec/support/models/appointment.rb +2 -2
  783. data/spec/support/models/armrest.rb +0 -1
  784. data/spec/support/models/array_field.rb +0 -1
  785. data/spec/support/models/article.rb +0 -1
  786. data/spec/support/models/artist.rb +16 -12
  787. data/spec/support/models/artwork.rb +1 -1
  788. data/spec/support/models/audible_sound.rb +0 -1
  789. data/spec/support/models/audio.rb +2 -2
  790. data/spec/support/models/augmentation.rb +1 -2
  791. data/spec/support/models/author.rb +1 -1
  792. data/spec/support/models/baby.rb +1 -1
  793. data/spec/support/models/band.rb +0 -1
  794. data/spec/support/models/bar.rb +2 -2
  795. data/spec/support/models/basic.rb +0 -1
  796. data/spec/support/models/bed.rb +0 -1
  797. data/spec/support/models/big_palette.rb +0 -1
  798. data/spec/support/models/birthday.rb +3 -5
  799. data/spec/support/models/bolt.rb +0 -1
  800. data/spec/support/models/bomb.rb +1 -1
  801. data/spec/support/models/book.rb +1 -1
  802. data/spec/support/models/breed.rb +1 -1
  803. data/spec/support/models/browser.rb +1 -2
  804. data/spec/support/models/building.rb +0 -1
  805. data/spec/support/models/building_address.rb +1 -1
  806. data/spec/support/models/bus.rb +1 -1
  807. data/spec/support/models/business.rb +2 -2
  808. data/spec/support/models/callback_test.rb +1 -1
  809. data/spec/support/models/canvas.rb +5 -6
  810. data/spec/support/models/car.rb +0 -1
  811. data/spec/support/models/cat.rb +0 -2
  812. data/spec/support/models/catalog.rb +0 -1
  813. data/spec/support/models/category.rb +1 -1
  814. data/spec/support/models/child.rb +1 -1
  815. data/spec/support/models/child_doc.rb +5 -6
  816. data/spec/support/models/church.rb +1 -1
  817. data/spec/support/models/circle.rb +0 -1
  818. data/spec/support/models/circuit.rb +2 -2
  819. data/spec/support/models/circus.rb +0 -1
  820. data/spec/support/models/code.rb +2 -1
  821. data/spec/support/models/coding/pull_request.rb +0 -1
  822. data/spec/support/models/coding.rb +0 -1
  823. data/spec/support/models/comment.rb +0 -1
  824. data/spec/support/models/company.rb +0 -1
  825. data/spec/support/models/consumption_period.rb +0 -1
  826. data/spec/support/models/contextable_item.rb +1 -1
  827. data/spec/support/models/contractor.rb +1 -1
  828. data/spec/support/models/cookie.rb +0 -1
  829. data/spec/support/models/country_code.rb +2 -3
  830. data/spec/support/models/courier_job.rb +2 -2
  831. data/spec/support/models/cover.rb +0 -1
  832. data/spec/support/models/crate.rb +0 -1
  833. data/spec/support/models/customer.rb +0 -1
  834. data/spec/support/models/customer_address.rb +0 -1
  835. data/spec/support/models/deed.rb +1 -1
  836. data/spec/support/models/definition.rb +1 -1
  837. data/spec/support/models/delegating_patient.rb +0 -1
  838. data/spec/support/models/description.rb +0 -1
  839. data/spec/support/models/dictionary.rb +1 -1
  840. data/spec/support/models/division.rb +2 -2
  841. data/spec/support/models/doctor.rb +0 -1
  842. data/spec/support/models/dog.rb +2 -2
  843. data/spec/support/models/dokument.rb +1 -1
  844. data/spec/support/models/draft.rb +0 -1
  845. data/spec/support/models/dragon.rb +1 -1
  846. data/spec/support/models/driver.rb +2 -2
  847. data/spec/support/models/drug.rb +1 -1
  848. data/spec/support/models/dungeon.rb +1 -1
  849. data/spec/support/models/edit.rb +1 -1
  850. data/spec/support/models/email.rb +1 -1
  851. data/spec/support/models/employer.rb +1 -2
  852. data/spec/support/models/entry.rb +1 -1
  853. data/spec/support/models/eraser.rb +0 -1
  854. data/spec/support/models/even.rb +1 -1
  855. data/spec/support/models/event.rb +3 -4
  856. data/spec/support/models/exhibition.rb +1 -1
  857. data/spec/support/models/exhibitor.rb +1 -1
  858. data/spec/support/models/explosion.rb +1 -1
  859. data/spec/support/models/eye.rb +0 -1
  860. data/spec/support/models/eye_bowl.rb +2 -3
  861. data/spec/support/models/face.rb +2 -3
  862. data/spec/support/models/fanatic.rb +1 -1
  863. data/spec/support/models/favorite.rb +1 -1
  864. data/spec/support/models/filesystem.rb +1 -1
  865. data/spec/support/models/fire_hydrant.rb +1 -1
  866. data/spec/support/models/firefox.rb +0 -1
  867. data/spec/support/models/fish.rb +0 -1
  868. data/spec/support/models/folder.rb +0 -2
  869. data/spec/support/models/folder_item.rb +1 -3
  870. data/spec/support/models/fruits.rb +9 -5
  871. data/spec/support/models/game.rb +3 -4
  872. data/spec/support/models/ghost.rb +0 -1
  873. data/spec/support/models/guitar.rb +0 -1
  874. data/spec/support/models/hole.rb +0 -1
  875. data/spec/support/models/home.rb +1 -1
  876. data/spec/support/models/house.rb +2 -2
  877. data/spec/support/models/html_writer.rb +0 -1
  878. data/spec/support/models/id_key.rb +3 -3
  879. data/spec/support/models/idnodef.rb +0 -1
  880. data/spec/support/models/image.rb +0 -1
  881. data/spec/support/models/implant.rb +1 -2
  882. data/spec/support/models/instrument.rb +2 -3
  883. data/spec/support/models/item.rb +2 -2
  884. data/spec/support/models/jar.rb +1 -2
  885. data/spec/support/models/kaleidoscope.rb +1 -1
  886. data/spec/support/models/kangaroo.rb +1 -1
  887. data/spec/support/models/label.rb +2 -2
  888. data/spec/support/models/language.rb +1 -1
  889. data/spec/support/models/lat_lng.rb +0 -1
  890. data/spec/support/models/league.rb +1 -1
  891. data/spec/support/models/learner.rb +0 -1
  892. data/spec/support/models/line_item.rb +1 -1
  893. data/spec/support/models/location.rb +1 -1
  894. data/spec/support/models/login.rb +1 -2
  895. data/spec/support/models/manufacturer.rb +0 -1
  896. data/spec/support/models/meat.rb +1 -1
  897. data/spec/support/models/membership.rb +1 -1
  898. data/spec/support/models/message.rb +1 -2
  899. data/spec/support/models/minim.rb +0 -1
  900. data/spec/support/models/mixed_drink.rb +1 -1
  901. data/spec/support/models/modifier_models.rb +25 -0
  902. data/spec/support/models/mop.rb +0 -1
  903. data/spec/support/models/movie.rb +1 -1
  904. data/spec/support/models/my_hash.rb +1 -2
  905. data/spec/support/models/name.rb +4 -5
  906. data/spec/support/models/name_only.rb +0 -1
  907. data/spec/support/models/node.rb +1 -1
  908. data/spec/support/models/note.rb +3 -3
  909. data/spec/support/models/nut.rb +0 -1
  910. data/spec/support/models/odd.rb +1 -1
  911. data/spec/support/models/order.rb +1 -1
  912. data/spec/support/models/ordered_post.rb +1 -1
  913. data/spec/support/models/ordered_preference.rb +1 -1
  914. data/spec/support/models/oscar.rb +1 -1
  915. data/spec/support/models/other_owner_object.rb +0 -1
  916. data/spec/support/models/override.rb +3 -11
  917. data/spec/support/models/ownable.rb +1 -1
  918. data/spec/support/models/owner.rb +1 -1
  919. data/spec/support/models/pack.rb +0 -1
  920. data/spec/support/models/page.rb +3 -3
  921. data/spec/support/models/page_question.rb +1 -1
  922. data/spec/support/models/palette.rb +2 -2
  923. data/spec/support/models/parent.rb +2 -2
  924. data/spec/support/models/parent_doc.rb +1 -1
  925. data/spec/support/models/passport.rb +0 -1
  926. data/spec/support/models/patient.rb +2 -2
  927. data/spec/support/models/pdf_writer.rb +0 -1
  928. data/spec/support/models/pencil.rb +0 -1
  929. data/spec/support/models/person.rb +32 -28
  930. data/spec/support/models/pet.rb +1 -1
  931. data/spec/support/models/pet_owner.rb +1 -1
  932. data/spec/support/models/phone.rb +1 -2
  933. data/spec/support/models/piano.rb +0 -1
  934. data/spec/support/models/pizza.rb +1 -1
  935. data/spec/support/models/player.rb +5 -5
  936. data/spec/support/models/post.rb +12 -12
  937. data/spec/support/models/post_genre.rb +1 -1
  938. data/spec/support/models/powerup.rb +1 -2
  939. data/spec/support/models/preference.rb +2 -2
  940. data/spec/support/models/princess.rb +1 -1
  941. data/spec/support/models/product.rb +3 -3
  942. data/spec/support/models/profile.rb +2 -1
  943. data/spec/support/models/pronunciation.rb +1 -1
  944. data/spec/support/models/pub.rb +2 -2
  945. data/spec/support/models/publication/encyclopedia.rb +0 -1
  946. data/spec/support/models/publication/review.rb +0 -1
  947. data/spec/support/models/publication.rb +0 -1
  948. data/spec/support/models/purchase.rb +1 -1
  949. data/spec/support/models/purchased_item.rb +1 -1
  950. data/spec/support/models/question.rb +2 -2
  951. data/spec/support/models/quiz.rb +1 -1
  952. data/spec/support/models/rating.rb +1 -1
  953. data/spec/support/models/record.rb +2 -3
  954. data/spec/support/models/registry.rb +1 -1
  955. data/spec/support/models/role.rb +1 -1
  956. data/spec/support/models/root_category.rb +1 -1
  957. data/spec/support/models/sandbox/app/models/app_models_message.rb +0 -1
  958. data/spec/support/models/sandbox/lib/models/lib_models_message.rb +0 -1
  959. data/spec/support/models/sandbox/sandbox_message.rb +0 -1
  960. data/spec/support/models/sandbox/sandbox_user.rb +0 -1
  961. data/spec/support/models/sandbox/subdir/sandbox_comment.rb +0 -1
  962. data/spec/support/models/sandwich.rb +1 -1
  963. data/spec/support/models/scheduler.rb +0 -1
  964. data/spec/support/models/school.rb +0 -1
  965. data/spec/support/models/scribe.rb +1 -1
  966. data/spec/support/models/sealer.rb +0 -1
  967. data/spec/support/models/seat.rb +0 -1
  968. data/spec/support/models/seo.rb +1 -1
  969. data/spec/support/models/series.rb +1 -1
  970. data/spec/support/models/server.rb +1 -1
  971. data/spec/support/models/service.rb +2 -2
  972. data/spec/support/models/shape.rb +3 -3
  973. data/spec/support/models/shelf.rb +1 -1
  974. data/spec/support/models/shield.rb +2 -2
  975. data/spec/support/models/shipment_address.rb +0 -1
  976. data/spec/support/models/shipping_container.rb +1 -1
  977. data/spec/support/models/shipping_pack.rb +0 -1
  978. data/spec/support/models/shirt.rb +0 -1
  979. data/spec/support/models/shop.rb +2 -2
  980. data/spec/support/models/short_agent.rb +0 -1
  981. data/spec/support/models/short_quiz.rb +1 -1
  982. data/spec/support/models/simple.rb +1 -1
  983. data/spec/support/models/slave.rb +1 -1
  984. data/spec/support/models/song.rb +1 -2
  985. data/spec/support/models/sound.rb +2 -2
  986. data/spec/support/models/spacer.rb +0 -1
  987. data/spec/support/models/square.rb +0 -1
  988. data/spec/support/models/staff.rb +0 -1
  989. data/spec/support/models/store_as_dup_test1.rb +2 -2
  990. data/spec/support/models/store_as_dup_test2.rb +1 -1
  991. data/spec/support/models/store_as_dup_test3.rb +2 -2
  992. data/spec/support/models/store_as_dup_test4.rb +1 -1
  993. data/spec/support/models/strategy.rb +0 -1
  994. data/spec/support/models/student.rb +1 -2
  995. data/spec/support/models/sub_item.rb +0 -1
  996. data/spec/support/models/subscription.rb +2 -2
  997. data/spec/support/models/survey.rb +2 -2
  998. data/spec/support/models/symptom.rb +2 -2
  999. data/spec/support/models/system_role.rb +2 -3
  1000. data/spec/support/models/tag.rb +2 -2
  1001. data/spec/support/models/target.rb +1 -1
  1002. data/spec/support/models/template.rb +1 -1
  1003. data/spec/support/models/thing.rb +1 -1
  1004. data/spec/support/models/threadlocker.rb +0 -1
  1005. data/spec/support/models/title.rb +0 -1
  1006. data/spec/support/models/tool.rb +3 -3
  1007. data/spec/support/models/topping.rb +1 -1
  1008. data/spec/support/models/toy.rb +0 -1
  1009. data/spec/support/models/track.rb +1 -1
  1010. data/spec/support/models/translation.rb +1 -1
  1011. data/spec/support/models/tree.rb +2 -3
  1012. data/spec/support/models/truck.rb +0 -1
  1013. data/spec/support/models/updatable.rb +0 -1
  1014. data/spec/support/models/user.rb +3 -4
  1015. data/spec/support/models/user_account.rb +3 -3
  1016. data/spec/support/models/validation_callback.rb +4 -4
  1017. data/spec/support/models/vehicle.rb +2 -3
  1018. data/spec/support/models/version.rb +1 -1
  1019. data/spec/support/models/vertex.rb +0 -1
  1020. data/spec/support/models/vet_visit.rb +1 -1
  1021. data/spec/support/models/video.rb +2 -2
  1022. data/spec/support/models/video_game.rb +0 -1
  1023. data/spec/support/models/washer.rb +0 -1
  1024. data/spec/support/models/weapon.rb +1 -2
  1025. data/spec/support/models/wiki_page.rb +2 -3
  1026. data/spec/support/models/word.rb +2 -2
  1027. data/spec/support/models/word_origin.rb +1 -2
  1028. data/spec/support/models/writer.rb +3 -3
  1029. data/spec/support/rails_mock.rb +7 -12
  1030. data/spec/support/shared/time.rb +0 -1
  1031. data/spec/support/sinatra_mock.rb +4 -2
  1032. data/spec/support/spec_config.rb +19 -18
  1033. metadata +64 -2
@@ -1,10 +1,8 @@
1
1
  # frozen_string_literal: true
2
- # rubocop:todo all
3
2
 
4
3
  module Mongoid
5
4
  class Criteria
6
5
  module Queryable
7
-
8
6
  # An queryable selectable is selectable, in that it has the ability to select
9
7
  # document from the database. The selectable module brings all functionality
10
8
  # to the selectable that has to do with building MongoDB selectors.
@@ -12,13 +10,13 @@ module Mongoid
12
10
  extend Macroable
13
11
 
14
12
  # Constant for a LineString $geometry.
15
- LINE_STRING = "LineString"
13
+ LINE_STRING = 'LineString'
16
14
 
17
15
  # Constant for a Point $geometry.
18
- POINT = "Point"
16
+ POINT = 'Point'
19
17
 
20
18
  # Constant for a Polygon $geometry.
21
- POLYGON = "Polygon"
19
+ POLYGON = 'Polygon'
22
20
 
23
21
  # @attribute [rw] negating If the next expression is negated.
24
22
  # @attribute [rw] selector The query selector.
@@ -43,27 +41,23 @@ module Mongoid
43
41
  end
44
42
 
45
43
  criteria.inject(clone) do |query, condition|
46
- if condition.nil?
47
- raise Errors::CriteriaArgumentRequired, :all
48
- end
44
+ raise Errors::CriteriaArgumentRequired, :all if condition.nil?
49
45
 
50
46
  condition = expand_condition_to_array_values(condition)
51
47
 
52
48
  if strategy
53
- send(strategy, condition, "$all")
49
+ send(strategy, condition, '$all')
54
50
  else
55
51
  condition.inject(query) do |_query, (field, value)|
56
- v = {'$all' => value}
57
- if negating?
58
- v = {'$not' => v}
59
- end
52
+ v = { '$all' => value }
53
+ v = { '$not' => v } if negating?
60
54
  _query.add_field_expression(field.to_s, v)
61
55
  end
62
56
  end
63
57
  end.reset_strategies!
64
58
  end
65
- alias :all_in :all
66
- key :all, :union, "$all"
59
+ alias all_in all
60
+ key :all, :union, '$all'
67
61
 
68
62
  # Add the $and criterion.
69
63
  #
@@ -76,10 +70,8 @@ module Mongoid
76
70
  #
77
71
  # @return [ Selectable ] The new selectable.
78
72
  def and(*criteria)
79
- _mongoid_flatten_arrays(criteria).inject(self.clone) do |c, new_s|
80
- if new_s.is_a?(Selectable)
81
- new_s = new_s.selector
82
- end
73
+ _mongoid_flatten_arrays(criteria).inject(clone) do |c, new_s|
74
+ new_s = new_s.selector if new_s.is_a?(Selectable)
83
75
  normalized = _mongoid_expand_keys(new_s)
84
76
  normalized.each do |k, v|
85
77
  k = k.to_s
@@ -90,16 +82,15 @@ module Mongoid
90
82
  # we can add to existing conditions.
91
83
  # Otherwise use $and.
92
84
  if v.is_a?(Hash) &&
93
- v.length == 1 &&
94
- (new_k = v.keys.first).start_with?('$') &&
95
- (existing_kv = c.selector[k]).is_a?(Hash) &&
96
- !existing_kv.key?(new_k) &&
97
- existing_kv.keys.all? { |sub_k| sub_k.start_with?('$') }
98
- then
85
+ v.length == 1 &&
86
+ (new_k = v.keys.first).start_with?('$') &&
87
+ (existing_kv = c.selector[k]).is_a?(Hash) &&
88
+ !existing_kv.key?(new_k) &&
89
+ existing_kv.keys.all? { |sub_k| sub_k.start_with?('$') }
99
90
  merged_v = c.selector[k].merge(v)
100
91
  c.selector.store(k, merged_v)
101
92
  else
102
- c = c.send(:__multi__, [k => v], '$and')
93
+ c = c.send(:__multi__, [ { k => v } ], '$and')
103
94
  end
104
95
  else
105
96
  c.selector.store(k, v)
@@ -108,7 +99,7 @@ module Mongoid
108
99
  c
109
100
  end
110
101
  end
111
- alias :all_of :and
102
+ alias all_of and
112
103
 
113
104
  # Add the range selection.
114
105
  #
@@ -122,14 +113,12 @@ module Mongoid
122
113
  #
123
114
  # @return [ Selectable ] The cloned selectable.
124
115
  def between(criterion)
125
- if criterion.nil?
126
- raise Errors::CriteriaArgumentRequired, :between
127
- end
116
+ raise Errors::CriteriaArgumentRequired, :between if criterion.nil?
128
117
 
129
118
  selection(criterion) do |selector, field, value|
130
119
  selector.store(
131
120
  field,
132
- { "$gte" => value.min, "$lte" => value.max }
121
+ { '$gte' => value.min, '$lte' => value.max }
133
122
  )
134
123
  end
135
124
  end
@@ -152,13 +141,11 @@ module Mongoid
152
141
  #
153
142
  # @return [ Selectable ] The cloned selectable.
154
143
  def elem_match(criterion)
155
- if criterion.nil?
156
- raise Errors::CriteriaArgumentRequired, :elem_match
157
- end
144
+ raise Errors::CriteriaArgumentRequired, :elem_match if criterion.nil?
158
145
 
159
- and_with_operator(criterion, "$elemMatch")
146
+ and_with_operator(criterion, '$elemMatch')
160
147
  end
161
- key :elem_match, :override, "$elemMatch"
148
+ key :elem_match, :override, '$elemMatch'
162
149
 
163
150
  # Add the $exists selection.
164
151
  #
@@ -175,15 +162,13 @@ module Mongoid
175
162
  #
176
163
  # @return [ Selectable ] The cloned selectable.
177
164
  def exists(criterion)
178
- if criterion.nil?
179
- raise Errors::CriteriaArgumentRequired, :exists
180
- end
165
+ raise Errors::CriteriaArgumentRequired, :exists if criterion.nil?
181
166
 
182
- typed_override(criterion, "$exists") do |value|
167
+ typed_override(criterion, '$exists') do |value|
183
168
  Mongoid::Boolean.evolve(value)
184
169
  end
185
170
  end
186
- key :exists, :override, "$exists" do |value|
171
+ key :exists, :override, '$exists' do |value|
187
172
  Mongoid::Boolean.evolve(value)
188
173
  end
189
174
 
@@ -222,26 +207,24 @@ module Mongoid
222
207
  #
223
208
  # @return [ Selectable ] The cloned selectable.
224
209
  def geo_spatial(criterion)
225
- if criterion.nil?
226
- raise Errors::CriteriaArgumentRequired, :geo_spatial
227
- end
210
+ raise Errors::CriteriaArgumentRequired, :geo_spatial if criterion.nil?
228
211
 
229
212
  __merge__(criterion)
230
213
  end
231
214
 
232
- key :intersects_line, :override, "$geoIntersects", "$geometry" do |value|
233
- { "type" => LINE_STRING, "coordinates" => value }
215
+ key :intersects_line, :override, '$geoIntersects', '$geometry' do |value|
216
+ { 'type' => LINE_STRING, 'coordinates' => value }
234
217
  end
235
- key :intersects_point, :override, "$geoIntersects", "$geometry" do |value|
236
- { "type" => POINT, "coordinates" => value }
218
+ key :intersects_point, :override, '$geoIntersects', '$geometry' do |value|
219
+ { 'type' => POINT, 'coordinates' => value }
237
220
  end
238
- key :intersects_polygon, :override, "$geoIntersects", "$geometry" do |value|
239
- { "type" => POLYGON, "coordinates" => value }
221
+ key :intersects_polygon, :override, '$geoIntersects', '$geometry' do |value|
222
+ { 'type' => POLYGON, 'coordinates' => value }
240
223
  end
241
- key :within_polygon, :override, "$geoWithin", "$geometry" do |value|
242
- { "type" => POLYGON, "coordinates" => value }
224
+ key :within_polygon, :override, '$geoWithin', '$geometry' do |value|
225
+ { 'type' => POLYGON, 'coordinates' => value }
243
226
  end
244
- key :within_box, :override, "$geoWithin", "$box"
227
+ key :within_box, :override, '$geoWithin', '$box'
245
228
 
246
229
  # Add the $eq criterion to the selector.
247
230
  #
@@ -255,13 +238,11 @@ module Mongoid
255
238
  #
256
239
  # @return [ Selectable ] The cloned selectable.
257
240
  def eq(criterion)
258
- if criterion.nil?
259
- raise Errors::CriteriaArgumentRequired, :eq
260
- end
241
+ raise Errors::CriteriaArgumentRequired, :eq if criterion.nil?
261
242
 
262
- and_with_operator(criterion, "$eq")
243
+ and_with_operator(criterion, '$eq')
263
244
  end
264
- key :eq, :override, "$eq"
245
+ key :eq, :override, '$eq'
265
246
 
266
247
  # Add the $gt criterion to the selector.
267
248
  #
@@ -275,13 +256,11 @@ module Mongoid
275
256
  #
276
257
  # @return [ Selectable ] The cloned selectable.
277
258
  def gt(criterion)
278
- if criterion.nil?
279
- raise Errors::CriteriaArgumentRequired, :gt
280
- end
259
+ raise Errors::CriteriaArgumentRequired, :gt if criterion.nil?
281
260
 
282
- and_with_operator(criterion, "$gt")
261
+ and_with_operator(criterion, '$gt')
283
262
  end
284
- key :gt, :override, "$gt"
263
+ key :gt, :override, '$gt'
285
264
 
286
265
  # Add the $gte criterion to the selector.
287
266
  #
@@ -295,13 +274,11 @@ module Mongoid
295
274
  #
296
275
  # @return [ Selectable ] The cloned selectable.
297
276
  def gte(criterion)
298
- if criterion.nil?
299
- raise Errors::CriteriaArgumentRequired, :gte
300
- end
277
+ raise Errors::CriteriaArgumentRequired, :gte if criterion.nil?
301
278
 
302
- and_with_operator(criterion, "$gte")
279
+ and_with_operator(criterion, '$gte')
303
280
  end
304
- key :gte, :override, "$gte"
281
+ key :gte, :override, '$gte'
305
282
 
306
283
  # Adds the $in selection to the selectable.
307
284
  #
@@ -318,26 +295,22 @@ module Mongoid
318
295
  #
319
296
  # @return [ Selectable ] The cloned selectable.
320
297
  def in(condition)
321
- if condition.nil?
322
- raise Errors::CriteriaArgumentRequired, :in
323
- end
298
+ raise Errors::CriteriaArgumentRequired, :in if condition.nil?
324
299
 
325
300
  condition = expand_condition_to_array_values(condition)
326
301
 
327
302
  if strategy
328
- send(strategy, condition, "$in")
303
+ send(strategy, condition, '$in')
329
304
  else
330
305
  condition.inject(clone) do |query, (field, value)|
331
- v = {'$in' => value}
332
- if negating?
333
- v = {'$not' => v}
334
- end
306
+ v = { '$in' => value }
307
+ v = { '$not' => v } if negating?
335
308
  query.add_field_expression(field.to_s, v)
336
309
  end.reset_strategies!
337
310
  end
338
311
  end
339
- alias :any_in :in
340
- key :in, :intersect, "$in"
312
+ alias any_in in
313
+ key :in, :intersect, '$in'
341
314
 
342
315
  # Add the $lt criterion to the selector.
343
316
  #
@@ -351,13 +324,11 @@ module Mongoid
351
324
  #
352
325
  # @return [ Selectable ] The cloned selectable.
353
326
  def lt(criterion)
354
- if criterion.nil?
355
- raise Errors::CriteriaArgumentRequired, :lt
356
- end
327
+ raise Errors::CriteriaArgumentRequired, :lt if criterion.nil?
357
328
 
358
- and_with_operator(criterion, "$lt")
329
+ and_with_operator(criterion, '$lt')
359
330
  end
360
- key :lt, :override, "$lt"
331
+ key :lt, :override, '$lt'
361
332
 
362
333
  # Add the $lte criterion to the selector.
363
334
  #
@@ -371,13 +342,11 @@ module Mongoid
371
342
  #
372
343
  # @return [ Selectable ] The cloned selectable.
373
344
  def lte(criterion)
374
- if criterion.nil?
375
- raise Errors::CriteriaArgumentRequired, :lte
376
- end
345
+ raise Errors::CriteriaArgumentRequired, :lte if criterion.nil?
377
346
 
378
- and_with_operator(criterion, "$lte")
347
+ and_with_operator(criterion, '$lte')
379
348
  end
380
- key :lte, :override, "$lte"
349
+ key :lte, :override, '$lte'
381
350
 
382
351
  # Add a $maxDistance selection to the selectable.
383
352
  #
@@ -388,12 +357,10 @@ module Mongoid
388
357
  #
389
358
  # @return [ Selectable ] The cloned selectable.
390
359
  def max_distance(criterion)
391
- if criterion.nil?
392
- raise Errors::CriteriaArgumentRequired, :max_distance
393
- end
360
+ raise Errors::CriteriaArgumentRequired, :max_distance if criterion.nil?
394
361
 
395
362
  # $maxDistance must be given together with $near
396
- __add__(criterion, "$maxDistance")
363
+ __add__(criterion, '$maxDistance')
397
364
  end
398
365
 
399
366
  # Adds $mod selection to the selectable.
@@ -408,13 +375,11 @@ module Mongoid
408
375
  #
409
376
  # @return [ Selectable ] The cloned selectable.
410
377
  def mod(criterion)
411
- if criterion.nil?
412
- raise Errors::CriteriaArgumentRequired, :mod
413
- end
378
+ raise Errors::CriteriaArgumentRequired, :mod if criterion.nil?
414
379
 
415
- and_with_operator(criterion, "$mod")
380
+ and_with_operator(criterion, '$mod')
416
381
  end
417
- key :mod, :override, "$mod"
382
+ key :mod, :override, '$mod'
418
383
 
419
384
  # Adds $ne selection to the selectable.
420
385
  #
@@ -428,14 +393,12 @@ module Mongoid
428
393
  #
429
394
  # @return [ Selectable ] The cloned selectable.
430
395
  def ne(criterion)
431
- if criterion.nil?
432
- raise Errors::CriteriaArgumentRequired, :ne
433
- end
396
+ raise Errors::CriteriaArgumentRequired, :ne if criterion.nil?
434
397
 
435
- and_with_operator(criterion, "$ne")
398
+ and_with_operator(criterion, '$ne')
436
399
  end
437
- alias :excludes :ne
438
- key :ne, :override, "$ne"
400
+ alias excludes ne
401
+ key :ne, :override, '$ne'
439
402
 
440
403
  # Adds a $near criterion to a geo selection.
441
404
  #
@@ -449,13 +412,11 @@ module Mongoid
449
412
  #
450
413
  # @return [ Selectable ] The cloned selectable.
451
414
  def near(criterion)
452
- if criterion.nil?
453
- raise Errors::CriteriaArgumentRequired, :near
454
- end
415
+ raise Errors::CriteriaArgumentRequired, :near if criterion.nil?
455
416
 
456
- and_with_operator(criterion, "$near")
417
+ and_with_operator(criterion, '$near')
457
418
  end
458
- key :near, :override, "$near"
419
+ key :near, :override, '$near'
459
420
 
460
421
  # Adds a $nearSphere criterion to a geo selection.
461
422
  #
@@ -469,13 +430,11 @@ module Mongoid
469
430
  #
470
431
  # @return [ Selectable ] The cloned selectable.
471
432
  def near_sphere(criterion)
472
- if criterion.nil?
473
- raise Errors::CriteriaArgumentRequired, :near_sphere
474
- end
433
+ raise Errors::CriteriaArgumentRequired, :near_sphere if criterion.nil?
475
434
 
476
- and_with_operator(criterion, "$nearSphere")
435
+ and_with_operator(criterion, '$nearSphere')
477
436
  end
478
- key :near_sphere, :override, "$nearSphere"
437
+ key :near_sphere, :override, '$nearSphere'
479
438
 
480
439
  # Adds the $nin selection to the selectable.
481
440
  #
@@ -492,26 +451,22 @@ module Mongoid
492
451
  #
493
452
  # @return [ Selectable ] The cloned selectable.
494
453
  def nin(condition)
495
- if condition.nil?
496
- raise Errors::CriteriaArgumentRequired, :nin
497
- end
454
+ raise Errors::CriteriaArgumentRequired, :nin if condition.nil?
498
455
 
499
456
  condition = expand_condition_to_array_values(condition)
500
457
 
501
458
  if strategy
502
- send(strategy, condition, "$nin")
459
+ send(strategy, condition, '$nin')
503
460
  else
504
461
  condition.inject(clone) do |query, (field, value)|
505
- v = {'$nin' => value}
506
- if negating?
507
- v = {'$not' => v}
508
- end
462
+ v = { '$nin' => value }
463
+ v = { '$not' => v } if negating?
509
464
  query.add_field_expression(field.to_s, v)
510
465
  end.reset_strategies!
511
466
  end
512
467
  end
513
- alias :not_in :nin
514
- key :nin, :intersect, "$nin"
468
+ alias not_in nin
469
+ key :nin, :intersect, '$nin'
515
470
 
516
471
  # Adds $nor selection to the selectable.
517
472
  #
@@ -536,16 +491,16 @@ module Mongoid
536
491
  !!negating
537
492
  end
538
493
 
539
- # Negate the arguments, or the next selection if no arguments are given.
540
- #
541
- # @example Negate the next selection.
542
- # selectable.not.in(field: [ 1, 2 ])
494
+ # Negate the arguments.
543
495
  #
544
496
  # @example Add the $not criterion.
545
- # selectable.not(name: /Bob/)
497
+ # Person.not(name: /Bob/)
546
498
  #
547
499
  # @example Execute a $not in a where query.
548
- # selectable.where(:field.not => /Bob/)
500
+ # Person.where(:name.not => /Bob/)
501
+ #
502
+ # @example Negate a Criteria instance
503
+ # Person.not(Person.where(...))
549
504
  #
550
505
  # @param [ [ Hash | Criteria ]... ] *criteria The key/value pair
551
506
  # matches or Criteria objects to negate.
@@ -553,34 +508,38 @@ module Mongoid
553
508
  # @return [ Selectable ] The new selectable.
554
509
  def not(*criteria)
555
510
  if criteria.empty?
511
+ # @deprecated
512
+ Mongoid.deprecation_warning(
513
+ :not_sans_arguments,
514
+ 'Calling `#not` without arguments is deprecated, and will be ' \
515
+ 'removed in the next major version. Instead, pass the Hash or ' \
516
+ 'Criteria instance to negate.',
517
+ caller_locations
518
+ )
556
519
  dup.tap { |query| query.negating = !query.negating }
557
520
  else
558
- criteria.compact.inject(self.clone) do |c, new_s|
559
- if new_s.is_a?(Selectable)
560
- new_s = new_s.selector
561
- end
521
+ criteria.compact.inject(clone) do |c, new_s|
522
+ new_s = new_s.selector if new_s.is_a?(Selectable)
562
523
  _mongoid_expand_keys(new_s).each do |k, v|
563
524
  k = k.to_s
564
525
  if c.selector[k] || k.start_with?('$')
565
- c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
526
+ c = c.send(:__multi__, [ { '$nor' => [ { k => v } ] } ], '$and')
527
+ elsif v.is_a?(Hash)
528
+ c = c.send(:__multi__, [ { '$nor' => [ { k => v } ] } ], '$and')
566
529
  else
567
- if v.is_a?(Hash)
568
- c = c.send(:__multi__, [{'$nor' => [{k => v}]}], '$and')
569
- else
570
- if v.is_a?(Regexp)
571
- negated_operator = '$not'
572
- else
573
- negated_operator = '$ne'
574
- end
575
- c = c.send(:__override__, {k => v}, negated_operator)
576
- end
530
+ negated_operator = if v.is_a?(Regexp)
531
+ '$not'
532
+ else
533
+ '$ne'
534
+ end
535
+ c = c.send(:__override__, { k => v }, negated_operator)
577
536
  end
578
537
  end
579
538
  c
580
539
  end
581
540
  end
582
541
  end
583
- key :not, :override, "$not"
542
+ key :not, :override, '$not'
584
543
 
585
544
  # Negate the arguments, constraining the query to only those documents
586
545
  # that do NOT match the arguments.
@@ -604,8 +563,8 @@ module Mongoid
604
563
 
605
564
  exprs = criteria.map do |criterion|
606
565
  _mongoid_expand_keys(
607
- criterion.is_a?(Selectable) ?
608
- criterion.selector : criterion)
566
+ criterion.is_a?(Selectable) ? criterion.selector : criterion
567
+ )
609
568
  end
610
569
 
611
570
  self.and('$nor' => exprs)
@@ -690,9 +649,9 @@ module Mongoid
690
649
  else
691
650
  Hash[criterion.map do |k, v|
692
651
  if k.is_a?(Symbol)
693
- [k.to_s, v]
652
+ [ k.to_s, v ]
694
653
  else
695
- [k, v]
654
+ [ k, v ]
696
655
  end
697
656
  end]
698
657
  end
@@ -716,15 +675,13 @@ module Mongoid
716
675
  #
717
676
  # @return [ Selectable ] The cloned selectable.
718
677
  def with_size(criterion)
719
- if criterion.nil?
720
- raise Errors::CriteriaArgumentRequired, :with_size
721
- end
678
+ raise Errors::CriteriaArgumentRequired, :with_size if criterion.nil?
722
679
 
723
- typed_override(criterion, "$size") do |value|
680
+ typed_override(criterion, '$size') do |value|
724
681
  ::Integer.evolve(value)
725
682
  end
726
683
  end
727
- key :with_size, :override, "$size" do |value|
684
+ key :with_size, :override, '$size' do |value|
728
685
  ::Integer.evolve(value)
729
686
  end
730
687
 
@@ -742,15 +699,13 @@ module Mongoid
742
699
  #
743
700
  # @return [ Selectable ] The cloned selectable.
744
701
  def with_type(criterion)
745
- if criterion.nil?
746
- raise Errors::CriteriaArgumentRequired, :with_type
747
- end
702
+ raise Errors::CriteriaArgumentRequired, :with_type if criterion.nil?
748
703
 
749
- typed_override(criterion, "$type") do |value|
704
+ typed_override(criterion, '$type') do |value|
750
705
  ::Integer.evolve(value)
751
706
  end
752
707
  end
753
- key :with_type, :override, "$type" do |value|
708
+ key :with_type, :override, '$type' do |value|
754
709
  ::Integer.evolve(value)
755
710
  end
756
711
 
@@ -774,12 +729,10 @@ module Mongoid
774
729
  #
775
730
  # @return [ Selectable ] The cloned selectable.
776
731
  def text_search(terms, opts = nil)
777
- if terms.nil?
778
- raise Errors::CriteriaArgumentRequired, :terms
779
- end
732
+ raise Errors::CriteriaArgumentRequired, :terms if terms.nil?
780
733
 
781
734
  clone.tap do |query|
782
- criterion = {'$text' => { '$search' => terms }}
735
+ criterion = { '$text' => { '$search' => terms } }
783
736
  criterion['$text'].merge!(opts) if opts
784
737
  if query.selector['$text']
785
738
  # Per https://www.mongodb.com/docs/manual/reference/operator/query/text/
@@ -788,7 +741,7 @@ module Mongoid
788
741
  # overwriting previous text search condition with the currently
789
742
  # given one.
790
743
  Mongoid.logger.warn('Multiple $text expressions per query are not currently supported by the server')
791
- query.selector = {'$and' => [query.selector]}.merge(criterion)
744
+ query.selector = { '$and' => [ query.selector ] }.merge(criterion)
792
745
  else
793
746
  query.selector = query.selector.merge(criterion)
794
747
  end
@@ -810,10 +763,10 @@ module Mongoid
810
763
  #
811
764
  # @return [ Selectable ] The cloned selectable.
812
765
  def where(*criteria)
813
- criteria.inject(clone) do |query, criterion|
814
- if criterion.nil?
815
- raise Errors::CriteriaArgumentRequired, :where
816
- end
766
+ return clone.reset_strategies! if criteria.empty?
767
+
768
+ criteria.inject(self) do |query, criterion|
769
+ raise Errors::CriteriaArgumentRequired, :where if criterion.nil?
817
770
 
818
771
  # We need to save the criterion in an instance variable so
819
772
  # Modifiable methods know how to create a polymorphic object.
@@ -823,14 +776,31 @@ module Mongoid
823
776
  # only ever specify one criterion to #where.
824
777
  @criterion = criterion
825
778
  if criterion.is_a?(String)
826
- js_query(criterion)
779
+ unless Mongoid.allow_unsafe_query_operators?
780
+ raise Errors::InvalidQuery,
781
+ "String criteria are not allowed because they compile to the '$where' operator, " \
782
+ 'which is not allowed in a query expression. Set Mongoid.allow_unsafe_query_operators = true ' \
783
+ 'to permit all operators.'
784
+ end
785
+ query.js_query(criterion)
827
786
  else
828
- expr_query(criterion)
787
+ query.expr_query(criterion)
829
788
  end
830
- end.reset_strategies!
789
+ end
831
790
  end
832
791
 
833
- private
792
+ # Operators permitted at the top level of a query expression without
793
+ # opt-in. Excludes $where (JS execution) and other operators not needed
794
+ # for ordinary application queries.
795
+ ALLOWED_QUERY_OPERATORS = %w[
796
+ $and $or $nor $not $text $comment $expr $jsonSchema $alwaysFalse $alwaysTrue
797
+ ].freeze
798
+
799
+ # Operators that execute server-side JavaScript. These are rejected at
800
+ # any depth, not just at the top level: the allowlist above permits
801
+ # $expr and the logical operators, and their values are arbitrary
802
+ # nested expressions that can carry $function or $where.
803
+ JAVASCRIPT_QUERY_OPERATORS = %w[$where $function $accumulator].freeze
834
804
 
835
805
  # Adds the specified expression to the query.
836
806
  #
@@ -850,19 +820,18 @@ module Mongoid
850
820
  # @return [ Selectable ] The cloned selectable.
851
821
  # @api private
852
822
  def expr_query(criterion)
853
- if criterion.nil?
854
- raise ArgumentError, 'Criterion cannot be nil here'
855
- end
856
- unless Hash === criterion
823
+ raise ArgumentError, 'Criterion cannot be nil here' if criterion.nil?
824
+ unless criterion.is_a?(Hash)
857
825
  raise Errors::InvalidQuery, "Expression must be a Hash: #{Errors::InvalidQuery.truncate_expr(criterion)}"
858
826
  end
859
827
 
828
+ # The operator guard is applied by _mongoid_expand_keys, which every
829
+ # query method that accepts a user-supplied expression passes through.
860
830
  normalized = _mongoid_expand_keys(criterion)
861
831
  clone.tap do |query|
862
832
  normalized.each do |field, value|
863
833
  field_s = field.to_s
864
834
  if field_s.start_with?('$')
865
- # Query expression-level operator, like $and or $where
866
835
  query.add_operator_expression(field_s, value)
867
836
  else
868
837
  query.add_field_expression(field, value)
@@ -872,25 +841,6 @@ module Mongoid
872
841
  end
873
842
  end
874
843
 
875
- # Force the values of the criterion to be evolved.
876
- #
877
- # @api private
878
- #
879
- # @example Force values to booleans.
880
- # selectable.force_typing(criterion) do |val|
881
- # Boolean.evolve(val)
882
- # end
883
- #
884
- # @param [ Hash ] criterion The criterion.
885
- def typed_override(criterion, operator)
886
- if criterion
887
- criterion.transform_values! do |value|
888
- yield(value)
889
- end
890
- end
891
- __override__(criterion, operator)
892
- end
893
-
894
844
  # Create a javascript selection.
895
845
  #
896
846
  # @api private
@@ -905,7 +855,7 @@ module Mongoid
905
855
  clone.tap do |query|
906
856
  if negating?
907
857
  query.add_operator_expression('$and',
908
- [{'$nor' => [{'$where' => criterion}]}])
858
+ [ { '$nor' => [ { '$where' => criterion } ] } ])
909
859
  else
910
860
  query.add_operator_expression('$where', criterion)
911
861
  end
@@ -913,6 +863,111 @@ module Mongoid
913
863
  end
914
864
  end
915
865
 
866
+ private
867
+
868
+ # Enforces the operator rules governed by the
869
+ # +allow_unsafe_query_operators+ configuration option against a
870
+ # normalized query expression.
871
+ #
872
+ # Two rules apply, and both are skipped when the option is true:
873
+ #
874
+ # - An operator at the top level of the expression must appear in
875
+ # ALLOWED_QUERY_OPERATORS.
876
+ # - An operator in JAVASCRIPT_QUERY_OPERATORS is rejected at any depth.
877
+ #
878
+ # This is called from #_mongoid_expand_keys rather than from the
879
+ # individual query methods, because that is the one point every query
880
+ # method taking a user-supplied expression passes through on its way to
881
+ # the selector.
882
+ #
883
+ # It deliberately does not cover the APIs that ask for JavaScript
884
+ # outright, such as #js_query and Criteria#for_js: there the developer
885
+ # has chosen server-side JavaScript, so there is nothing to guard
886
+ # against. The same goes for the low-level Storable methods
887
+ # (#add_field_expression, #add_operator_expression), which write to the
888
+ # selector directly.
889
+ #
890
+ # @param [ Hash ] expr A normalized query expression.
891
+ #
892
+ # @raise [ Errors::InvalidQuery ] If a disallowed operator is present.
893
+ #
894
+ # @api private
895
+ def _mongoid_validate_operators!(expr)
896
+ return if Mongoid.allow_unsafe_query_operators?
897
+
898
+ expr.each_key do |field|
899
+ field_s = field.to_s
900
+ next unless field_s.start_with?('$')
901
+ next if ALLOWED_QUERY_OPERATORS.include?(field_s)
902
+
903
+ raise Errors::InvalidQuery,
904
+ "Operator '#{field_s}' is not allowed in a query expression. " \
905
+ 'Set Mongoid.allow_unsafe_query_operators = true to permit all operators.'
906
+ end
907
+
908
+ _mongoid_validate_no_javascript!(expr)
909
+ end
910
+
911
+ # Walks a query expression looking for operators that execute
912
+ # server-side JavaScript, descending through both hashes and arrays so
913
+ # that nested forms such as {'$expr' => {'$function' => ...}} and
914
+ # {'$or' => [ {'$where' => ...} ]} are caught.
915
+ #
916
+ # The walk does not distinguish operator position from value position,
917
+ # so it also rejects queries where a JavaScript operator name appears as
918
+ # data rather than as an operator. Server 5.0+ permits $-prefixed field
919
+ # names in stored documents, which makes this reachable:
920
+ #
921
+ # Doc.where(payload: { '$eq' => { '$function' => 'abc' } })
922
+ #
923
+ # Here the $eq marks its argument as a literal value to compare, so the
924
+ # server never evaluates it, but the guard raises anyway. The only
925
+ # workaround today is the global allow_unsafe_query_operators flag.
926
+ #
927
+ # TODO: discuss whether to track operator position (skipping the subtree
928
+ # under $eq, $ne, $in, $nin, and $elemMatch values) in a future
929
+ # iteration. It removes the false positive but adds exactly the kind of
930
+ # state that a real bypass could hide in, so it was left out for now.
931
+ #
932
+ # @param [ Object ] object A fragment of a query expression.
933
+ #
934
+ # @raise [ Errors::InvalidQuery ] If a JavaScript operator is present.
935
+ #
936
+ # @api private
937
+ def _mongoid_validate_no_javascript!(object)
938
+ case object
939
+ when Hash
940
+ object.each do |key, value|
941
+ key_s = key.to_s
942
+ if JAVASCRIPT_QUERY_OPERATORS.include?(key_s)
943
+ raise Errors::InvalidQuery,
944
+ "Operator '#{key_s}' executes server-side JavaScript and is not allowed " \
945
+ 'anywhere in a query expression. Set Mongoid.allow_unsafe_query_operators = true ' \
946
+ 'to permit all operators.'
947
+ end
948
+
949
+ _mongoid_validate_no_javascript!(value)
950
+ end
951
+ when Array
952
+ object.each { |value| _mongoid_validate_no_javascript!(value) }
953
+ end
954
+ end
955
+
956
+ # Force the values of the criterion to be evolved.
957
+ #
958
+ # @api private
959
+ #
960
+ # @example Force values to booleans.
961
+ # selectable.force_typing(criterion) do |val|
962
+ # Boolean.evolve(val)
963
+ # end
964
+ #
965
+ # @param [ Hash ] criterion The criterion.
966
+ def typed_override(criterion, operator, &block)
967
+ criterion.transform_values!(&block) if criterion
968
+ __override__(criterion, operator)
969
+ end
970
+
916
971
  # Take the provided criterion and store it as a selection in the query
917
972
  # selector.
918
973
  #
@@ -935,7 +990,6 @@ module Mongoid
935
990
  end
936
991
 
937
992
  class << self
938
-
939
993
  # Get the methods on the selectable that can be forwarded to from a model.
940
994
  #
941
995
  # @example Get the forwardable methods.
@@ -944,7 +998,7 @@ module Mongoid
944
998
  # @return [ Array<Symbol> ] The names of the forwardable methods.
945
999
  def forwardables
946
1000
  public_instance_methods(false) -
947
- [ :negating, :negating=, :negating?, :selector, :selector= ]
1001
+ %i[negating negating= negating? selector selector=]
948
1002
  end
949
1003
  end
950
1004
  end