mongoid 7.4.3 → 8.0.7

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 (383) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/Rakefile +25 -0
  5. data/lib/config/locales/en.yml +52 -28
  6. data/lib/mongoid/association/accessors.rb +38 -9
  7. data/lib/mongoid/association/bindable.rb +50 -2
  8. data/lib/mongoid/association/builders.rb +4 -2
  9. data/lib/mongoid/association/constrainable.rb +0 -1
  10. data/lib/mongoid/association/eager_loadable.rb +29 -7
  11. data/lib/mongoid/association/embedded/batchable.rb +33 -10
  12. data/lib/mongoid/association/embedded/cyclic.rb +1 -1
  13. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  14. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -2
  15. data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
  16. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  17. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  18. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +65 -41
  19. data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
  20. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  21. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +23 -4
  22. data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
  23. data/lib/mongoid/association/macros.rb +28 -1
  24. data/lib/mongoid/association/many.rb +11 -7
  25. data/lib/mongoid/association/nested/many.rb +5 -4
  26. data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
  27. data/lib/mongoid/association/nested/one.rb +5 -5
  28. data/lib/mongoid/association/one.rb +2 -2
  29. data/lib/mongoid/association/options.rb +9 -9
  30. data/lib/mongoid/association/proxy.rb +14 -3
  31. data/lib/mongoid/association/referenced/auto_save.rb +4 -3
  32. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  33. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  34. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
  35. data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
  36. data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
  37. data/lib/mongoid/association/referenced/eager.rb +2 -2
  38. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +70 -13
  39. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
  40. data/lib/mongoid/association/referenced/has_many/enumerable.rb +20 -24
  41. data/lib/mongoid/association/referenced/has_many/proxy.rb +26 -16
  42. data/lib/mongoid/association/referenced/has_many.rb +3 -3
  43. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  44. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
  45. data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
  46. data/lib/mongoid/association/referenced/has_one.rb +3 -3
  47. data/lib/mongoid/association/referenced/syncable.rb +4 -4
  48. data/lib/mongoid/association/reflections.rb +2 -2
  49. data/lib/mongoid/association/relatable.rb +44 -10
  50. data/lib/mongoid/association.rb +5 -5
  51. data/lib/mongoid/atomic/modifiers.rb +2 -2
  52. data/lib/mongoid/atomic.rb +7 -0
  53. data/lib/mongoid/attributes/dynamic.rb +3 -3
  54. data/lib/mongoid/attributes/nested.rb +5 -5
  55. data/lib/mongoid/attributes/processing.rb +37 -6
  56. data/lib/mongoid/attributes/projector.rb +1 -1
  57. data/lib/mongoid/attributes/readonly.rb +2 -2
  58. data/lib/mongoid/attributes.rb +43 -40
  59. data/lib/mongoid/cacheable.rb +2 -2
  60. data/lib/mongoid/changeable.rb +43 -10
  61. data/lib/mongoid/clients/options.rb +5 -1
  62. data/lib/mongoid/clients/sessions.rb +2 -14
  63. data/lib/mongoid/clients/validators/storage.rb +3 -3
  64. data/lib/mongoid/config/options.rb +3 -0
  65. data/lib/mongoid/config/validators/client.rb +6 -6
  66. data/lib/mongoid/config.rb +62 -17
  67. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  68. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  69. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  70. data/lib/mongoid/contextual/atomic.rb +1 -1
  71. data/lib/mongoid/contextual/geo_near.rb +7 -7
  72. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  73. data/lib/mongoid/contextual/memory.rb +180 -21
  74. data/lib/mongoid/contextual/mongo.rb +260 -217
  75. data/lib/mongoid/contextual/none.rb +67 -5
  76. data/lib/mongoid/contextual/queryable.rb +1 -1
  77. data/lib/mongoid/contextual.rb +2 -2
  78. data/lib/mongoid/copyable.rb +32 -8
  79. data/lib/mongoid/criteria/findable.rb +7 -4
  80. data/lib/mongoid/criteria/includable.rb +24 -20
  81. data/lib/mongoid/criteria/marshalable.rb +10 -2
  82. data/lib/mongoid/criteria/permission.rb +1 -1
  83. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  84. data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -14
  85. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  86. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  87. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  88. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  89. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -15
  90. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -9
  91. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  92. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  93. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  94. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  95. data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -14
  96. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -12
  97. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  98. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  99. data/lib/mongoid/criteria/queryable/key.rb +3 -3
  100. data/lib/mongoid/criteria/queryable/mergeable.rb +21 -0
  101. data/lib/mongoid/criteria/queryable/optional.rb +5 -11
  102. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  103. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  104. data/lib/mongoid/criteria/queryable/selectable.rb +31 -37
  105. data/lib/mongoid/criteria/queryable/selector.rb +93 -8
  106. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  107. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  108. data/lib/mongoid/criteria/queryable.rb +12 -7
  109. data/lib/mongoid/criteria/scopable.rb +2 -2
  110. data/lib/mongoid/criteria/translator.rb +45 -0
  111. data/lib/mongoid/criteria.rb +16 -35
  112. data/lib/mongoid/deprecable.rb +37 -0
  113. data/lib/mongoid/deprecation.rb +25 -0
  114. data/lib/mongoid/document.rb +135 -34
  115. data/lib/mongoid/equality.rb +8 -8
  116. data/lib/mongoid/errors/document_not_found.rb +33 -12
  117. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  118. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  119. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  120. data/lib/mongoid/errors/invalid_field.rb +6 -2
  121. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  122. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  123. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  124. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  125. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  126. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  127. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  128. data/lib/mongoid/errors/no_client_database.rb +1 -1
  129. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  130. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  131. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  132. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  133. data/lib/mongoid/errors.rb +2 -2
  134. data/lib/mongoid/extensions/array.rb +9 -7
  135. data/lib/mongoid/extensions/big_decimal.rb +33 -10
  136. data/lib/mongoid/extensions/binary.rb +42 -0
  137. data/lib/mongoid/extensions/boolean.rb +8 -2
  138. data/lib/mongoid/extensions/date.rb +26 -20
  139. data/lib/mongoid/extensions/date_time.rb +1 -1
  140. data/lib/mongoid/extensions/false_class.rb +1 -1
  141. data/lib/mongoid/extensions/float.rb +7 -4
  142. data/lib/mongoid/extensions/hash.rb +37 -8
  143. data/lib/mongoid/extensions/integer.rb +7 -4
  144. data/lib/mongoid/extensions/module.rb +1 -1
  145. data/lib/mongoid/extensions/object.rb +8 -6
  146. data/lib/mongoid/extensions/range.rb +41 -10
  147. data/lib/mongoid/extensions/regexp.rb +11 -4
  148. data/lib/mongoid/extensions/set.rb +11 -4
  149. data/lib/mongoid/extensions/string.rb +11 -22
  150. data/lib/mongoid/extensions/symbol.rb +4 -15
  151. data/lib/mongoid/extensions/time.rb +27 -16
  152. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  153. data/lib/mongoid/extensions/true_class.rb +1 -1
  154. data/lib/mongoid/extensions.rb +1 -0
  155. data/lib/mongoid/factory.rb +55 -7
  156. data/lib/mongoid/fields/foreign_key.rb +11 -4
  157. data/lib/mongoid/fields/localized.rb +9 -4
  158. data/lib/mongoid/fields/standard.rb +7 -7
  159. data/lib/mongoid/fields/validators/macro.rb +3 -9
  160. data/lib/mongoid/fields.rb +233 -40
  161. data/lib/mongoid/findable.rb +34 -13
  162. data/lib/mongoid/indexable/specification.rb +2 -2
  163. data/lib/mongoid/indexable/validators/options.rb +6 -2
  164. data/lib/mongoid/interceptable.rb +185 -16
  165. data/lib/mongoid/matchable.rb +1 -1
  166. data/lib/mongoid/matcher.rb +33 -13
  167. data/lib/mongoid/persistable/creatable.rb +18 -9
  168. data/lib/mongoid/persistable/deletable.rb +1 -1
  169. data/lib/mongoid/persistable/destroyable.rb +1 -1
  170. data/lib/mongoid/persistable/savable.rb +2 -2
  171. data/lib/mongoid/persistable/unsettable.rb +1 -1
  172. data/lib/mongoid/persistable/updatable.rb +19 -12
  173. data/lib/mongoid/persistable/upsertable.rb +1 -1
  174. data/lib/mongoid/persistable.rb +3 -3
  175. data/lib/mongoid/persistence_context.rb +63 -10
  176. data/lib/mongoid/query_cache.rb +8 -260
  177. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  178. data/lib/mongoid/reloadable.rb +10 -8
  179. data/lib/mongoid/scopable.rb +26 -22
  180. data/lib/mongoid/selectable.rb +1 -2
  181. data/lib/mongoid/serializable.rb +10 -6
  182. data/lib/mongoid/shardable.rb +35 -11
  183. data/lib/mongoid/stateful.rb +35 -9
  184. data/lib/mongoid/tasks/database.rb +0 -2
  185. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  186. data/lib/mongoid/threaded.rb +42 -12
  187. data/lib/mongoid/timestamps/created.rb +1 -1
  188. data/lib/mongoid/timestamps/updated.rb +2 -2
  189. data/lib/mongoid/touchable.rb +2 -3
  190. data/lib/mongoid/traversable.rb +5 -4
  191. data/lib/mongoid/validatable/localizable.rb +1 -1
  192. data/lib/mongoid/validatable/macros.rb +0 -2
  193. data/lib/mongoid/validatable/presence.rb +2 -2
  194. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  195. data/lib/mongoid/validatable.rb +6 -6
  196. data/lib/mongoid/version.rb +1 -1
  197. data/lib/mongoid/warnings.rb +28 -0
  198. data/lib/mongoid.rb +2 -0
  199. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -3
  200. data/spec/config/mongoid.yml +16 -0
  201. data/spec/integration/app_spec.rb +8 -12
  202. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  203. data/spec/integration/associations/embedded_spec.rb +15 -0
  204. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  205. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  206. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  207. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  208. data/spec/integration/associations/has_one_spec.rb +97 -1
  209. data/spec/integration/associations/scope_option_spec.rb +1 -1
  210. data/spec/integration/callbacks_models.rb +95 -1
  211. data/spec/integration/callbacks_spec.rb +246 -4
  212. data/spec/integration/criteria/range_spec.rb +95 -1
  213. data/spec/integration/discriminator_key_spec.rb +115 -76
  214. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  215. data/spec/integration/i18n_fallbacks_spec.rb +1 -17
  216. data/spec/integration/matcher_examples_spec.rb +20 -13
  217. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  218. data/spec/integration/matcher_operator_spec.rb +3 -5
  219. data/spec/integration/persistence/range_field_spec.rb +350 -0
  220. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  221. data/spec/mongoid/association/depending_spec.rb +9 -9
  222. data/spec/mongoid/association/eager_spec.rb +2 -1
  223. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  224. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  225. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  226. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  227. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +235 -40
  228. data/spec/mongoid/association/embedded/embeds_many_models.rb +36 -0
  229. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  230. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  231. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  232. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  233. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  234. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  235. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  236. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  237. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  238. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  239. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +202 -201
  240. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  241. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  242. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  243. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +8 -8
  244. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +160 -119
  245. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  246. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  247. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  248. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  249. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  250. data/spec/mongoid/association/syncable_spec.rb +14 -0
  251. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  252. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  253. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  254. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  255. data/spec/mongoid/attributes_spec.rb +551 -27
  256. data/spec/mongoid/cacheable_spec.rb +3 -3
  257. data/spec/mongoid/changeable_spec.rb +130 -13
  258. data/spec/mongoid/clients/factory_spec.rb +23 -30
  259. data/spec/mongoid/clients/options_spec.rb +1 -0
  260. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  261. data/spec/mongoid/clients_spec.rb +57 -2
  262. data/spec/mongoid/config_spec.rb +78 -18
  263. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  264. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  265. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  266. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  267. data/spec/mongoid/contextual/memory_spec.rb +1336 -69
  268. data/spec/mongoid/contextual/mongo_spec.rb +1253 -247
  269. data/spec/mongoid/contextual/none_spec.rb +38 -0
  270. data/spec/mongoid/copyable_spec.rb +451 -1
  271. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  272. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  273. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  274. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  275. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  276. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  277. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  278. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  279. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  280. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  281. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +0 -59
  282. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  283. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  284. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  285. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -484
  286. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  287. data/spec/mongoid/criteria/queryable/selectable_spec.rb +289 -124
  288. data/spec/mongoid/criteria/queryable/selector_spec.rb +89 -4
  289. data/spec/mongoid/criteria/queryable/storable_spec.rb +72 -0
  290. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  291. data/spec/mongoid/criteria_projection_spec.rb +0 -1
  292. data/spec/mongoid/criteria_spec.rb +475 -1199
  293. data/spec/mongoid/document_fields_spec.rb +173 -24
  294. data/spec/mongoid/document_spec.rb +32 -41
  295. data/spec/mongoid/errors/document_not_found_spec.rb +76 -0
  296. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  297. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  298. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  299. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  300. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  301. data/spec/mongoid/extensions/array_spec.rb +16 -2
  302. data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
  303. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  304. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  305. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  306. data/spec/mongoid/extensions/date_spec.rb +71 -1
  307. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  308. data/spec/mongoid/extensions/float_spec.rb +53 -74
  309. data/spec/mongoid/extensions/hash_spec.rb +33 -3
  310. data/spec/mongoid/extensions/integer_spec.rb +50 -64
  311. data/spec/mongoid/extensions/range_spec.rb +255 -54
  312. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  313. data/spec/mongoid/extensions/set_spec.rb +106 -0
  314. data/spec/mongoid/extensions/string_spec.rb +53 -25
  315. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  316. data/spec/mongoid/extensions/time_spec.rb +634 -66
  317. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  318. data/spec/mongoid/factory_spec.rb +61 -1
  319. data/spec/mongoid/fields/localized_spec.rb +37 -12
  320. data/spec/mongoid/fields_spec.rb +364 -50
  321. data/spec/mongoid/findable_spec.rb +80 -15
  322. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  323. data/spec/mongoid/indexable_spec.rb +39 -20
  324. data/spec/mongoid/interceptable_spec.rb +807 -27
  325. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  326. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  327. data/spec/mongoid/mongoizable_spec.rb +285 -0
  328. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  329. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  330. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  331. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  332. data/spec/mongoid/persistence_context_spec.rb +50 -1
  333. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  334. data/spec/mongoid/query_cache_spec.rb +0 -154
  335. data/spec/mongoid/reloadable_spec.rb +59 -2
  336. data/spec/mongoid/scopable_spec.rb +54 -16
  337. data/spec/mongoid/shardable_models.rb +14 -0
  338. data/spec/mongoid/shardable_spec.rb +157 -51
  339. data/spec/mongoid/stateful_spec.rb +28 -0
  340. data/spec/mongoid/timestamps_spec.rb +390 -0
  341. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  342. data/spec/mongoid/touchable_spec.rb +116 -0
  343. data/spec/mongoid/touchable_spec_models.rb +12 -8
  344. data/spec/mongoid/traversable_spec.rb +4 -11
  345. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  346. data/spec/mongoid/validatable/uniqueness_spec.rb +59 -31
  347. data/spec/mongoid/warnings_spec.rb +35 -0
  348. data/spec/mongoid_spec.rb +1 -1
  349. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  350. data/spec/rails/mongoid_spec.rb +4 -16
  351. data/spec/shared/lib/mrss/docker_runner.rb +7 -0
  352. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  353. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  354. data/spec/shared/lib/mrss/utils.rb +28 -6
  355. data/spec/shared/share/Dockerfile.erb +36 -40
  356. data/spec/shared/shlib/server.sh +32 -8
  357. data/spec/shared/shlib/set_env.sh +4 -4
  358. data/spec/support/constraints.rb +24 -0
  359. data/spec/support/macros.rb +46 -0
  360. data/spec/support/models/augmentation.rb +12 -0
  361. data/spec/support/models/band.rb +3 -0
  362. data/spec/support/models/catalog.rb +24 -0
  363. data/spec/support/models/circus.rb +3 -0
  364. data/spec/support/models/code.rb +2 -0
  365. data/spec/support/models/fanatic.rb +8 -0
  366. data/spec/support/models/implant.rb +9 -0
  367. data/spec/support/models/label.rb +2 -0
  368. data/spec/support/models/passport.rb +9 -0
  369. data/spec/support/models/person.rb +2 -0
  370. data/spec/support/models/player.rb +2 -0
  371. data/spec/support/models/powerup.rb +12 -0
  372. data/spec/support/models/purse.rb +9 -0
  373. data/spec/support/models/registry.rb +1 -0
  374. data/spec/support/models/school.rb +14 -0
  375. data/spec/support/models/shield.rb +18 -0
  376. data/spec/support/models/student.rb +14 -0
  377. data/spec/support/models/weapon.rb +12 -0
  378. data.tar.gz.sig +4 -1
  379. metadata +682 -635
  380. metadata.gz.sig +0 -0
  381. data/lib/mongoid/errors/eager_load.rb +0 -23
  382. data/lib/mongoid/errors/invalid_value.rb +0 -17
  383. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
@@ -33,9 +33,10 @@ module Mongoid
33
33
  include Optional
34
34
 
35
35
  # @attribute [r] aliases The aliases.
36
- # @attribute [r] driver The Mongo driver being used.
36
+ attr_reader :aliases
37
+
37
38
  # @attribute [r] serializers The serializers.
38
- attr_reader :aliases, :driver, :serializers
39
+ attr_reader :serializers
39
40
 
40
41
  # Is this queryable equal to another object? Is true if the selector and
41
42
  # options are equal.
@@ -45,7 +46,7 @@ module Mongoid
45
46
  #
46
47
  # @param [ Object ] other The object to compare against.
47
48
  #
48
- # @return [ true, false ] If the objects are equal.
49
+ # @return [ true | false ] If the objects are equal.
49
50
  def ==(other)
50
51
  return false unless other.is_a?(Queryable)
51
52
  selector == other.selector && options == other.options
@@ -59,11 +60,15 @@ module Mongoid
59
60
  #
60
61
  # @param [ Hash ] aliases The optional field aliases.
61
62
  # @param [ Hash ] serializers The optional field serializers.
63
+ # @param [ Hash ] associations The optional associations.
64
+ # @param [ Hash ] aliased_associations The optional aliased associations.
62
65
  # @param [ Symbol ] driver The driver being used.
63
- def initialize(aliases = {}, serializers = {}, driver = :mongo)
64
- @aliases, @driver, @serializers = aliases, driver.to_sym, serializers
65
- @options = Options.new(aliases, serializers)
66
- @selector = Selector.new(aliases, serializers)
66
+ #
67
+ # @api private
68
+ def initialize(aliases = {}, serializers = {}, associations = {}, aliased_associations = {})
69
+ @aliases, @serializers = aliases, serializers
70
+ @options = Options.new(aliases, serializers, associations, aliased_associations)
71
+ @selector = Selector.new(aliases, serializers, associations, aliased_associations)
67
72
  @pipeline = Pipeline.new(aliases)
68
73
  @aggregating = nil
69
74
  yield(self) if block_given?
@@ -83,7 +83,7 @@ module Mongoid
83
83
  # @example Is the default scope applied?
84
84
  # criteria.scoped?
85
85
  #
86
- # @return [ true, false ] If the default scope is applied.
86
+ # @return [ true | false ] If the default scope is applied.
87
87
  def scoped?
88
88
  !!(defined?(@scoped) ? @scoped : nil)
89
89
  end
@@ -108,7 +108,7 @@ module Mongoid
108
108
  # @example Is the criteria unscoped?
109
109
  # criteria.unscoped?
110
110
  #
111
- # @return [ true, false ] If the criteria is force unscoped.
111
+ # @return [ true | false ] If the criteria is force unscoped.
112
112
  def unscoped?
113
113
  !!(defined?(@unscoped) ? @unscoped : nil)
114
114
  end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ class Criteria
5
+
6
+ # This is a helper module for translating atomic and composite
7
+ # Ruby values into corresponding query and option components.
8
+ # Originally implemented as patches to core classes, that approach
9
+ # has generally fallen into disfavor, as it bleeds too much into
10
+ # the public namespace.
11
+ #
12
+ # @api private
13
+ module Translator
14
+ extend self
15
+
16
+ # Converts the given value to a direction specification for use in
17
+ # sorting.
18
+ #
19
+ # @example Convert the value to a direction.
20
+ # Translator.to_direction(:desc)
21
+ # Translator.to_direction("1")
22
+ # Translator.to_direction(-1)
23
+ # Translator.to_direction(score: { "$meta": "textScore" })
24
+ #
25
+ # @param [ Hash | Numeric | String | Symbol ] value The value to convert.
26
+ #
27
+ # @return [ Hash | Numeric ] The direction.
28
+ def to_direction(value)
29
+ case value
30
+ when Hash then
31
+ value
32
+ when Numeric then
33
+ value
34
+ when String then
35
+ value =~ /desc/i ? -1 : 1
36
+ when Symbol then
37
+ to_direction(value.to_s)
38
+ else
39
+ raise ArgumentError, "cannot translate #{value.inspect} (#{value.class}) to a direction specification"
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -8,6 +8,7 @@ require "mongoid/criteria/modifiable"
8
8
  require "mongoid/criteria/queryable"
9
9
  require "mongoid/criteria/scopable"
10
10
  require "mongoid/criteria/options"
11
+ require "mongoid/criteria/translator"
11
12
 
12
13
  module Mongoid
13
14
 
@@ -52,7 +53,7 @@ module Mongoid
52
53
  #
53
54
  # @param [ Object ] other The other +Enumerable+ or +Criteria+ to compare to.
54
55
  #
55
- # @return [ true, false ] If the objects are equal.
56
+ # @return [ true | false ] If the objects are equal.
56
57
  def ==(other)
57
58
  return super if other.respond_to?(:selector)
58
59
  entries == other
@@ -73,6 +74,9 @@ module Mongoid
73
74
  # treated by Mongoid - the decision between delegating to +Findable+ vs
74
75
  # +Enumerable+ is made solely based on whether +find+ is passed a block.
75
76
  #
77
+ # @note Each argument can be an individual id, an array of ids or
78
+ # a nested array. Each array will be flattened.
79
+ #
76
80
  # @example Finds a document by its _id, invokes Findable#find.
77
81
  # critera.find("1234")
78
82
  #
@@ -85,6 +89,9 @@ module Mongoid
85
89
  # @example Tries to find a document whose _id is the stringification of the provided Proc, typically failing.
86
90
  # enumerator = criteria.find(-> { "Default Band" })
87
91
  #
92
+ # @param [ Object | Array<Object> ] *args The ids.
93
+ # @param [ Proc ] block Optional block to pass.
94
+ #
88
95
  # @return [ Document | Array<Document> | nil ] A document or matching documents.
89
96
  #
90
97
  # @raise Errors::DocumentNotFound If the parameters were _id values and
@@ -112,31 +119,6 @@ module Mongoid
112
119
  entries.as_json(options)
113
120
  end
114
121
 
115
- # Tells the criteria that the cursor that gets returned needs to be
116
- # cached. This is so multiple iterations don't hit the database multiple
117
- # times, however this is not advisable when working with large data sets
118
- # as the entire results will get stored in memory.
119
- #
120
- # @example Flag the criteria as cached.
121
- # criteria.cache
122
- #
123
- # @return [ Criteria ] The cloned criteria.
124
- def cache
125
- crit = clone
126
- crit.options.merge!(cache: true)
127
- crit
128
- end
129
-
130
- # Will return true if the cache option has been set.
131
- #
132
- # @example Is the criteria cached?
133
- # criteria.cached?
134
- #
135
- # @return [ true, false ] If the criteria is flagged as cached.
136
- def cached?
137
- options[:cache] == true
138
- end
139
-
140
122
  # Get the documents from the embedded criteria.
141
123
  #
142
124
  # @example Get the documents.
@@ -163,7 +145,7 @@ module Mongoid
163
145
  # @example Is the criteria for embedded documents?
164
146
  # criteria.embedded?
165
147
  #
166
- # @return [ true, false ] If the criteria is embedded.
148
+ # @return [ true | false ] If the criteria is embedded.
167
149
  def embedded?
168
150
  !!@embedded
169
151
  end
@@ -230,7 +212,7 @@ module Mongoid
230
212
  @klass = klass
231
213
  @embedded = nil
232
214
  @none = nil
233
- klass ? super(klass.aliased_fields, klass.fields) : super({}, {})
215
+ klass ? super(klass.aliased_fields, klass.fields, klass.relations, klass.aliased_associations) : super({}, {}, {}, {})
234
216
  end
235
217
 
236
218
  # Merges another object with this +Criteria+ and returns a new criteria.
@@ -293,7 +275,7 @@ module Mongoid
293
275
  # @example Is the criteria a none criteria?
294
276
  # criteria.empty_and_chainable?
295
277
  #
296
- # @return [ true, false ] If the criteria is a none.
278
+ # @return [ true | false ] If the criteria is a none.
297
279
  def empty_and_chainable?
298
280
  !!@none
299
281
  end
@@ -351,9 +333,9 @@ module Mongoid
351
333
  # crtiteria.respond_to?(:each)
352
334
  #
353
335
  # @param [ Symbol ] name The name of the class method on the +Document+.
354
- # @param [ true, false ] include_private Whether to include privates.
336
+ # @param [ true | false ] include_private Whether to include privates.
355
337
  #
356
- # @return [ true, false ] If the criteria responds to the method.
338
+ # @return [ true | false ] If the criteria responds to the method.
357
339
  def respond_to?(name, include_private = false)
358
340
  super || klass.respond_to?(name) || CHECK.respond_to?(name, include_private)
359
341
  end
@@ -404,7 +386,7 @@ module Mongoid
404
386
  # @example Add a javascript selection.
405
387
  # criteria.where("this.name == 'syd'")
406
388
  #
407
- # @param [ String, Hash ] expression The javascript or standard selection.
389
+ # @param [ String | Hash ] expression The javascript or standard selection.
408
390
  #
409
391
  # @raise [ UnsupportedJavascript ] If provided a string and the criteria
410
392
  # is embedded.
@@ -430,7 +412,6 @@ module Mongoid
430
412
  super
431
413
  end
432
414
 
433
-
434
415
  # Get a version of this criteria without the options.
435
416
  #
436
417
  # @example Get the criteria without options.
@@ -536,7 +517,7 @@ module Mongoid
536
517
  # @example Add the type selection.
537
518
  # criteria.merge_type_selection
538
519
  #
539
- # @return [ true, false ] If type selection was added.
520
+ # @return [ true | false ] If type selection was added.
540
521
  def merge_type_selection
541
522
  selector.merge!(type_selection) if type_selectable?
542
523
  end
@@ -548,7 +529,7 @@ module Mongoid
548
529
  # @example If the criteria type selectable?
549
530
  # criteria.type_selectable?
550
531
  #
551
- # @return [ true, false ] If type selection should be added.
532
+ # @return [ true | false ] If type selection should be added.
552
533
  def type_selectable?
553
534
  klass.hereditary? &&
554
535
  !selector.keys.include?(self.discriminator_key) &&
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "mongoid/deprecation"
4
+
5
+ module Mongoid
6
+
7
+ # Adds ability to declare Mongoid-specific deprecations.
8
+ #
9
+ # @api private
10
+ module Deprecable
11
+
12
+ # Declares method(s) as deprecated.
13
+ #
14
+ # @example Deprecate a method.
15
+ # Mongoid.deprecate(Cat, :meow); Cat.new.meow
16
+ # #=> Mongoid.logger.warn("meow is deprecated and will be removed from Mongoid 8.0")
17
+ #
18
+ # @example Deprecate a method and declare the replacement method.
19
+ # Mongoid.deprecate(Cat, meow: :speak); Cat.new.meow
20
+ # #=> Mongoid.logger.warn("meow is deprecated and will be removed from Mongoid 8.0 (use speak instead)")
21
+ #
22
+ # @example Deprecate a method and give replacement instructions.
23
+ # Mongoid.deprecate(Cat, meow: 'eat :catnip instead'); Cat.new.meow
24
+ # #=> Mongoid.logger.warn("meow is deprecated and will be removed from Mongoid 8.0 (eat :catnip instead)")
25
+ #
26
+ # @param [ Module ] target_module The parent which contains the method.
27
+ # @param [ [ Symbol | Hash<Symbol, [ Symbol | String ]> ]... ] *method_descriptors
28
+ # The methods to deprecate, with optional replacement instructions.
29
+ def deprecate(target_module, *method_descriptors)
30
+ @_deprecator ||= Mongoid::Deprecation.new
31
+ @_deprecator.deprecate_methods(target_module, *method_descriptors)
32
+ end
33
+ end
34
+ end
35
+
36
+ # Ensure Mongoid.deprecate can be used during initialization
37
+ Mongoid.extend(Mongoid::Deprecable)
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+
5
+ # Utility class for logging deprecation warnings.
6
+ class Deprecation < ::ActiveSupport::Deprecation
7
+
8
+ @gem_name = 'Mongoid'
9
+
10
+ # Per change policy, deprecations will be removed in the next major version.
11
+ @deprecation_horizon = "#{Mongoid::VERSION.split('.').first.to_i + 1}.0".freeze
12
+
13
+ # Overrides default ActiveSupport::Deprecation behavior
14
+ # to use Mongoid's logger.
15
+ #
16
+ # @return Array<Proc> The deprecation behavior.
17
+ def behavior
18
+ @behavior ||= Array(->(*args) {
19
+ logger = Mongoid.logger
20
+ logger.warn(args[0])
21
+ logger.debug(args[1].join("\n ")) if debug
22
+ })
23
+ end
24
+ end
25
+ end
@@ -56,7 +56,7 @@ module Mongoid
56
56
  # @example Check if frozen
57
57
  # document.frozen?
58
58
  #
59
- # @return [ true, false ] True if frozen, else false.
59
+ # @return [ true | false ] True if frozen, else false.
60
60
  def frozen?
61
61
  attributes.frozen?
62
62
  end
@@ -100,21 +100,8 @@ module Mongoid
100
100
  # @param [ Hash ] attrs The attributes to set up the document with.
101
101
  #
102
102
  # @return [ Document ] A new document.
103
- def initialize(attrs = nil)
104
- @__parent = nil
105
- _building do
106
- @new_record = true
107
- @attributes ||= {}
108
- apply_pre_processed_defaults
109
- apply_default_scoping
110
- process_attributes(attrs) do
111
- yield(self) if block_given?
112
- end
113
- apply_post_processed_defaults
114
- # @todo: #2586: Need to have access to parent document in these
115
- # callbacks.
116
- run_callbacks(:initialize) unless _initialize_callbacks.empty?
117
- end
103
+ def initialize(attrs = nil, &block)
104
+ construct_document(attrs, &block)
118
105
  end
119
106
 
120
107
  # Return the model name of the document.
@@ -137,16 +124,6 @@ module Mongoid
137
124
  (persisted? || destroyed?) ? [ _id.to_s ] : nil
138
125
  end
139
126
 
140
- # Return an array with this +Document+ only in it.
141
- #
142
- # @example Return the document in an array.
143
- # document.to_a
144
- #
145
- # @return [ Array<Document> ] An array with the document as its only item.
146
- def to_a
147
- [ self ]
148
- end
149
-
150
127
  # Return a hash of the entire document hierarchy from this document and
151
128
  # below. Used when the attributes are needed for everything and not just
152
129
  # the current document.
@@ -173,14 +150,14 @@ module Mongoid
173
150
  #
174
151
  # @param [ Hash ] options The options.
175
152
  #
176
- # @option options [ true, false ] :compact (Deprecated) Whether to include fields
153
+ # @option options [ true | false ] :compact (Deprecated) Whether to include fields
177
154
  # with nil values in the json document.
178
155
  #
179
156
  # @return [ Hash ] The document as json.
180
157
  def as_json(options = nil)
181
158
  rv = super
182
159
  if options && options[:compact]
183
- Mongoid.logger.warn('#as_json :compact option is deprecated. Please call #compact on the returned Hash object instead.')
160
+ Mongoid::Warnings.warn_as_json_compact_deprecated
184
161
  rv = rv.compact
185
162
  end
186
163
  rv
@@ -228,6 +205,47 @@ module Mongoid
228
205
 
229
206
  private
230
207
 
208
+ # Does the construction of a document.
209
+ #
210
+ # @param [ Hash ] attrs The attributes to set up the document with.
211
+ # @param [ Hash ] options The options to use.
212
+ #
213
+ # @option options [ true | false ] :execute_callbacks Flag specifies
214
+ # whether callbacks should be run.
215
+ #
216
+ # @return [ Document ] A new document.
217
+ #
218
+ # @note A Ruby 2.x bug prevents the options hash from being keyword
219
+ # arguments. Once we drop support for Ruby 2.x, we can reimplement
220
+ # the options hash as keyword arguments.
221
+ # See https://bugs.ruby-lang.org/issues/15753
222
+ #
223
+ # @api private
224
+ def construct_document(attrs = nil, options = {})
225
+ execute_callbacks = options.fetch(:execute_callbacks, Threaded.execute_callbacks?)
226
+
227
+ @__parent = nil
228
+ _building do
229
+ @new_record = true
230
+ @attributes ||= {}
231
+ apply_pre_processed_defaults
232
+ apply_default_scoping
233
+ process_attributes(attrs) do
234
+ yield(self) if block_given?
235
+ end
236
+ @attributes_before_type_cast = @attributes.merge(attributes_before_type_cast)
237
+
238
+ if execute_callbacks
239
+ apply_post_processed_defaults
240
+ run_callbacks(:initialize) unless _initialize_callbacks.empty?
241
+ else
242
+ pending_callbacks << :apply_post_processed_defaults
243
+ pending_callbacks << :initialize
244
+ end
245
+ end
246
+ self
247
+ end
248
+
231
249
  # Returns the logger
232
250
  #
233
251
  # @return [ Logger ] The configured logger or a default Logger instance.
@@ -245,6 +263,14 @@ module Mongoid
245
263
  @model_cache_key ||= self.class.model_name.cache_key
246
264
  end
247
265
 
266
+ # Returns a hash of the attributes.
267
+ #
268
+ # Note this method modifies the attributes hash that already exists on the
269
+ # class and returns it. This means that the hash returned by this method
270
+ # refers to the same hash as calling #attributes on the instance. See
271
+ # MONGOID-4476 for an explanation on how this is used.
272
+ #
273
+ # @return [ Hash ] The attributes hash.
248
274
  def as_attributes
249
275
  return attributes if frozen?
250
276
  embedded_relations.each_pair do |name, meta|
@@ -264,6 +290,20 @@ module Mongoid
264
290
 
265
291
  module ClassMethods
266
292
 
293
+ # Indicate whether callbacks should be invoked by default or not,
294
+ # within the block. Callbacks may always be explicitly invoked by passing
295
+ # `execute_callbacks: true` where available.
296
+ #
297
+ # @params execute_callbacks [ true | false ] Whether callbacks should be
298
+ # suppressed or not.
299
+ def with_callbacks(execute_callbacks)
300
+ saved, Threaded.execute_callbacks =
301
+ Threaded.execute_callbacks?, execute_callbacks
302
+ yield
303
+ ensure
304
+ Threaded.execute_callbacks = saved
305
+ end
306
+
267
307
  # Instantiate a new object, only when loaded from the database or when
268
308
  # the attributes have already been typecast.
269
309
  #
@@ -273,20 +313,81 @@ module Mongoid
273
313
  # @param [ Hash ] attrs The hash of attributes to instantiate with.
274
314
  # @param [ Integer ] selected_fields The selected fields from the
275
315
  # criteria.
316
+ # @param [ true | false ] execute_callbacks Flag specifies whether callbacks
317
+ # should be run.
318
+ #
319
+ # @return [ Document ] A new document.
320
+ def instantiate(attrs = nil, selected_fields = nil, &block)
321
+ instantiate_document(attrs, selected_fields, &block)
322
+ end
323
+
324
+ # Instantiate the document.
325
+ #
326
+ # @param [ Hash ] attrs The hash of attributes to instantiate with.
327
+ # @param [ Integer ] selected_fields The selected fields from the
328
+ # criteria.
329
+ # @param [ Hash ] options The options to use.
330
+ #
331
+ # @option options [ true | false ] :execute_callbacks Flag specifies
332
+ # whether callbacks should be run.
276
333
  #
277
334
  # @return [ Document ] A new document.
278
- def instantiate(attrs = nil, selected_fields = nil)
279
- attributes = attrs || {}
335
+ #
336
+ # @note A Ruby 2.x bug prevents the options hash from being keyword
337
+ # arguments. Once we drop support for Ruby 2.x, we can reimplement
338
+ # the options hash as keyword arguments.
339
+ #
340
+ # @api private
341
+ def instantiate_document(attrs = nil, selected_fields = nil, options = {})
342
+ execute_callbacks = options.fetch(:execute_callbacks, Threaded.execute_callbacks?)
343
+ attributes = if Mongoid.legacy_attributes
344
+ attrs
345
+ else
346
+ attrs&.to_h
347
+ end || {}
348
+
280
349
  doc = allocate
281
350
  doc.__selected_fields = selected_fields
282
351
  doc.instance_variable_set(:@attributes, attributes)
283
- doc.apply_defaults
284
- yield(doc) if block_given?
285
- doc.run_callbacks(:find) unless doc._find_callbacks.empty?
286
- doc.run_callbacks(:initialize) unless doc._initialize_callbacks.empty?
352
+ # TODO: remove the to_h when the legacy_attributes flag is removed.
353
+ # The to_h ensures that we don't accidentally make attributes_before_type_cast
354
+ # a BSON::Document.
355
+ doc.instance_variable_set(:@attributes_before_type_cast, attributes&.to_h.dup)
356
+
357
+ if execute_callbacks
358
+ doc.apply_defaults
359
+ yield(doc) if block_given?
360
+ doc.run_callbacks(:find) unless doc._find_callbacks.empty?
361
+ doc.run_callbacks(:initialize) unless doc._initialize_callbacks.empty?
362
+ else
363
+ yield(doc) if block_given?
364
+ doc.pending_callbacks += [:apply_defaults, :find, :initialize]
365
+ end
366
+
287
367
  doc
288
368
  end
289
369
 
370
+ # Allocates and constructs a document.
371
+ #
372
+ # @param [ Hash ] attrs The attributes to set up the document with.
373
+ # @param [ Hash ] options The options to use.
374
+ #
375
+ # @option options [ true | false ] :execute_callbacks Flag specifies
376
+ # whether callbacks should be run.
377
+ #
378
+ # @note A Ruby 2.x bug prevents the options hash from being keyword
379
+ # arguments. Once we drop support for Ruby 2.x, we can reimplement
380
+ # the options hash as keyword arguments.
381
+ # See https://bugs.ruby-lang.org/issues/15753
382
+ #
383
+ # @return [ Document ] A new document.
384
+ #
385
+ # @api private
386
+ def construct_document(attrs = nil, options = {})
387
+ execute_callbacks = options.fetch(:execute_callbacks, Threaded.execute_callbacks?)
388
+ with_callbacks(execute_callbacks) { new(attrs) }
389
+ end
390
+
290
391
  # Returns all types to query for when using this class as the base.
291
392
  #
292
393
  # @example Get the types.
@@ -26,9 +26,9 @@ module Mongoid
26
26
  # @example Compare for equality.
27
27
  # document == other
28
28
  #
29
- # @param [ Document, Object ] other The other object to compare with.
29
+ # @param [ Document | Object ] other The other object to compare with.
30
30
  #
31
- # @return [ true, false ] True if the ids are equal, false if not.
31
+ # @return [ true | false ] True if the ids are equal, false if not.
32
32
  def ==(other)
33
33
  self.class == other.class &&
34
34
  attributes["_id"] == other.attributes["_id"]
@@ -39,9 +39,9 @@ module Mongoid
39
39
  # @example Compare the classes.
40
40
  # document === other
41
41
  #
42
- # @param [ Document, Object ] other The other object to compare with.
42
+ # @param [ Document | Object ] other The other object to compare with.
43
43
  #
44
- # @return [ true, false ] True if the classes are equal, false if not.
44
+ # @return [ true | false ] True if the classes are equal, false if not.
45
45
  def ===(other)
46
46
  if Mongoid.legacy_triple_equals
47
47
  other.class == Class ? self.class === other : self == other
@@ -55,9 +55,9 @@ module Mongoid
55
55
  # @example Perform equality checking.
56
56
  # document.eql?(other)
57
57
  #
58
- # @param [ Document, Object ] other The object to check against.
58
+ # @param [ Document | Object ] other The object to check against.
59
59
  #
60
- # @return [ true, false ] True if equal, false if not.
60
+ # @return [ true | false ] True if equal, false if not.
61
61
  def eql?(other)
62
62
  self == (other)
63
63
  end
@@ -68,9 +68,9 @@ module Mongoid
68
68
  # @example Compare the classes.
69
69
  # document === other
70
70
  #
71
- # @param [ Document, Object ] other The other object to compare with.
71
+ # @param [ Document | Object ] other The other object to compare with.
72
72
  #
73
- # @return [ true, false ] True if the classes are equal, false if not.
73
+ # @return [ true | false ] True if the classes are equal, false if not.
74
74
  def ===(other)
75
75
  if Mongoid.legacy_triple_equals
76
76
  other.class == Class ? self <= other : other.is_a?(self)
@@ -19,23 +19,25 @@ module Mongoid
19
19
  # DocumentNotFound.new(Person, :ssn => "1234", :name => "Helen")
20
20
  #
21
21
  # @param [ Class ] klass The model class.
22
- # @param [ Hash, Array, Object ] params The attributes or ids.
23
- # @param [ Array ] unmatched The unmatched ids, if appropriate
22
+ # @param [ Hash | Array | Object ] params The attributes or ids.
23
+ # @param [ Array | Hash ] unmatched The unmatched ids, if appropriate. If
24
+ # there is a shard key this will be a hash.
24
25
  def initialize(klass, params, unmatched = nil)
25
26
  if !unmatched && !params.is_a?(Hash)
26
- unmatched = Array(params)
27
+ unmatched = Array(params) if params
27
28
  end
28
29
 
29
30
  @klass, @params = klass, params
30
31
  super(
31
32
  compose_message(
32
- message_key(params),
33
+ message_key(params, unmatched),
33
34
  {
34
35
  klass: klass.name,
35
36
  searched: searched(params),
36
37
  attributes: params,
37
38
  total: total(params),
38
- missing: missing(unmatched)
39
+ missing: missing(unmatched),
40
+ shard_key: shard_key(unmatched)
39
41
  }
40
42
  )
41
43
  )
@@ -48,12 +50,14 @@ module Mongoid
48
50
  # @example Get the missing string.
49
51
  # error.missing(1)
50
52
  #
51
- # @param [ Object, Array ] unmatched The ids that did not match.
53
+ # @param [ Object | Array ] unmatched The ids that did not match.
52
54
  #
53
55
  # @return [ String ] The missing string.
54
56
  def missing(unmatched)
55
57
  if unmatched.is_a?(::Array)
56
58
  unmatched.join(", ")
59
+ elsif unmatched.is_a?(::Hash)
60
+ unmatched[:_id] || unmatched["_id"]
57
61
  else
58
62
  unmatched
59
63
  end
@@ -64,7 +68,7 @@ module Mongoid
64
68
  # @example Get the searched string.
65
69
  # error.searched(1)
66
70
  #
67
- # @param [ Object, Array ] params The ids that were searched for.
71
+ # @param [ Object | Array ] params The ids that were searched for.
68
72
  #
69
73
  # @return [ String ] The searched string.
70
74
  def searched(params)
@@ -80,7 +84,7 @@ module Mongoid
80
84
  # @example Get the total.
81
85
  # error.total([ 1, 2, 3 ])
82
86
  #
83
- # @param [ Object, Array ] params What was searched for.
87
+ # @param [ Object | Array ] params What was searched for.
84
88
  #
85
89
  # @return [ Integer ] The total number.
86
90
  def total(params)
@@ -93,10 +97,27 @@ module Mongoid
93
97
  # error.problem
94
98
  #
95
99
  # @return [ String ] The problem.
96
- def message_key(params)
97
- case params
98
- when Hash then "document_with_attributes_not_found"
99
- else "document_not_found"
100
+ def message_key(params, unmatched)
101
+ if !params && !unmatched
102
+ "no_documents_found"
103
+ elsif Hash === params
104
+ "document_with_attributes_not_found"
105
+ elsif Hash === unmatched && unmatched.size >= 2
106
+ "document_with_shard_key_not_found"
107
+ else
108
+ "document_not_found"
109
+ end
110
+ end
111
+
112
+ # Get the shard key from the unmatched hash.
113
+ #
114
+ # @return [ String ] the shard key and value.
115
+ def shard_key(unmatched)
116
+ if Hash === unmatched
117
+ h = unmatched.dup
118
+ h.delete("_id")
119
+ h.delete(:_id)
120
+ h.map{|k,v| "#{k}: #{v}" }.join(", ")
100
121
  end
101
122
  end
102
123
  end