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,89 +1,84 @@
1
1
  # frozen_string_literal: true
2
- # rubocop:todo all
3
2
 
4
- require "spec_helper"
5
- require_relative './selectable_shared_examples'
3
+ require 'spec_helper'
4
+ require_relative 'selectable_shared_examples'
6
5
 
7
6
  describe Mongoid::Criteria::Queryable::Selectable do
8
-
9
7
  let(:query) do
10
- Mongoid::Query.new("id" => "_id")
8
+ Mongoid::Query.new('id' => '_id')
11
9
  end
12
10
 
13
- describe "#where" do
14
-
11
+ describe '#where' do
15
12
  let(:query_method) { :where }
16
13
 
17
- context "when provided no criterion" do
18
-
14
+ context 'when provided no criterion' do
19
15
  let(:selection) do
20
16
  query.where
21
17
  end
22
18
 
23
- it "does not add any criterion" do
19
+ it 'does not add any criterion' do
24
20
  expect(selection.selector).to eq({})
25
21
  end
26
22
 
27
- it "returns the query" do
23
+ it 'returns the query' do
28
24
  expect(selection).to eq(query)
29
25
  end
30
26
 
31
- it "returns a cloned query" do
32
- expect(selection).to_not equal(query)
27
+ it 'returns a cloned query' do
28
+ expect(selection).not_to equal(query)
33
29
  end
34
30
  end
35
31
 
36
32
  it_behaves_like 'requires a non-nil argument'
37
33
 
38
- context "when provided a string" do
34
+ context 'when provided a string' do
35
+ # String criteria compile to $where, which requires the opt-in.
36
+ config_override :allow_unsafe_query_operators, true
39
37
 
40
38
  let(:selection) do
41
- query.where("this.value = 10")
39
+ query.where('this.value = 10')
42
40
  end
43
41
 
44
- it "adds the $where criterion" do
45
- expect(selection.selector).to eq({ "$where" => "this.value = 10" })
42
+ it 'adds the $where criterion' do
43
+ expect(selection.selector).to eq({ '$where' => 'this.value = 10' })
46
44
  end
47
45
 
48
- it "returns a cloned query" do
49
- expect(selection).to_not equal(query)
46
+ it 'returns a cloned query' do
47
+ expect(selection).not_to equal(query)
50
48
  end
51
49
 
52
50
  context 'when multiple calls with string argument are made' do
53
-
54
51
  let(:selection) do
55
- query.where("this.value = 10").where('foo.bar')
52
+ query.where('this.value = 10').where('foo.bar')
56
53
  end
57
54
 
58
55
  it 'combines conditions' do
59
56
  expect(selection.selector).to eq(
60
- "$where" => "this.value = 10", '$and' => [{'$where' => 'foo.bar'}],
57
+ '$where' => 'this.value = 10', '$and' => [ { '$where' => 'foo.bar' } ]
61
58
  )
62
59
  end
63
60
  end
64
61
 
65
62
  context 'when called with string argument and with hash argument' do
66
-
67
63
  let(:selection) do
68
- query.where("this.value = 10").where(foo: 'bar')
64
+ query.where('this.value = 10').where(foo: 'bar')
69
65
  end
70
66
 
71
67
  it 'combines conditions' do
72
68
  expect(selection.selector).to eq(
73
- "$where" => "this.value = 10", 'foo' => 'bar',
69
+ '$where' => 'this.value = 10', 'foo' => 'bar'
74
70
  )
75
71
  end
76
72
  end
77
73
 
78
74
  context 'when called with hash argument and with string argument' do
79
-
80
75
  let(:selection) do
81
- query.where(foo: 'bar').where("this.value = 10")
76
+ query.where(foo: 'bar').where('this.value = 10')
82
77
  end
83
78
 
84
79
  it 'combines conditions' do
85
80
  expect(selection.selector).to eq(
86
- 'foo' => 'bar', "$where" => "this.value = 10",
81
+ 'foo' => 'bar', '$where' => 'this.value = 10'
87
82
  )
88
83
  end
89
84
  end
@@ -91,46 +86,41 @@ describe Mongoid::Criteria::Queryable::Selectable do
91
86
  context 'when called with two hash arguments' do
92
87
  context 'when arguments use operators' do
93
88
  shared_examples 'combines conditions' do
94
-
95
89
  it 'combines conditions' do
96
90
  expect(selection.selector).to eq(
97
- 'foo' => {'$in' => [1]},
98
- '$and' => ['foo' => {'$in' => [2]}],
91
+ 'foo' => { '$in' => [ 1 ] },
92
+ '$and' => [ { 'foo' => { '$in' => [ 2 ] } } ]
99
93
  )
100
94
  end
101
95
  end
102
96
 
103
97
  context 'string operators' do
104
-
105
98
  let(:selection) do
106
- query.where(foo: {'$in' => [1]}).where(foo: {'$in' => [2]})
99
+ query.where(foo: { '$in' => [ 1 ] }).where(foo: { '$in' => [ 2 ] })
107
100
  end
108
101
 
109
102
  include_examples 'combines conditions'
110
103
  end
111
104
 
112
105
  context 'symbol operators' do
113
-
114
106
  let(:selection) do
115
- query.where(foo: {:$in => [1]}).where(foo: {:$in => [2]})
107
+ query.where(foo: { :$in => [ 1 ] }).where(foo: { :$in => [ 2 ] })
116
108
  end
117
109
 
118
110
  include_examples 'combines conditions'
119
111
  end
120
112
 
121
113
  context 'string and symbol operators' do
122
-
123
114
  let(:selection) do
124
- query.where(foo: {'$in' => [1]}).where(foo: {:$in => [2]})
115
+ query.where(foo: { '$in' => [ 1 ] }).where(foo: { :$in => [ 2 ] })
125
116
  end
126
117
 
127
118
  include_examples 'combines conditions'
128
119
  end
129
120
 
130
121
  context 'symbol and string operators' do
131
-
132
122
  let(:selection) do
133
- query.where(foo: {:$in => [1]}).where(foo: {'$in' => [2]})
123
+ query.where(foo: { :$in => [ 1 ] }).where(foo: { '$in' => [ 2 ] })
134
124
  end
135
125
 
136
126
  include_examples 'combines conditions'
@@ -139,26 +129,24 @@ describe Mongoid::Criteria::Queryable::Selectable do
139
129
  end
140
130
  end
141
131
 
142
- context "when provided a single criterion" do
143
-
144
- context "when the value needs no evolution" do
145
-
132
+ context 'when provided a single criterion' do
133
+ context 'when the value needs no evolution' do
146
134
  let(:selection) do
147
- query.where(name: "Syd")
135
+ query.where(name: 'Syd')
148
136
  end
149
137
 
150
- it "adds the criterion to the selection" do
151
- expect(selection.selector).to eq({ "name" => "Syd" })
138
+ it 'adds the criterion to the selection' do
139
+ expect(selection.selector).to eq({ 'name' => 'Syd' })
152
140
  end
153
141
  end
154
142
 
155
- context "when the value must be evolved" do
156
-
143
+ context 'when the value must be evolved' do
157
144
  before(:all) do
158
145
  class Document
159
146
  def id
160
147
  13
161
148
  end
149
+
162
150
  def self.evolve(object)
163
151
  object.id
164
152
  end
@@ -169,10 +157,9 @@ describe Mongoid::Criteria::Queryable::Selectable do
169
157
  Object.send(:remove_const, :Document)
170
158
  end
171
159
 
172
- context "when the key needs evolution" do
173
-
160
+ context 'when the key needs evolution' do
174
161
  let(:query) do
175
- Mongoid::Query.new({ "user" => "user_id" })
162
+ Mongoid::Query.new({ 'user' => 'user_id' })
176
163
  end
177
164
 
178
165
  let(:document) do
@@ -183,13 +170,12 @@ describe Mongoid::Criteria::Queryable::Selectable do
183
170
  query.where(user: document)
184
171
  end
185
172
 
186
- it "alters the key and value" do
187
- expect(selection.selector).to eq({ "user_id" => document.id })
173
+ it 'alters the key and value' do
174
+ expect(selection.selector).to eq({ 'user_id' => document.id })
188
175
  end
189
176
  end
190
177
 
191
178
  context 'when the field is a String and the value is a BSON::Regexp::Raw' do
192
-
193
179
  let(:raw_regexp) do
194
180
  BSON::Regexp::Raw.new('^Em')
195
181
  end
@@ -199,338 +185,314 @@ describe Mongoid::Criteria::Queryable::Selectable do
199
185
  end
200
186
 
201
187
  it 'does not convert the bson raw regexp object to a String' do
202
- expect(selection.selector).to eq({ "_id" => raw_regexp })
188
+ expect(selection.selector).to eq({ '_id' => raw_regexp })
203
189
  end
204
190
  end
205
191
  end
206
192
  end
207
193
 
208
- context "when provided complex criterion" do
209
-
210
- context "when performing an $all" do
211
-
212
- context "when performing a single query" do
213
-
194
+ context 'when provided complex criterion' do
195
+ context 'when performing an $all' do
196
+ context 'when performing a single query' do
214
197
  let(:selection) do
215
198
  query.where(:field.all => [ 1, 2 ])
216
199
  end
217
200
 
218
- it "adds the $all criterion" do
219
- expect(selection.selector).to eq({ "field" => { "$all" => [ 1, 2 ] }})
201
+ it 'adds the $all criterion' do
202
+ expect(selection.selector).to eq({ 'field' => { '$all' => [ 1, 2 ] } })
220
203
  end
221
204
 
222
- it "returns a cloned query" do
223
- expect(selection).to_not eq(query)
205
+ it 'returns a cloned query' do
206
+ expect(selection).not_to eq(query)
224
207
  end
225
208
  end
226
209
  end
227
210
 
228
- context "when performing an $elemMatch" do
229
-
230
- context "when the value is not complex" do
231
-
211
+ context 'when performing an $elemMatch' do
212
+ context 'when the value is not complex' do
232
213
  let(:selection) do
233
214
  query.where(:field.elem_match => { key: 1 })
234
215
  end
235
216
 
236
- it "adds the $elemMatch criterion" do
217
+ it 'adds the $elemMatch criterion' do
237
218
  expect(selection.selector).to eq(
238
- { "field" => { "$elemMatch" => { 'key' => 1 } }}
219
+ { 'field' => { '$elemMatch' => { 'key' => 1 } } }
239
220
  )
240
221
  end
241
222
 
242
- it "returns a cloned query" do
243
- expect(selection).to_not eq(query)
223
+ it 'returns a cloned query' do
224
+ expect(selection).not_to eq(query)
244
225
  end
245
226
  end
246
227
 
247
- context "when the value is complex" do
248
-
228
+ context 'when the value is complex' do
249
229
  let(:selection) do
250
230
  query.where(:field.elem_match => { :key.gt => 1 })
251
231
  end
252
232
 
253
- it "adds the $elemMatch criterion" do
233
+ it 'adds the $elemMatch criterion' do
254
234
  expect(selection.selector).to eq(
255
- { "field" => { "$elemMatch" => { "key" => { "$gt" => 1 }}}}
235
+ { 'field' => { '$elemMatch' => { 'key' => { '$gt' => 1 } } } }
256
236
  )
257
237
  end
258
238
 
259
- it "returns a cloned query" do
260
- expect(selection).to_not eq(query)
239
+ it 'returns a cloned query' do
240
+ expect(selection).not_to eq(query)
261
241
  end
262
242
  end
263
243
  end
264
244
 
265
- context "when performing an $exists" do
266
-
267
- context "when providing boolean values" do
268
-
245
+ context 'when performing an $exists' do
246
+ context 'when providing boolean values' do
269
247
  let(:selection) do
270
248
  query.where(:field.exists => true)
271
249
  end
272
250
 
273
- it "adds the $exists criterion" do
251
+ it 'adds the $exists criterion' do
274
252
  expect(selection.selector).to eq(
275
- { "field" => { "$exists" => true }}
253
+ { 'field' => { '$exists' => true } }
276
254
  )
277
255
  end
278
256
 
279
- it "returns a cloned query" do
280
- expect(selection).to_not eq(query)
257
+ it 'returns a cloned query' do
258
+ expect(selection).not_to eq(query)
281
259
  end
282
260
  end
283
261
 
284
- context "when providing string values" do
285
-
262
+ context 'when providing string values' do
286
263
  let(:selection) do
287
- query.where(:field.exists => "t")
264
+ query.where(:field.exists => 't')
288
265
  end
289
266
 
290
- it "adds the $exists criterion" do
267
+ it 'adds the $exists criterion' do
291
268
  expect(selection.selector).to eq(
292
- { "field" => { "$exists" => true }}
269
+ { 'field' => { '$exists' => true } }
293
270
  )
294
271
  end
295
272
 
296
- it "returns a cloned query" do
297
- expect(selection).to_not eq(query)
273
+ it 'returns a cloned query' do
274
+ expect(selection).not_to eq(query)
298
275
  end
299
276
  end
300
277
  end
301
278
 
302
- context "when performing a $gt" do
303
-
279
+ context 'when performing a $gt' do
304
280
  let(:selection) do
305
281
  query.where(:field.gt => 10)
306
282
  end
307
283
 
308
- it "adds the $gt criterion" do
284
+ it 'adds the $gt criterion' do
309
285
  expect(selection.selector).to eq(
310
- { "field" => { "$gt" => 10 }}
286
+ { 'field' => { '$gt' => 10 } }
311
287
  )
312
288
  end
313
289
 
314
- it "returns a cloned query" do
315
- expect(selection).to_not eq(query)
290
+ it 'returns a cloned query' do
291
+ expect(selection).not_to eq(query)
316
292
  end
317
293
  end
318
294
 
319
- context "when performing a $gte" do
320
-
295
+ context 'when performing a $gte' do
321
296
  let(:selection) do
322
297
  query.where(:field.gte => 10)
323
298
  end
324
299
 
325
- it "adds the $gte criterion" do
300
+ it 'adds the $gte criterion' do
326
301
  expect(selection.selector).to eq(
327
- { "field" => { "$gte" => 10 }}
302
+ { 'field' => { '$gte' => 10 } }
328
303
  )
329
304
  end
330
305
 
331
- it "returns a cloned query" do
332
- expect(selection).to_not eq(query)
306
+ it 'returns a cloned query' do
307
+ expect(selection).not_to eq(query)
333
308
  end
334
309
  end
335
310
 
336
- context "when performing an $in" do
337
-
311
+ context 'when performing an $in' do
338
312
  let(:selection) do
339
313
  query.where(:field.in => [ 1, 2 ])
340
314
  end
341
315
 
342
- it "adds the $in criterion" do
343
- expect(selection.selector).to eq({ "field" => { "$in" => [ 1, 2 ] }})
316
+ it 'adds the $in criterion' do
317
+ expect(selection.selector).to eq({ 'field' => { '$in' => [ 1, 2 ] } })
344
318
  end
345
319
 
346
- it "returns a cloned query" do
347
- expect(selection).to_not eq(query)
320
+ it 'returns a cloned query' do
321
+ expect(selection).not_to eq(query)
348
322
  end
349
323
  end
350
324
 
351
- context "when performing a $lt" do
352
-
325
+ context 'when performing a $lt' do
353
326
  let(:selection) do
354
327
  query.where(:field.lt => 10)
355
328
  end
356
329
 
357
- it "adds the $lt criterion" do
330
+ it 'adds the $lt criterion' do
358
331
  expect(selection.selector).to eq(
359
- { "field" => { "$lt" => 10 }}
332
+ { 'field' => { '$lt' => 10 } }
360
333
  )
361
334
  end
362
335
 
363
- it "returns a cloned query" do
364
- expect(selection).to_not eq(query)
336
+ it 'returns a cloned query' do
337
+ expect(selection).not_to eq(query)
365
338
  end
366
339
  end
367
340
 
368
- context "when performing a $lte" do
369
-
341
+ context 'when performing a $lte' do
370
342
  let(:selection) do
371
343
  query.where(:field.lte => 10)
372
344
  end
373
345
 
374
- it "adds the $lte criterion" do
346
+ it 'adds the $lte criterion' do
375
347
  expect(selection.selector).to eq(
376
- { "field" => { "$lte" => 10 }}
348
+ { 'field' => { '$lte' => 10 } }
377
349
  )
378
350
  end
379
351
 
380
- it "returns a cloned query" do
381
- expect(selection).to_not eq(query)
352
+ it 'returns a cloned query' do
353
+ expect(selection).not_to eq(query)
382
354
  end
383
355
  end
384
356
 
385
- context "when performing a $mod" do
386
-
357
+ context 'when performing a $mod' do
387
358
  let(:selection) do
388
359
  query.where(:field.mod => [ 10, 1 ])
389
360
  end
390
361
 
391
- it "adds the $lte criterion" do
362
+ it 'adds the $lte criterion' do
392
363
  expect(selection.selector).to eq(
393
- { "field" => { "$mod" => [ 10, 1 ]}}
364
+ { 'field' => { '$mod' => [ 10, 1 ] } }
394
365
  )
395
366
  end
396
367
 
397
- it "returns a cloned query" do
398
- expect(selection).to_not eq(query)
368
+ it 'returns a cloned query' do
369
+ expect(selection).not_to eq(query)
399
370
  end
400
371
  end
401
372
 
402
- context "when performing a $ne" do
403
-
373
+ context 'when performing a $ne' do
404
374
  let(:selection) do
405
375
  query.where(:field.ne => 10)
406
376
  end
407
377
 
408
- it "adds the $ne criterion" do
378
+ it 'adds the $ne criterion' do
409
379
  expect(selection.selector).to eq(
410
- { "field" => { "$ne" => 10 }}
380
+ { 'field' => { '$ne' => 10 } }
411
381
  )
412
382
  end
413
383
 
414
- it "returns a cloned query" do
415
- expect(selection).to_not eq(query)
384
+ it 'returns a cloned query' do
385
+ expect(selection).not_to eq(query)
416
386
  end
417
387
  end
418
388
 
419
- context "when performing a $near" do
420
-
389
+ context 'when performing a $near' do
421
390
  let(:selection) do
422
391
  query.where(:field.near => [ 1, 1 ])
423
392
  end
424
393
 
425
- it "adds the $near criterion" do
394
+ it 'adds the $near criterion' do
426
395
  expect(selection.selector).to eq(
427
- { "field" => { "$near" => [ 1, 1 ] }}
396
+ { 'field' => { '$near' => [ 1, 1 ] } }
428
397
  )
429
398
  end
430
399
 
431
- it "returns a cloned query" do
432
- expect(selection).to_not eq(query)
400
+ it 'returns a cloned query' do
401
+ expect(selection).not_to eq(query)
433
402
  end
434
403
  end
435
404
 
436
- context "when performing a $nearSphere" do
437
-
405
+ context 'when performing a $nearSphere' do
438
406
  let(:selection) do
439
407
  query.where(:field.near_sphere => [ 1, 1 ])
440
408
  end
441
409
 
442
- it "adds the $nearSphere criterion" do
410
+ it 'adds the $nearSphere criterion' do
443
411
  expect(selection.selector).to eq(
444
- { "field" => { "$nearSphere" => [ 1, 1 ] }}
412
+ { 'field' => { '$nearSphere' => [ 1, 1 ] } }
445
413
  )
446
414
  end
447
415
 
448
- it "returns a cloned query" do
449
- expect(selection).to_not eq(query)
416
+ it 'returns a cloned query' do
417
+ expect(selection).not_to eq(query)
450
418
  end
451
419
  end
452
420
 
453
- context "when performing a $nin" do
454
-
421
+ context 'when performing a $nin' do
455
422
  let(:selection) do
456
423
  query.where(:field.nin => [ 1, 2 ])
457
424
  end
458
425
 
459
- it "adds the $nin criterion" do
460
- expect(selection.selector).to eq({ "field" => { "$nin" => [ 1, 2 ] }})
426
+ it 'adds the $nin criterion' do
427
+ expect(selection.selector).to eq({ 'field' => { '$nin' => [ 1, 2 ] } })
461
428
  end
462
429
 
463
- it "returns a cloned query" do
464
- expect(selection).to_not eq(query)
430
+ it 'returns a cloned query' do
431
+ expect(selection).not_to eq(query)
465
432
  end
466
433
  end
467
434
 
468
- context "when performing a $not" do
469
-
435
+ context 'when performing a $not' do
470
436
  let(:selection) do
471
437
  query.where(:field.not => /test/)
472
438
  end
473
439
 
474
- it "adds the $not criterion" do
475
- expect(selection.selector).to eq({ "field" => { "$not" => /test/ }})
440
+ it 'adds the $not criterion' do
441
+ expect(selection.selector).to eq({ 'field' => { '$not' => /test/ } })
476
442
  end
477
443
 
478
- it "returns a cloned query" do
479
- expect(selection).to_not eq(query)
444
+ it 'returns a cloned query' do
445
+ expect(selection).not_to eq(query)
480
446
  end
481
447
  end
482
448
 
483
- context "when performing a $size" do
484
-
485
- context "when providing an integer" do
486
-
449
+ context 'when performing a $size' do
450
+ context 'when providing an integer' do
487
451
  let(:selection) do
488
452
  query.where(:field.with_size => 10)
489
453
  end
490
454
 
491
- it "adds the $size criterion" do
455
+ it 'adds the $size criterion' do
492
456
  expect(selection.selector).to eq(
493
- { "field" => { "$size" => 10 }}
457
+ { 'field' => { '$size' => 10 } }
494
458
  )
495
459
  end
496
460
 
497
- it "returns a cloned query" do
498
- expect(selection).to_not eq(query)
461
+ it 'returns a cloned query' do
462
+ expect(selection).not_to eq(query)
499
463
  end
500
464
  end
501
465
 
502
- context "when providing a string" do
503
-
466
+ context 'when providing a string' do
504
467
  let(:selection) do
505
- query.where(:field.with_size => "10")
468
+ query.where(:field.with_size => '10')
506
469
  end
507
470
 
508
- it "adds the $size criterion" do
471
+ it 'adds the $size criterion' do
509
472
  expect(selection.selector).to eq(
510
- { "field" => { "$size" => 10 }}
473
+ { 'field' => { '$size' => 10 } }
511
474
  )
512
475
  end
513
476
 
514
- it "returns a cloned query" do
515
- expect(selection).to_not eq(query)
477
+ it 'returns a cloned query' do
478
+ expect(selection).not_to eq(query)
516
479
  end
517
480
  end
518
481
  end
519
482
 
520
- context "when performing a $type" do
521
-
483
+ context 'when performing a $type' do
522
484
  let(:selection) do
523
485
  query.where(:field.with_type => 10)
524
486
  end
525
487
 
526
- it "adds the $type criterion" do
488
+ it 'adds the $type criterion' do
527
489
  expect(selection.selector).to eq(
528
- { "field" => { "$type" => 10 }}
490
+ { 'field' => { '$type' => 10 } }
529
491
  )
530
492
  end
531
493
 
532
- it "returns a cloned query" do
533
- expect(selection).to_not eq(query)
494
+ it 'returns a cloned query' do
495
+ expect(selection).not_to eq(query)
534
496
  end
535
497
  end
536
498
  end
@@ -541,24 +503,28 @@ describe Mongoid::Criteria::Queryable::Selectable do
541
503
  end
542
504
 
543
505
  let(:selection) do
544
- base_query.where(mql_operator => ['hello' => 'world'])
506
+ base_query.where(mql_operator => [ { 'hello' => 'world' } ])
545
507
  end
546
508
 
547
509
  shared_examples_for 'adds conditions to existing query' do
548
510
  it 'adds conditions to existing query' do
549
- selection.selector.should == {
550
- 'test' => 1,
551
- mql_operator => ['hello' => 'world'],
552
- }
511
+ selection.selector.should eq(
512
+ {
513
+ 'test' => 1,
514
+ mql_operator => [ { 'hello' => 'world' } ]
515
+ }
516
+ )
553
517
  end
554
518
  end
555
519
 
556
520
  shared_examples_for 'adds conditions to existing query with an extra $and' do
557
521
  it 'adds conditions to existing query' do
558
- selection.selector.should == {
559
- 'test' => 1,
560
- mql_operator => ['hello' => 'world'],
561
- }
522
+ selection.selector.should eq(
523
+ {
524
+ 'test' => 1,
525
+ mql_operator => [ { 'hello' => 'world' } ]
526
+ }
527
+ )
562
528
  end
563
529
  end
564
530
 
@@ -587,4 +553,202 @@ describe Mongoid::Criteria::Queryable::Selectable do
587
553
  end
588
554
  end
589
555
  end
556
+
557
+ describe 'top-level operator injection guard' do
558
+ context 'when allow_unsafe_query_operators is true' do
559
+ config_override :allow_unsafe_query_operators, true
560
+
561
+ context 'when passing $where' do
562
+ it 'does not raise' do
563
+ expect do
564
+ query.where('$where' => 'this.name == "admin"')
565
+ end.not_to raise_error
566
+ end
567
+ end
568
+
569
+ context 'when passing $function' do
570
+ it 'does not raise' do
571
+ expect do
572
+ query.where('$function' => { body: 'function() { return true; }', args: [], lang: 'js' })
573
+ end.not_to raise_error
574
+ end
575
+ end
576
+
577
+ context 'when passing a string criterion' do
578
+ it 'does not raise' do
579
+ expect do
580
+ query.where('this.name == "admin"')
581
+ end.not_to raise_error
582
+ end
583
+ end
584
+
585
+ context 'when passing a string criterion to a negated query' do
586
+ it 'does not raise' do
587
+ expect do
588
+ query.not.where('this.name == "admin"')
589
+ end.not_to raise_error
590
+ end
591
+ end
592
+ end
593
+
594
+ context 'when allow_unsafe_query_operators is false' do
595
+ config_override :allow_unsafe_query_operators, false
596
+
597
+ context 'when passing $where' do
598
+ it 'raises InvalidQuery' do
599
+ expect do
600
+ query.where('$where' => 'this.name == "admin"')
601
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /\$where/)
602
+ end
603
+ end
604
+
605
+ context 'when passing $function' do
606
+ it 'raises InvalidQuery' do
607
+ expect do
608
+ query.where('$function' => { body: 'function() { return true; }', args: [], lang: 'js' })
609
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /\$function/)
610
+ end
611
+ end
612
+
613
+ context 'when the error mentions allow_unsafe_query_operators' do
614
+ it 'includes the config opt-in in the message' do
615
+ expect do
616
+ query.where('$where' => 'true')
617
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /allow_unsafe_query_operators/)
618
+ end
619
+ end
620
+
621
+ context 'when passing a string criterion' do
622
+ it 'raises InvalidQuery' do
623
+ expect do
624
+ query.where('this.name == "admin"')
625
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /\$where/)
626
+ end
627
+
628
+ it 'includes the config opt-in in the message' do
629
+ expect do
630
+ query.where('this.name == "admin"')
631
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /allow_unsafe_query_operators/)
632
+ end
633
+ end
634
+
635
+ context 'when passing a string criterion to a negated query' do
636
+ it 'raises InvalidQuery' do
637
+ expect do
638
+ query.not.where('this.name == "admin"')
639
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /\$where/)
640
+ end
641
+ end
642
+
643
+ %w[$and $or $nor $not $text $comment $expr $jsonSchema $alwaysFalse $alwaysTrue].each do |op|
644
+ context "when passing #{op} (allowlisted)" do
645
+ it 'does not raise' do
646
+ value = case op
647
+ when '$and', '$or', '$nor', '$not' then [ { 'x' => 1 } ]
648
+ when '$text' then { '$search' => 'hi' }
649
+ when '$expr' then { '$gt' => [ '$a', 1 ] }
650
+ when '$jsonSchema' then { 'required' => [ 'x' ] }
651
+ else true
652
+ end
653
+ expect { query.where(op => value) }.not_to raise_error
654
+ end
655
+ end
656
+ end
657
+ end
658
+ end
659
+
660
+ describe 'nested operator injection guard' do
661
+ js = 'this.name == "admin"'
662
+
663
+ function_expr = {
664
+ '$function' => { 'body' => 'function() { return true; }', 'args' => [], 'lang' => 'js' }
665
+ }.freeze
666
+
667
+ accumulator_expr = {
668
+ '$accumulator' => {
669
+ 'init' => 'function() { return 0; }',
670
+ 'accumulate' => 'function() { return 0; }',
671
+ 'accumulateArgs' => [],
672
+ 'merge' => 'function() { return 0; }',
673
+ 'lang' => 'js'
674
+ }
675
+ }.freeze
676
+
677
+ # Every path into the selector that does not route through #expr_query,
678
+ # plus the nested forms that a top-level key check cannot see.
679
+ unsafe_queries = {
680
+ 'and with a $where key' => ->(query) { query.and('$where' => js) },
681
+ 'or with a $where key' => ->(query) { query.or('$where' => js) },
682
+ 'nor with a $where key' => ->(query) { query.nor('$where' => js) },
683
+ 'not with a $where key' => ->(query) { query.not('$where' => js) },
684
+ 'any_of with a $where key' => ->(query) { query.any_of('$where' => js) },
685
+ 'none_of with a $where key' => ->(query) { query.none_of('$where' => js) },
686
+ 'elem_match with a nested $where' => ->(query) { query.elem_match(a: { '$where' => js }) },
687
+ 'where with $where inside $or' => ->(query) { query.where('$or' => [ { '$where' => js } ]) },
688
+ 'where with $function inside $expr' => ->(query) { query.where('$expr' => function_expr) },
689
+ 'where with $accumulator inside $expr' => ->(query) { query.where('$expr' => accumulator_expr) },
690
+ 'where with $where three levels deep' => lambda { |query|
691
+ query.where('$and' => [ { '$or' => [ { '$where' => js } ] } ])
692
+ },
693
+ 'where with a symbol $where key inside $or' => ->(query) { query.where('$or' => [ { :$where => js } ]) }
694
+ }.freeze
695
+
696
+ context 'when allow_unsafe_query_operators is false' do
697
+ config_override :allow_unsafe_query_operators, false
698
+
699
+ unsafe_queries.each do |description, builder|
700
+ context "when querying with #{description}" do
701
+ it 'raises InvalidQuery' do
702
+ expect do
703
+ builder.call(query)
704
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /\$where|\$function|\$accumulator/)
705
+ end
706
+ end
707
+ end
708
+
709
+ it 'includes the config opt-in in the message' do
710
+ expect do
711
+ query.or('$where' => js)
712
+ end.to raise_error(Mongoid::Errors::InvalidQuery, /allow_unsafe_query_operators/)
713
+ end
714
+
715
+ context 'when the nested expression is safe' do
716
+ it 'permits $or with field expressions' do
717
+ expect do
718
+ query.where('$or' => [ { 'a' => 1 }, { 'b' => { '$gt' => 2 } } ])
719
+ end.not_to raise_error
720
+ end
721
+
722
+ it 'permits $expr with aggregation operators' do
723
+ expect do
724
+ query.where('$expr' => { '$gt' => [ '$a', '$b' ] })
725
+ end.not_to raise_error
726
+ end
727
+
728
+ it 'permits a field whose name resembles a javascript operator' do
729
+ expect do
730
+ query.where('where' => js)
731
+ end.not_to raise_error
732
+ end
733
+
734
+ it 'permits a value that resembles a javascript operator' do
735
+ expect do
736
+ query.where('name' => '$where')
737
+ end.not_to raise_error
738
+ end
739
+ end
740
+ end
741
+
742
+ context 'when allow_unsafe_query_operators is true' do
743
+ config_override :allow_unsafe_query_operators, true
744
+
745
+ unsafe_queries.each do |description, builder|
746
+ context "when querying with #{description}" do
747
+ it 'does not raise' do
748
+ expect { builder.call(query) }.not_to raise_error
749
+ end
750
+ end
751
+ end
752
+ end
753
+ end
590
754
  end