mongoid 7.5.4 → 8.1.9

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 (446) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +3 -3
  3. data/README.md +6 -6
  4. data/Rakefile +44 -46
  5. data/lib/config/locales/en.yml +92 -43
  6. data/lib/mongoid/association/accessors.rb +44 -11
  7. data/lib/mongoid/association/bindable.rb +50 -2
  8. data/lib/mongoid/association/builders.rb +5 -3
  9. data/lib/mongoid/association/constrainable.rb +0 -1
  10. data/lib/mongoid/association/eager_loadable.rb +32 -7
  11. data/lib/mongoid/association/embedded/batchable.rb +34 -11
  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/buildable.rb +2 -2
  15. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +4 -3
  16. data/lib/mongoid/association/embedded/embedded_in.rb +3 -2
  17. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  18. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +4 -3
  19. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +85 -46
  20. data/lib/mongoid/association/embedded/embeds_many.rb +2 -2
  21. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +19 -5
  22. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +24 -5
  23. data/lib/mongoid/association/embedded/embeds_one.rb +3 -3
  24. data/lib/mongoid/association/macros.rb +8 -1
  25. data/lib/mongoid/association/many.rb +11 -7
  26. data/lib/mongoid/association/nested/many.rb +5 -4
  27. data/lib/mongoid/association/nested/nested_buildable.rb +4 -4
  28. data/lib/mongoid/association/nested/one.rb +45 -7
  29. data/lib/mongoid/association/one.rb +2 -2
  30. data/lib/mongoid/association/options.rb +9 -9
  31. data/lib/mongoid/association/proxy.rb +15 -4
  32. data/lib/mongoid/association/referenced/auto_save.rb +4 -3
  33. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  34. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  35. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +5 -6
  36. data/lib/mongoid/association/referenced/belongs_to.rb +2 -2
  37. data/lib/mongoid/association/referenced/counter_cache.rb +10 -10
  38. data/lib/mongoid/association/referenced/eager.rb +2 -2
  39. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +70 -13
  40. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +6 -3
  41. data/lib/mongoid/association/referenced/has_many/enumerable.rb +22 -30
  42. data/lib/mongoid/association/referenced/has_many/proxy.rb +40 -21
  43. data/lib/mongoid/association/referenced/has_many.rb +3 -3
  44. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  45. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +5 -5
  46. data/lib/mongoid/association/referenced/has_one/proxy.rb +9 -12
  47. data/lib/mongoid/association/referenced/has_one.rb +3 -3
  48. data/lib/mongoid/association/referenced/syncable.rb +4 -4
  49. data/lib/mongoid/association/reflections.rb +4 -4
  50. data/lib/mongoid/association/relatable.rb +44 -10
  51. data/lib/mongoid/association.rb +5 -5
  52. data/lib/mongoid/atomic/modifiers.rb +2 -2
  53. data/lib/mongoid/atomic.rb +16 -7
  54. data/lib/mongoid/attributes/dynamic.rb +4 -4
  55. data/lib/mongoid/attributes/nested.rb +6 -6
  56. data/lib/mongoid/attributes/processing.rb +37 -6
  57. data/lib/mongoid/attributes/projector.rb +2 -2
  58. data/lib/mongoid/attributes/readonly.rb +11 -6
  59. data/lib/mongoid/attributes.rb +51 -42
  60. data/lib/mongoid/changeable.rb +147 -14
  61. data/lib/mongoid/clients/options.rb +5 -1
  62. data/lib/mongoid/clients/sessions.rb +2 -14
  63. data/lib/mongoid/clients/storage_options.rb +2 -5
  64. data/lib/mongoid/clients/validators/storage.rb +3 -15
  65. data/lib/mongoid/collection_configurable.rb +58 -0
  66. data/lib/mongoid/composable.rb +2 -0
  67. data/lib/mongoid/config/defaults.rb +60 -0
  68. data/lib/mongoid/config/options.rb +3 -0
  69. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  70. data/lib/mongoid/config/validators/client.rb +6 -6
  71. data/lib/mongoid/config/validators.rb +1 -0
  72. data/lib/mongoid/config.rb +153 -18
  73. data/lib/mongoid/contextual/aggregable/memory.rb +24 -16
  74. data/lib/mongoid/contextual/aggregable/mongo.rb +5 -5
  75. data/lib/mongoid/contextual/aggregable/none.rb +1 -1
  76. data/lib/mongoid/contextual/atomic.rb +1 -1
  77. data/lib/mongoid/contextual/geo_near.rb +7 -7
  78. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  79. data/lib/mongoid/contextual/memory.rb +285 -58
  80. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  81. data/lib/mongoid/contextual/mongo.rb +540 -346
  82. data/lib/mongoid/contextual/none.rb +193 -20
  83. data/lib/mongoid/contextual/queryable.rb +1 -1
  84. data/lib/mongoid/contextual.rb +14 -2
  85. data/lib/mongoid/copyable.rb +32 -8
  86. data/lib/mongoid/criteria/findable.rb +8 -5
  87. data/lib/mongoid/criteria/includable.rb +27 -22
  88. data/lib/mongoid/criteria/marshalable.rb +10 -2
  89. data/lib/mongoid/criteria/permission.rb +1 -1
  90. data/lib/mongoid/criteria/queryable/aggregable.rb +2 -2
  91. data/lib/mongoid/criteria/queryable/extensions/array.rb +3 -16
  92. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  93. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +2 -2
  94. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  95. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  96. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -17
  97. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +15 -9
  98. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  99. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  100. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  101. data/lib/mongoid/criteria/queryable/extensions/set.rb +1 -1
  102. data/lib/mongoid/criteria/queryable/extensions/string.rb +4 -14
  103. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +4 -12
  104. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  105. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  106. data/lib/mongoid/criteria/queryable/key.rb +4 -4
  107. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  108. data/lib/mongoid/criteria/queryable/optional.rb +11 -17
  109. data/lib/mongoid/criteria/queryable/options.rb +2 -2
  110. data/lib/mongoid/criteria/queryable/pipeline.rb +1 -1
  111. data/lib/mongoid/criteria/queryable/selectable.rb +48 -39
  112. data/lib/mongoid/criteria/queryable/selector.rb +92 -7
  113. data/lib/mongoid/criteria/queryable/smash.rb +40 -7
  114. data/lib/mongoid/criteria/queryable.rb +12 -7
  115. data/lib/mongoid/criteria/scopable.rb +2 -2
  116. data/lib/mongoid/criteria/translator.rb +45 -0
  117. data/lib/mongoid/criteria.rb +20 -40
  118. data/lib/mongoid/deprecable.rb +37 -0
  119. data/lib/mongoid/deprecation.rb +25 -0
  120. data/lib/mongoid/document.rb +135 -36
  121. data/lib/mongoid/equality.rb +9 -8
  122. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  123. data/lib/mongoid/errors/document_not_found.rb +10 -6
  124. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  125. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  126. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  127. data/lib/mongoid/errors/invalid_config_option.rb +1 -1
  128. data/lib/mongoid/errors/invalid_dependent_strategy.rb +1 -1
  129. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  130. data/lib/mongoid/errors/invalid_field.rb +6 -2
  131. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  132. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  133. data/lib/mongoid/errors/invalid_relation.rb +1 -1
  134. data/lib/mongoid/errors/invalid_relation_option.rb +1 -1
  135. data/lib/mongoid/errors/invalid_session_use.rb +1 -1
  136. data/lib/mongoid/errors/invalid_storage_options.rb +1 -1
  137. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  138. data/lib/mongoid/errors/mongoid_error.rb +3 -3
  139. data/lib/mongoid/errors/nested_attributes_metadata_not_found.rb +1 -1
  140. data/lib/mongoid/errors/no_client_database.rb +1 -1
  141. data/lib/mongoid/errors/no_client_hosts.rb +1 -1
  142. data/lib/mongoid/errors/readonly_attribute.rb +1 -1
  143. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  144. data/lib/mongoid/errors/unknown_attribute.rb +1 -1
  145. data/lib/mongoid/errors.rb +6 -3
  146. data/lib/mongoid/extensions/array.rb +9 -7
  147. data/lib/mongoid/extensions/big_decimal.rb +33 -10
  148. data/lib/mongoid/extensions/binary.rb +42 -0
  149. data/lib/mongoid/extensions/boolean.rb +8 -2
  150. data/lib/mongoid/extensions/date.rb +26 -20
  151. data/lib/mongoid/extensions/date_time.rb +1 -1
  152. data/lib/mongoid/extensions/false_class.rb +1 -1
  153. data/lib/mongoid/extensions/float.rb +7 -4
  154. data/lib/mongoid/extensions/hash.rb +38 -9
  155. data/lib/mongoid/extensions/integer.rb +7 -4
  156. data/lib/mongoid/extensions/module.rb +1 -1
  157. data/lib/mongoid/extensions/object.rb +10 -8
  158. data/lib/mongoid/extensions/range.rb +41 -10
  159. data/lib/mongoid/extensions/regexp.rb +11 -4
  160. data/lib/mongoid/extensions/set.rb +11 -4
  161. data/lib/mongoid/extensions/string.rb +11 -22
  162. data/lib/mongoid/extensions/symbol.rb +4 -15
  163. data/lib/mongoid/extensions/time.rb +29 -16
  164. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  165. data/lib/mongoid/extensions/true_class.rb +1 -1
  166. data/lib/mongoid/extensions.rb +1 -0
  167. data/lib/mongoid/factory.rb +55 -7
  168. data/lib/mongoid/fields/foreign_key.rb +11 -4
  169. data/lib/mongoid/fields/localized.rb +19 -4
  170. data/lib/mongoid/fields/standard.rb +17 -7
  171. data/lib/mongoid/fields/validators/macro.rb +3 -9
  172. data/lib/mongoid/fields.rb +142 -28
  173. data/lib/mongoid/findable.rb +54 -24
  174. data/lib/mongoid/indexable/specification.rb +2 -2
  175. data/lib/mongoid/indexable/validators/options.rb +6 -2
  176. data/lib/mongoid/interceptable.rb +187 -16
  177. data/lib/mongoid/matchable.rb +1 -1
  178. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  179. data/lib/mongoid/matcher/type.rb +1 -1
  180. data/lib/mongoid/matcher.rb +48 -14
  181. data/lib/mongoid/persistable/creatable.rb +19 -9
  182. data/lib/mongoid/persistable/deletable.rb +2 -2
  183. data/lib/mongoid/persistable/destroyable.rb +1 -1
  184. data/lib/mongoid/persistable/savable.rb +14 -2
  185. data/lib/mongoid/persistable/unsettable.rb +2 -2
  186. data/lib/mongoid/persistable/updatable.rb +69 -12
  187. data/lib/mongoid/persistable/upsertable.rb +21 -2
  188. data/lib/mongoid/persistable.rb +6 -3
  189. data/lib/mongoid/persistence_context.rb +6 -4
  190. data/lib/mongoid/query_cache.rb +13 -261
  191. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  192. data/lib/mongoid/railties/database.rake +7 -2
  193. data/lib/mongoid/reloadable.rb +10 -8
  194. data/lib/mongoid/scopable.rb +15 -13
  195. data/lib/mongoid/selectable.rb +1 -2
  196. data/lib/mongoid/serializable.rb +17 -13
  197. data/lib/mongoid/stateful.rb +57 -10
  198. data/lib/mongoid/tasks/database.rake +12 -0
  199. data/lib/mongoid/tasks/database.rb +20 -2
  200. data/lib/mongoid/threaded/lifecycle.rb +5 -5
  201. data/lib/mongoid/threaded.rb +42 -12
  202. data/lib/mongoid/timestamps/created.rb +9 -2
  203. data/lib/mongoid/timestamps/updated.rb +2 -2
  204. data/lib/mongoid/touchable.rb +3 -4
  205. data/lib/mongoid/traversable.rb +41 -5
  206. data/lib/mongoid/utils.rb +22 -0
  207. data/lib/mongoid/validatable/associated.rb +98 -17
  208. data/lib/mongoid/validatable/localizable.rb +1 -1
  209. data/lib/mongoid/validatable/macros.rb +5 -7
  210. data/lib/mongoid/validatable/presence.rb +2 -2
  211. data/lib/mongoid/validatable/uniqueness.rb +9 -8
  212. data/lib/mongoid/validatable.rb +17 -6
  213. data/lib/mongoid/version.rb +1 -1
  214. data/lib/mongoid/warnings.rb +19 -4
  215. data/lib/mongoid.rb +17 -3
  216. data/spec/config/mongoid.yml +16 -0
  217. data/spec/integration/app_spec.rb +24 -19
  218. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  219. data/spec/integration/associations/embedded_spec.rb +15 -0
  220. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  221. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  222. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  223. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +61 -0
  224. data/spec/integration/associations/has_one_spec.rb +97 -1
  225. data/spec/integration/associations/scope_option_spec.rb +1 -1
  226. data/spec/integration/callbacks_models.rb +132 -1
  227. data/spec/integration/callbacks_spec.rb +381 -4
  228. data/spec/integration/criteria/range_spec.rb +95 -1
  229. data/spec/integration/discriminator_key_spec.rb +118 -80
  230. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  231. data/spec/integration/i18n_fallbacks_spec.rb +3 -32
  232. data/spec/integration/matcher_examples_spec.rb +20 -13
  233. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  234. data/spec/integration/matcher_operator_spec.rb +3 -5
  235. data/spec/integration/persistence/range_field_spec.rb +350 -0
  236. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  237. data/spec/mongoid/association/depending_spec.rb +9 -9
  238. data/spec/mongoid/association/eager_spec.rb +26 -3
  239. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  240. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  241. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +96 -9
  242. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  243. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +290 -65
  244. data/spec/mongoid/association/embedded/embeds_many_models.rb +37 -0
  245. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +16 -0
  246. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  247. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  248. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  249. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  250. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  251. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  252. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  253. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +19 -0
  254. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  255. data/spec/mongoid/association/referenced/belongs_to_spec.rb +4 -20
  256. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +186 -229
  257. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  258. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  259. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  260. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  261. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +215 -177
  262. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  263. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  264. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  265. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  266. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  267. data/spec/mongoid/association/syncable_spec.rb +15 -1
  268. data/spec/mongoid/association_spec.rb +60 -0
  269. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  270. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  271. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  272. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  273. data/spec/mongoid/attributes/readonly_spec.rb +19 -0
  274. data/spec/mongoid/attributes_spec.rb +526 -33
  275. data/spec/mongoid/changeable_spec.rb +429 -37
  276. data/spec/mongoid/clients/factory_spec.rb +23 -30
  277. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  278. data/spec/mongoid/clients_spec.rb +149 -15
  279. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  280. data/spec/mongoid/config/defaults_spec.rb +160 -0
  281. data/spec/mongoid/config_spec.rb +214 -31
  282. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  283. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  284. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  285. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  286. data/spec/mongoid/contextual/memory_spec.rb +850 -88
  287. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  288. data/spec/mongoid/contextual/mongo_spec.rb +2256 -1005
  289. data/spec/mongoid/contextual/none_spec.rb +60 -21
  290. data/spec/mongoid/copyable_spec.rb +453 -11
  291. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  292. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  293. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  294. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  295. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  296. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  297. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  298. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  299. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  300. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  301. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
  302. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  303. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  304. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  305. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -484
  306. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  307. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +469 -0
  308. data/spec/mongoid/criteria/queryable/selectable_spec.rb +107 -86
  309. data/spec/mongoid/criteria/queryable/selector_spec.rb +15 -3
  310. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  311. data/spec/mongoid/criteria_projection_spec.rb +1 -5
  312. data/spec/mongoid/criteria_spec.rb +469 -1205
  313. data/spec/mongoid/document_fields_spec.rb +173 -24
  314. data/spec/mongoid/document_spec.rb +59 -41
  315. data/spec/mongoid/equality_spec.rb +6 -0
  316. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  317. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  318. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  319. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  320. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  321. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  322. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  323. data/spec/mongoid/extensions/array_spec.rb +16 -2
  324. data/spec/mongoid/extensions/big_decimal_spec.rb +712 -212
  325. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  326. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  327. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  328. data/spec/mongoid/extensions/date_spec.rb +71 -1
  329. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  330. data/spec/mongoid/extensions/float_spec.rb +53 -74
  331. data/spec/mongoid/extensions/hash_spec.rb +33 -3
  332. data/spec/mongoid/extensions/integer_spec.rb +50 -64
  333. data/spec/mongoid/extensions/range_spec.rb +255 -54
  334. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  335. data/spec/mongoid/extensions/set_spec.rb +106 -0
  336. data/spec/mongoid/extensions/string_spec.rb +53 -25
  337. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  338. data/spec/mongoid/extensions/time_spec.rb +639 -106
  339. data/spec/mongoid/extensions/time_with_zone_spec.rb +24 -83
  340. data/spec/mongoid/factory_spec.rb +61 -1
  341. data/spec/mongoid/fields/localized_spec.rb +80 -37
  342. data/spec/mongoid/fields_spec.rb +503 -87
  343. data/spec/mongoid/findable_spec.rb +450 -58
  344. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  345. data/spec/mongoid/indexable_spec.rb +55 -30
  346. data/spec/mongoid/interceptable_spec.rb +904 -22
  347. data/spec/mongoid/interceptable_spec_models.rb +189 -22
  348. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  349. data/spec/mongoid/mongoizable_spec.rb +285 -0
  350. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  351. data/spec/mongoid/persistable/deletable_spec.rb +28 -8
  352. data/spec/mongoid/persistable/destroyable_spec.rb +28 -8
  353. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  354. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  355. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  356. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  357. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  358. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  359. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  360. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  361. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  362. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  363. data/spec/mongoid/persistable/upsertable_spec.rb +89 -1
  364. data/spec/mongoid/persistence_context_spec.rb +31 -57
  365. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  366. data/spec/mongoid/query_cache_spec.rb +56 -215
  367. data/spec/mongoid/reloadable_spec.rb +83 -6
  368. data/spec/mongoid/scopable_spec.rb +91 -1
  369. data/spec/mongoid/serializable_spec.rb +25 -39
  370. data/spec/mongoid/shardable_spec.rb +4 -4
  371. data/spec/mongoid/stateful_spec.rb +150 -8
  372. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  373. data/spec/mongoid/tasks/database_spec.rb +127 -0
  374. data/spec/mongoid/timestamps/created_spec.rb +23 -0
  375. data/spec/mongoid/timestamps_spec.rb +392 -4
  376. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  377. data/spec/mongoid/touchable_spec.rb +390 -2
  378. data/spec/mongoid/touchable_spec_models.rb +14 -8
  379. data/spec/mongoid/traversable_spec.rb +13 -35
  380. data/spec/mongoid/validatable/associated_spec.rb +27 -34
  381. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  382. data/spec/mongoid/validatable/uniqueness_spec.rb +58 -31
  383. data/spec/mongoid/warnings_spec.rb +35 -0
  384. data/spec/mongoid_spec.rb +34 -16
  385. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  386. data/spec/rails/mongoid_spec.rb +4 -16
  387. data/spec/spec_helper.rb +5 -0
  388. data/spec/support/constraints.rb +24 -0
  389. data/spec/support/immutable_ids.rb +118 -0
  390. data/spec/support/macros.rb +78 -0
  391. data/spec/support/models/artist.rb +0 -1
  392. data/spec/support/models/augmentation.rb +12 -0
  393. data/spec/support/models/band.rb +5 -0
  394. data/spec/support/models/book.rb +1 -0
  395. data/spec/support/models/building.rb +2 -0
  396. data/spec/support/models/catalog.rb +24 -0
  397. data/spec/support/models/circus.rb +3 -0
  398. data/spec/support/models/cover.rb +10 -0
  399. data/spec/support/models/fanatic.rb +8 -0
  400. data/spec/support/models/implant.rb +9 -0
  401. data/spec/support/models/label.rb +2 -0
  402. data/spec/support/models/lat_lng.rb +6 -0
  403. data/spec/support/models/name.rb +10 -0
  404. data/spec/support/models/passport.rb +9 -0
  405. data/spec/support/models/person.rb +2 -0
  406. data/spec/support/models/player.rb +2 -0
  407. data/spec/support/models/powerup.rb +12 -0
  408. data/spec/support/models/product.rb +1 -0
  409. data/spec/support/models/purse.rb +9 -0
  410. data/spec/support/models/registry.rb +1 -0
  411. data/spec/support/models/school.rb +14 -0
  412. data/spec/support/models/shield.rb +18 -0
  413. data/spec/support/models/student.rb +14 -0
  414. data/spec/support/models/weapon.rb +12 -0
  415. metadata +98 -96
  416. checksums.yaml.gz.sig +0 -0
  417. data/lib/mongoid/errors/eager_load.rb +0 -23
  418. data/lib/mongoid/errors/invalid_value.rb +0 -17
  419. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  420. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
  421. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
  422. data/spec/shared/LICENSE +0 -20
  423. data/spec/shared/bin/get-mongodb-download-url +0 -17
  424. data/spec/shared/bin/s3-copy +0 -45
  425. data/spec/shared/bin/s3-upload +0 -69
  426. data/spec/shared/lib/mrss/child_process_helper.rb +0 -80
  427. data/spec/shared/lib/mrss/cluster_config.rb +0 -231
  428. data/spec/shared/lib/mrss/constraints.rb +0 -378
  429. data/spec/shared/lib/mrss/docker_runner.rb +0 -291
  430. data/spec/shared/lib/mrss/eg_config_utils.rb +0 -51
  431. data/spec/shared/lib/mrss/event_subscriber.rb +0 -210
  432. data/spec/shared/lib/mrss/lite_constraints.rb +0 -238
  433. data/spec/shared/lib/mrss/server_version_registry.rb +0 -120
  434. data/spec/shared/lib/mrss/session_registry.rb +0 -69
  435. data/spec/shared/lib/mrss/session_registry_legacy.rb +0 -60
  436. data/spec/shared/lib/mrss/spec_organizer.rb +0 -179
  437. data/spec/shared/lib/mrss/utils.rb +0 -15
  438. data/spec/shared/share/Dockerfile.erb +0 -325
  439. data/spec/shared/share/haproxy-1.conf +0 -16
  440. data/spec/shared/share/haproxy-2.conf +0 -17
  441. data/spec/shared/shlib/config.sh +0 -27
  442. data/spec/shared/shlib/distro.sh +0 -74
  443. data/spec/shared/shlib/server.sh +0 -392
  444. data/spec/shared/shlib/set_env.sh +0 -169
  445. data.tar.gz.sig +0 -0
  446. metadata.gz.sig +0 -3
@@ -92,7 +92,7 @@ module Mongoid
92
92
 
93
93
  # Is this association polymorphic?
94
94
  #
95
- # @return [ true, false ] Whether this association is polymorphic.
95
+ # @return [ true | false ] Whether this association is polymorphic.
96
96
  def polymorphic?
97
97
  @polymorphic ||= !!as
98
98
  end
@@ -101,7 +101,7 @@ module Mongoid
101
101
  #
102
102
  # @note Only relevant for polymorphic associations.
103
103
  #
104
- # @return [ String, nil ] The type field.
104
+ # @return [ String | nil ] The type field.
105
105
  def type
106
106
  @type ||= "#{as}_type" if polymorphic?
107
107
  end
@@ -111,7 +111,7 @@ module Mongoid
111
111
  #
112
112
  # @param [ Document ] doc The document to be bound.
113
113
  #
114
- # @return [ true, false ] Whether the document can be bound.
114
+ # @return [ true | false ] Whether the document can be bound.
115
115
  def bindable?(doc)
116
116
  forced_nil_inverse? || (!!inverse && doc.fields.keys.include?(foreign_key))
117
117
  end
@@ -16,7 +16,7 @@ module Mongoid
16
16
  #
17
17
  # @param [ Association ] association The association metadata.
18
18
  #
19
- # @return [ true, false ] If we can sync.
19
+ # @return [ true | false ] If we can sync.
20
20
  def _syncable?(association)
21
21
  !_synced?(association.foreign_key) && send(association.foreign_key_check)
22
22
  end
@@ -38,7 +38,7 @@ module Mongoid
38
38
  #
39
39
  # @param [ String ] foreign_key The foreign key.
40
40
  #
41
- # @return [ true, false ] If we can sync.
41
+ # @return [ true | false ] If we can sync.
42
42
  def _synced?(foreign_key)
43
43
  !!_synced[foreign_key]
44
44
  end
@@ -67,8 +67,8 @@ module Mongoid
67
67
  #
68
68
  # @return [ Object ] The updated values.
69
69
  def update_inverse_keys(association)
70
- if changes.has_key?(association.foreign_key)
71
- old, new = changes[association.foreign_key]
70
+ if previous_changes.has_key?(association.foreign_key)
71
+ old, new = previous_changes[association.foreign_key]
72
72
  adds, subs = new - (old || []), (old || []) - new
73
73
 
74
74
  # If we are autosaving we don't want a duplicate to get added - the
@@ -13,7 +13,7 @@ module Mongoid
13
13
  # @example Find association metadata by name.
14
14
  # person.reflect_on_association(:addresses)
15
15
  #
16
- # @param [ String, Symbol ] name The name of the association to find.
16
+ # @param [ String | Symbol ] name The name of the association to find.
17
17
  #
18
18
  # @return [ Association ] The matching association metadata.
19
19
  def reflect_on_association(name)
@@ -25,7 +25,7 @@ module Mongoid
25
25
  # @example Find multiple association metadata by macro.
26
26
  # person.reflect_on_all_associations(:embeds_many)
27
27
  #
28
- # @param [ Array<Symbol> ] macros The association macros.
28
+ # @param [ Symbol... ] *macros The association macros.
29
29
  #
30
30
  # @return [ Array<Association> ] The matching association metadata.
31
31
  def reflect_on_all_association(*macros)
@@ -39,7 +39,7 @@ module Mongoid
39
39
  # @example Find association metadata by name.
40
40
  # Person.reflect_on_association(:addresses)
41
41
  #
42
- # @param [ String, Symbol ] name The name of the association to find.
42
+ # @param [ String | Symbol ] name The name of the association to find.
43
43
  #
44
44
  # @return [ Association ] The matching association metadata.
45
45
  def reflect_on_association(name)
@@ -51,7 +51,7 @@ module Mongoid
51
51
  # @example Find multiple association metadata by macro.
52
52
  # Person.reflect_on_all_associations(:embeds_many)
53
53
  #
54
- # @param [ Array<Symbol> ] macros The association macros.
54
+ # @param [ Symbol... ] *macros The association macros.
55
55
  #
56
56
  # @return [ Array<Association> ] The matching association metadata.
57
57
  def reflect_on_all_associations(*macros)
@@ -69,7 +69,7 @@ module Mongoid
69
69
  #
70
70
  # @param [ Symbol ] callback_type The type of callback type.
71
71
  #
72
- # @return [ Array<Proc, Symbol> ] A list of the callbacks, either method
72
+ # @return [ Array<Proc | Symbol> ] A list of the callbacks, either method
73
73
  # names or Procs.
74
74
  def get_callbacks(callback_type)
75
75
  Array(options[callback_type])
@@ -88,7 +88,7 @@ module Mongoid
88
88
  #
89
89
  # @param [ Document ] doc The document to be bound.
90
90
  #
91
- # @return [ true, false ] Whether the document can be bound.
91
+ # @return [ true | false ] Whether the document can be bound.
92
92
  def bindable?(doc); false; end
93
93
 
94
94
  # Get the inverse names.
@@ -189,7 +189,7 @@ module Mongoid
189
189
  # The foreign key field if this association stores a foreign key.
190
190
  # Otherwise, the primary key.
191
191
  #
192
- # @return [ Symbol, String ] The primary key.
192
+ # @return [ Symbol | String ] The primary key.
193
193
  def key
194
194
  stores_foreign_key? ? foreign_key : primary_key
195
195
  end
@@ -242,13 +242,13 @@ module Mongoid
242
242
  #
243
243
  # @return [ String ] The foreign key check.
244
244
  def foreign_key_check
245
- @foreign_key_check ||= "#{foreign_key}_changed?" if (stores_foreign_key? && foreign_key)
245
+ @foreign_key_check ||= "#{foreign_key}_previously_changed?" if (stores_foreign_key? && foreign_key)
246
246
  end
247
247
 
248
248
  # Create an association proxy object using the owner and target.
249
249
  #
250
250
  # @param [ Document ] owner The document this association hangs off of.
251
- # @param [ Document, Array<Document> ] target The target (parent) of the
251
+ # @param [ Document | Array<Document> ] target The target (parent) of the
252
252
  # association.
253
253
  #
254
254
  # @return [ Proxy ]
@@ -258,7 +258,7 @@ module Mongoid
258
258
 
259
259
  # Whether the dependent method is destructive.
260
260
  #
261
- # @return [ true, false ] If the dependent method is destructive.
261
+ # @return [ true | false ] If the dependent method is destructive.
262
262
  def destructive?
263
263
  @destructive ||= !!(dependent && (dependent == :delete_all || dependent == :destroy))
264
264
  end
@@ -289,7 +289,7 @@ module Mongoid
289
289
 
290
290
  # Whether the associated object(s) should be validated.
291
291
  #
292
- # @return [ true, false ] If the associated object(s)
292
+ # @return [ true | false ] If the associated object(s)
293
293
  # should be validated.
294
294
  def validate?
295
295
  @validate ||= if @options[:validate].nil?
@@ -299,6 +299,35 @@ module Mongoid
299
299
  end
300
300
  end
301
301
 
302
+ # @return [ Array<String> ] The associations above this one in the inclusion tree.
303
+ attr_accessor :parent_inclusions
304
+
305
+ def parent_inclusions
306
+ @parent_inclusions ||= []
307
+ end
308
+
309
+ # Is this association an embeds_many or has_many association?
310
+ #
311
+ # @return [ true | false ] true if it is a *_many association, false if not.
312
+ def many?
313
+ [Referenced::HasMany, Embedded::EmbedsMany].any? { |a| self.is_a?(a) }
314
+ end
315
+
316
+ # Is this association an embeds_one or has_one association?
317
+ #
318
+ # @return [ true | false ] true if it is a *_one association, false if not.
319
+ def one?
320
+ [Referenced::HasOne, Embedded::EmbedsOne].any? { |a| self.is_a?(a) }
321
+ end
322
+
323
+ # Is this association an embedded_in or belongs_to association?
324
+ #
325
+ # @return [ true | false ] true if it is an embedded_in or belongs_to
326
+ # association, false if not.
327
+ def in_to?
328
+ [Referenced::BelongsTo, Embedded::EmbeddedIn].any? { |a| self.is_a?(a) }
329
+ end
330
+
302
331
  private
303
332
 
304
333
  # Gets the model classes with inverse associations of this model. This is used to determine
@@ -404,10 +433,15 @@ module Mongoid
404
433
  def namespace_hierarchy(mod)
405
434
  parent = Object
406
435
  hier = [parent]
407
- mod.name.split('::').each do |part|
408
- parent = parent.const_get(part)
409
- hier << parent
436
+
437
+ # name is not present on anonymous modules
438
+ if mod.name
439
+ mod.name.split('::').each do |part|
440
+ parent = parent.const_get(part)
441
+ hier << parent
442
+ end
410
443
  end
444
+
411
445
  hier.reverse
412
446
  end
413
447
 
@@ -56,7 +56,7 @@ module Mongoid
56
56
  # @example Is the document embedded?
57
57
  # address.embedded?
58
58
  #
59
- # @return [ true, false ] True if the document has a parent document.
59
+ # @return [ true | false ] True if the document has a parent document.
60
60
  def embedded?
61
61
  @embedded ||= (cyclic ? _parent.present? : self.class.embedded?)
62
62
  end
@@ -66,7 +66,7 @@ module Mongoid
66
66
  # @example Is the document in an embeds many?
67
67
  # address.embedded_many?
68
68
  #
69
- # @return [ true, false ] True if in an embeds many.
69
+ # @return [ true | false ] True if in an embeds many.
70
70
  def embedded_many?
71
71
  _association && _association.is_a?(Association::Embedded::EmbedsMany)
72
72
  end
@@ -76,7 +76,7 @@ module Mongoid
76
76
  # @example Is the document in an embeds one?
77
77
  # address.embedded_one?
78
78
  #
79
- # @return [ true, false ] True if in an embeds one.
79
+ # @return [ true | false ] True if in an embeds one.
80
80
  def embedded_one?
81
81
  _association && _association.is_a?(Association::Embedded::EmbedsOne)
82
82
  end
@@ -100,7 +100,7 @@ module Mongoid
100
100
  # @example Is the document in a references many?
101
101
  # post.referenced_many?
102
102
  #
103
- # @return [ true, false ] True if in a references many.
103
+ # @return [ true | false ] True if in a references many.
104
104
  def referenced_many?
105
105
  _association && _association.is_a?(Association::Referenced::HasMany)
106
106
  end
@@ -110,7 +110,7 @@ module Mongoid
110
110
  # @example Is the document in a references one?
111
111
  # address.referenced_one?
112
112
  #
113
- # @return [ true, false ] True if in a references one.
113
+ # @return [ true | false ] True if in a references one.
114
114
  def referenced_one?
115
115
  _association && _association.is_a?(Association::Referenced::HasOne)
116
116
  end
@@ -153,7 +153,7 @@ module Mongoid
153
153
  #
154
154
  # @param [ String ] field The field.
155
155
  #
156
- # @return [ true, false ] If this field is a conflict.
156
+ # @return [ true | false ] If this field is a conflict.
157
157
  def set_conflict?(field)
158
158
  name = field.split(".", 2)[0]
159
159
  pull_fields.has_key?(name) || push_fields.has_key?(name)
@@ -166,7 +166,7 @@ module Mongoid
166
166
  #
167
167
  # @param [ String ] field The field.
168
168
  #
169
- # @return [ true, false ] If this field is a conflict.
169
+ # @return [ true | false ] If this field is a conflict.
170
170
  def push_conflict?(field)
171
171
  name = field.split(".", 2)[0]
172
172
  set_fields.has_key?(name) || pull_fields.has_key?(name) ||
@@ -178,13 +178,15 @@ module Mongoid
178
178
  #
179
179
  # @return [ Object ] The associated path.
180
180
  def atomic_paths
181
- @atomic_paths ||= begin
182
- if _association
183
- _association.path(self)
184
- else
185
- Atomic::Paths::Root.new(self)
186
- end
187
- end
181
+ return @atomic_paths if @atomic_paths
182
+
183
+ paths = if _association
184
+ _association.path(self)
185
+ else
186
+ Atomic::Paths::Root.new(self)
187
+ end
188
+
189
+ paths.tap { @atomic_paths = paths unless new_record? }
188
190
  end
189
191
 
190
192
  # Get all the attributes that need to be pulled.
@@ -311,6 +313,13 @@ module Mongoid
311
313
 
312
314
  private
313
315
 
316
+ # Clears all pending atomic updates.
317
+ def reset_atomic_updates!
318
+ Atomic::UPDATES.each do |update|
319
+ send(update).clear
320
+ end
321
+ end
322
+
314
323
  # Generates the atomic updates in the correct order.
315
324
  #
316
325
  # @example Generate the updates.
@@ -13,9 +13,9 @@ module Mongoid
13
13
  # person.respond_to?(:title)
14
14
  #
15
15
  # @param [ Array ] name The name of the method.
16
- # @param [ true, false ] include_private
16
+ # @param [ true | false ] include_private
17
17
  #
18
- # @return [ true, false ] True if it does, false if not.
18
+ # @return [ true | false ] True if it does, false if not.
19
19
  def respond_to?(name, include_private = false)
20
20
  super || (
21
21
  attributes &&
@@ -114,8 +114,8 @@ module Mongoid
114
114
  # @example Call through method_missing.
115
115
  # document.method_missing(:test)
116
116
  #
117
- # @param [ String, Symbol ] name The name of the method.
118
- # @param [ Array ] args The arguments to the method.
117
+ # @param [ String | Symbol ] name The name of the method.
118
+ # @param [ Object... ] *args The arguments to the method.
119
119
  #
120
120
  # @return [ Object ] The result of the method call.
121
121
  def method_missing(name, *args)
@@ -33,15 +33,15 @@ module Mongoid
33
33
  # accepts_nested_attributes_for :addresses, :game, :posts
34
34
  # end
35
35
  #
36
- # @param [ Array<Symbol>, Hash ] args A list of association names, followed
37
- # by a hash of options.
36
+ # @param [ Symbol..., Hash ] *args A list of association names, followed
37
+ # by an optional hash of options.
38
38
  #
39
- # @option *args [ true, false ] :allow_destroy Can deletion occur?
40
- # @option *args [ Proc, Symbol ] :reject_if Block or symbol pointing
39
+ # @option *args [ true | false ] :allow_destroy Can deletion occur?
40
+ # @option *args [ Proc | Symbol ] :reject_if Block or symbol pointing
41
41
  # to a class method to reject documents with.
42
42
  # @option *args [ Integer ] :limit The max number to create.
43
- # @option *args [ true, false ] :update_only Only update existing docs.
44
- # @options *args [ true, false ] :autosave Whether autosave should be enabled on the
43
+ # @option *args [ true | false ] :update_only Only update existing docs.
44
+ # @option *args [ true | false ] :autosave Whether autosave should be enabled on the
45
45
  # association. Note that since the default is true, setting autosave to nil will still
46
46
  # enable it.
47
47
  def accepts_nested_attributes_for(*args)
@@ -40,18 +40,49 @@ module Mongoid
40
40
  # @param [ Symbol ] key The name of the attribute.
41
41
  # @param [ Object ] value The value of the attribute.
42
42
  #
43
- # @return [ true, false ] True if pending, false if not.
43
+ # @return [ true | false ] True if pending, false if not.
44
44
  def pending_attribute?(key, value)
45
45
  name = key.to_s
46
- if relations.has_key?(name)
47
- pending_relations[name] = value
46
+ aliased = if aliased_associations.key?(name)
47
+ aliased_associations[name]
48
+ else
49
+ name
50
+ end
51
+ if relations.has_key?(aliased)
52
+ set_pending_relation(name, aliased, value)
48
53
  return true
49
54
  end
50
- if nested_attributes.has_key?(name)
51
- pending_nested[name] = value
55
+ if nested_attributes.has_key?(aliased)
56
+ set_pending_nested(name, aliased, value)
52
57
  return true
53
58
  end
54
- return false
59
+ false
60
+ end
61
+
62
+ # Set value of the pending relation.
63
+ #
64
+ # @param [ Symbol ] name The name of the relation.
65
+ # @param [ Symbol ] aliased The aliased name of the relation.
66
+ # @param [ Object ] value The value of the relation.
67
+ def set_pending_relation(name, aliased, value)
68
+ if stored_as_associations.include?(name)
69
+ pending_relations[aliased] = value
70
+ else
71
+ pending_relations[name] = value
72
+ end
73
+ end
74
+
75
+ # Set value of the pending nested attribute.
76
+ #
77
+ # @param [ Symbol ] name The name of the nested attribute.
78
+ # @param [ Symbol ] aliased The aliased name of the nested attribute.
79
+ # @param [ Object ] value The value of the nested attribute.
80
+ def set_pending_nested(name, aliased, value)
81
+ if stored_as_associations.include?(name)
82
+ pending_nested[aliased] = value
83
+ else
84
+ pending_nested[name] = value
85
+ end
55
86
  end
56
87
 
57
88
  # Get all the pending associations that need to be set.
@@ -6,7 +6,7 @@ module Mongoid
6
6
  # This module defines projection helpers.
7
7
  #
8
8
  # Projection rules are rather non-trivial. See
9
- # https://docs.mongodb.com/manual/reference/method/db.collection.find/#find-projection
9
+ # https://www.mongodb.com/docs/manual/reference/method/db.collection.find/#find-projection
10
10
  # for server documentation.
11
11
  # 4.4 server (and presumably all older ones) requires that a projection
12
12
  # for content fields is either exclusionary or inclusionary, i.e. one
@@ -41,7 +41,7 @@ module Mongoid
41
41
  #
42
42
  # @param [ String ] name The name of the attribute or a dot notation path.
43
43
  #
44
- # @return [ true, false ] Whether the attribute is allowed by projection.
44
+ # @return [ true | false ] Whether the attribute is allowed by projection.
45
45
  #
46
46
  # @api private
47
47
  def attribute_or_path_allowed?(name)
@@ -17,12 +17,12 @@ module Mongoid
17
17
  # @example Can we write the attribute?
18
18
  # model.attribute_writable?(:title)
19
19
  #
20
- # @param [ String, Symbol ] name The name of the field.
20
+ # @param [ String | Symbol ] name The name of the field.
21
21
  #
22
- # @return [ true, false ] If the document is new, or if the field is not
22
+ # @return [ true | false ] If the document is new, or if the field is not
23
23
  # readonly.
24
24
  def attribute_writable?(name)
25
- new_record? || (!readonly_attributes.include?(name) && _loaded?(name))
25
+ new_record? || (!self.class.readonly_attributes.include?(name) && _loaded?(name))
26
26
  end
27
27
 
28
28
  private
@@ -61,13 +61,18 @@ module Mongoid
61
61
  # attr_readonly :name, :genre
62
62
  # end
63
63
  #
64
- # @param [ Array<Symbol> ] names The names of the fields.
64
+ # @param [ Symbol... ] *names The names of the fields.
65
+ # @note When a parent class contains readonly attributes and is then
66
+ # inherited by a child class, the child class will inherit the
67
+ # parent's readonly attributes at the time of its creation.
68
+ # Updating the parent does not propagate down to child classes after wards.
65
69
  def attr_readonly(*names)
70
+ self.readonly_attributes = self.readonly_attributes.dup
66
71
  names.each do |name|
67
- readonly_attributes << database_field_name(name)
72
+ self.readonly_attributes << database_field_name(name)
68
73
  end
69
74
  end
70
75
  end
71
76
  end
72
77
  end
73
- end
78
+ end
@@ -25,9 +25,9 @@ module Mongoid
25
25
  # @example Is the attribute present?
26
26
  # person.attribute_present?("title")
27
27
  #
28
- # @param [ String, Symbol ] name The name of the attribute.
28
+ # @param [ String | Symbol ] name The name of the attribute.
29
29
  #
30
- # @return [ true, false ] True if present, false if not.
30
+ # @return [ true | false ] True if present, false if not.
31
31
  def attribute_present?(name)
32
32
  attribute = read_raw_attribute(name)
33
33
  !attribute.blank? || attribute == false
@@ -50,9 +50,9 @@ module Mongoid
50
50
  # @example Does the document have the attribute?
51
51
  # model.has_attribute?(:name)
52
52
  #
53
- # @param [ String, Symbol ] name The name of the attribute.
53
+ # @param [ String | Symbol ] name The name of the attribute.
54
54
  #
55
- # @return [ true, false ] If the key is present in the attributes.
55
+ # @return [ true | false ] If the key is present in the attributes.
56
56
  def has_attribute?(name)
57
57
  attributes.key?(name.to_s)
58
58
  end
@@ -63,9 +63,9 @@ module Mongoid
63
63
  # @example Does the document have the attribute before it was assigned?
64
64
  # model.has_attribute_before_type_cast?(:name)
65
65
  #
66
- # @param [ String, Symbol ] name The name of the attribute.
66
+ # @param [ String | Symbol ] name The name of the attribute.
67
67
  #
68
- # @return [ true, false ] If the key is present in the
68
+ # @return [ true | false ] If the key is present in the
69
69
  # attributes_before_type_cast.
70
70
  def has_attribute_before_type_cast?(name)
71
71
  attributes_before_type_cast.key?(name.to_s)
@@ -80,16 +80,32 @@ module Mongoid
80
80
  # @example Read an attribute (alternate syntax.)
81
81
  # person[:title]
82
82
  #
83
- # @param [ String, Symbol ] name The name of the attribute to get.
83
+ # @param [ String | Symbol ] name The name of the attribute to get.
84
84
  #
85
85
  # @return [ Object ] The value of the attribute.
86
86
  def read_attribute(name)
87
87
  field = fields[name.to_s]
88
88
  raw = read_raw_attribute(name)
89
- field ? field.demongoize(raw) : raw
89
+ process_raw_attribute(name.to_s, raw, field)
90
90
  end
91
91
  alias :[] :read_attribute
92
92
 
93
+
94
+ # Process the raw attribute values just read from the documents attributes.
95
+ #
96
+ # @param [ String ] name The name of the attribute to get.
97
+ # @param [ Object ] raw The raw attribute value.
98
+ # @param [ Field | nil ] field The field to use for demongoization or nil.
99
+ #
100
+ # @return [ Object ] The value of the attribute.
101
+ #
102
+ # @api private
103
+ def process_raw_attribute(name, raw, field)
104
+ value = field ? field.demongoize(raw) : raw
105
+ attribute_will_change!(name) if value.resizable?
106
+ value
107
+ end
108
+
93
109
  # Read a value from the attributes before type cast. If the value has not
94
110
  # yet been assigned then this will return the attribute's existing value
95
111
  # using read_raw_attribute.
@@ -97,7 +113,7 @@ module Mongoid
97
113
  # @example Read an attribute before type cast.
98
114
  # person.read_attribute_before_type_cast(:price)
99
115
  #
100
- # @param [ String, Symbol ] name The name of the attribute to get.
116
+ # @param [ String | Symbol ] name The name of the attribute to get.
101
117
  #
102
118
  # @return [ Object ] The value of the attribute before type cast, if
103
119
  # available. Otherwise, the value of the attribute.
@@ -116,11 +132,12 @@ module Mongoid
116
132
  # @example Remove the attribute.
117
133
  # person.remove_attribute(:title)
118
134
  #
119
- # @param [ String, Symbol ] name The name of the attribute to remove.
135
+ # @param [ String | Symbol ] name The name of the attribute to remove.
120
136
  #
121
137
  # @raise [ Errors::ReadonlyAttribute ] If the field cannot be removed due
122
138
  # to being flagged as reaodnly.
123
139
  def remove_attribute(name)
140
+ validate_writable_field_name!(name.to_s)
124
141
  as_writable_attribute!(name) do |access|
125
142
  _assigning do
126
143
  attribute_will_change!(access)
@@ -140,9 +157,11 @@ module Mongoid
140
157
  # @example Write the attribute (alternate syntax.)
141
158
  # person[:title] = "Mr."
142
159
  #
143
- # @param [ String, Symbol ] name The name of the attribute to update.
160
+ # @param [ String | Symbol ] name The name of the attribute to update.
144
161
  # @param [ Object ] value The value to set for the attribute.
145
162
  def write_attribute(name, value)
163
+ validate_writable_field_name!(name.to_s)
164
+
146
165
  field_name = database_field_name(name)
147
166
 
148
167
  if attribute_missing?(field_name)
@@ -151,7 +170,6 @@ module Mongoid
151
170
 
152
171
  if attribute_writable?(field_name)
153
172
  _assigning do
154
- validate_attribute_value(field_name, value)
155
173
  localized = fields[field_name].try(:localized?)
156
174
  attributes_before_type_cast[name.to_s] = value
157
175
  typed_value = typed_value_for(field_name, value)
@@ -159,11 +177,22 @@ module Mongoid
159
177
  attribute_will_change!(field_name)
160
178
  end
161
179
  if localized
162
- attributes[field_name] ||= {}
163
- attributes[field_name].merge!(typed_value)
180
+ present = fields[field_name].try(:localize_present?)
181
+ loc_key, loc_val = typed_value.first
182
+ if present && loc_val.blank?
183
+ attributes[field_name]&.delete(loc_key)
184
+ else
185
+ attributes[field_name] ||= {}
186
+ attributes[field_name].merge!(typed_value)
187
+ end
164
188
  else
165
189
  attributes[field_name] = typed_value
166
190
  end
191
+
192
+ # when writing an attribute, also remove it from the unsets,
193
+ # so that removing then writing doesn't result in a removal.
194
+ delayed_atomic_unsets.delete(field_name)
195
+
167
196
  typed_value
168
197
  end
169
198
  else
@@ -214,7 +243,7 @@ module Mongoid
214
243
  #
215
244
  # @param [ String ] name The name of the attribute.
216
245
  #
217
- # @return [ true, false ] If the attribute is missing.
246
+ # @return [ true | false ] If the attribute is missing.
218
247
  def attribute_missing?(name)
219
248
  !Projector.new(__selected_fields).attribute_or_path_allowed?(name)
220
249
  end
@@ -238,7 +267,7 @@ module Mongoid
238
267
  # @example Is the string in dot syntax.
239
268
  # model.hash_dot_syntax?
240
269
  #
241
- # @return [ true, false ] If the string contains a "."
270
+ # @return [ true | false ] If the string contains a "."
242
271
  def hash_dot_syntax?(string)
243
272
  string.include?(".")
244
273
  end
@@ -248,7 +277,7 @@ module Mongoid
248
277
  # @example Get the value typecasted.
249
278
  # person.typed_value_for(:title, :sir)
250
279
  #
251
- # @param [ String, Symbol ] key The field name.
280
+ # @param [ String | Symbol ] key The field name.
252
281
  # @param [ Object ] value The uncast value.
253
282
  #
254
283
  # @return [ Object ] The cast value.
@@ -266,7 +295,11 @@ module Mongoid
266
295
  end
267
296
 
268
297
  if hash_dot_syntax?(normalized)
269
- attributes.__nested__(normalized)
298
+ if fields.key?(normalized)
299
+ attributes[normalized]
300
+ else
301
+ attributes.__nested__(normalized)
302
+ end
270
303
  else
271
304
  attributes[normalized]
272
305
  end
@@ -325,30 +358,6 @@ module Mongoid
325
358
 
326
359
  private
327
360
 
328
- # Validates an attribute value as being assignable to the specified field.
329
- #
330
- # For now, only Hash and Array fields are validated, and the value is
331
- # being checked to be of an appropriate type (i.e. either Hash or Array,
332
- # respectively, or nil).
333
- #
334
- # This method takes the name of the field as stored in the document
335
- # in the database, not (necessarily) the Ruby method name used to read/write
336
- # the said field.
337
- #
338
- # @param [ String, Symbol ] field_name The name of the field.
339
- # @param [ Object ] value The value to be validated.
340
- def validate_attribute_value(field_name, value)
341
- return if value.nil?
342
- field = fields[field_name]
343
- return unless field
344
- validatable_types = [ Hash, Array ]
345
- if validatable_types.include?(field.type)
346
- unless value.is_a?(field.type)
347
- raise Mongoid::Errors::InvalidValue.new(field.type, value.class)
348
- end
349
- end
350
- end
351
-
352
361
  def lookup_attribute_presence(name, value)
353
362
  if localized_fields.has_key?(name) && value
354
363
  value = localized_fields[name].send(:lookup, value)