mongoid 7.6.0 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data/README.md +3 -3
  4. data/Rakefile +21 -85
  5. data/lib/config/locales/en.yml +46 -30
  6. data/lib/mongoid/association/accessors.rb +32 -3
  7. data/lib/mongoid/association/bindable.rb +48 -0
  8. data/lib/mongoid/association/builders.rb +4 -2
  9. data/lib/mongoid/association/eager_loadable.rb +29 -7
  10. data/lib/mongoid/association/embedded/batchable.rb +28 -5
  11. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  12. data/lib/mongoid/association/embedded/embedded_in.rb +2 -1
  13. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  14. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  15. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +40 -18
  16. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  17. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +21 -2
  18. data/lib/mongoid/association/macros.rb +2 -1
  19. data/lib/mongoid/association/many.rb +5 -0
  20. data/lib/mongoid/association/nested/many.rb +2 -1
  21. data/lib/mongoid/association/proxy.rb +12 -0
  22. data/lib/mongoid/association/referenced/auto_save.rb +3 -2
  23. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  24. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  25. data/lib/mongoid/association/referenced/belongs_to.rb +1 -1
  26. data/lib/mongoid/association/referenced/counter_cache.rb +8 -8
  27. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +64 -11
  28. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +4 -1
  29. data/lib/mongoid/association/referenced/has_many/enumerable.rb +10 -18
  30. data/lib/mongoid/association/referenced/has_many/proxy.rb +12 -9
  31. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  32. data/lib/mongoid/association/referenced/has_one/proxy.rb +8 -11
  33. data/lib/mongoid/association/referenced/syncable.rb +2 -2
  34. data/lib/mongoid/association/relatable.rb +38 -4
  35. data/lib/mongoid/attributes/processing.rb +9 -2
  36. data/lib/mongoid/attributes.rb +30 -27
  37. data/lib/mongoid/cacheable.rb +2 -2
  38. data/lib/mongoid/changeable.rb +37 -2
  39. data/lib/mongoid/clients/options.rb +4 -0
  40. data/lib/mongoid/clients/sessions.rb +2 -14
  41. data/lib/mongoid/config.rb +15 -11
  42. data/lib/mongoid/contextual/aggregable/memory.rb +23 -15
  43. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  44. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  45. data/lib/mongoid/contextual/memory.rb +55 -28
  46. data/lib/mongoid/contextual/mongo.rb +173 -287
  47. data/lib/mongoid/contextual/none.rb +33 -15
  48. data/lib/mongoid/copyable.rb +32 -8
  49. data/lib/mongoid/criteria/includable.rb +24 -20
  50. data/lib/mongoid/criteria/marshalable.rb +10 -2
  51. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -15
  52. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  53. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  54. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  55. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  56. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -16
  57. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  58. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  59. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  60. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +1 -1
  61. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
  62. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  63. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  64. data/lib/mongoid/criteria/queryable/optional.rb +3 -9
  65. data/lib/mongoid/criteria/queryable/options.rb +1 -1
  66. data/lib/mongoid/criteria/queryable/selectable.rb +2 -24
  67. data/lib/mongoid/criteria/queryable/selector.rb +90 -5
  68. data/lib/mongoid/criteria/queryable/smash.rb +39 -6
  69. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  70. data/lib/mongoid/criteria/queryable.rb +11 -6
  71. data/lib/mongoid/criteria.rb +1 -28
  72. data/lib/mongoid/deprecable.rb +36 -0
  73. data/lib/mongoid/deprecation.rb +25 -0
  74. data/lib/mongoid/document.rb +88 -33
  75. data/lib/mongoid/equality.rb +4 -4
  76. data/lib/mongoid/errors/document_not_found.rb +6 -2
  77. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  78. data/lib/mongoid/errors/invalid_field.rb +5 -1
  79. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  80. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  81. data/lib/mongoid/errors.rb +2 -2
  82. data/lib/mongoid/extensions/array.rb +8 -6
  83. data/lib/mongoid/extensions/big_decimal.rb +29 -10
  84. data/lib/mongoid/extensions/binary.rb +42 -0
  85. data/lib/mongoid/extensions/boolean.rb +8 -2
  86. data/lib/mongoid/extensions/date.rb +26 -20
  87. data/lib/mongoid/extensions/date_time.rb +1 -1
  88. data/lib/mongoid/extensions/float.rb +4 -5
  89. data/lib/mongoid/extensions/hash.rb +12 -5
  90. data/lib/mongoid/extensions/integer.rb +4 -5
  91. data/lib/mongoid/extensions/object.rb +2 -0
  92. data/lib/mongoid/extensions/range.rb +41 -10
  93. data/lib/mongoid/extensions/regexp.rb +11 -4
  94. data/lib/mongoid/extensions/set.rb +11 -4
  95. data/lib/mongoid/extensions/string.rb +2 -13
  96. data/lib/mongoid/extensions/symbol.rb +3 -14
  97. data/lib/mongoid/extensions/time.rb +27 -16
  98. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  99. data/lib/mongoid/extensions.rb +1 -0
  100. data/lib/mongoid/factory.rb +42 -7
  101. data/lib/mongoid/fields/foreign_key.rb +7 -0
  102. data/lib/mongoid/fields/validators/macro.rb +3 -9
  103. data/lib/mongoid/fields.rb +49 -7
  104. data/lib/mongoid/findable.rb +21 -16
  105. data/lib/mongoid/indexable/specification.rb +1 -1
  106. data/lib/mongoid/indexable/validators/options.rb +4 -1
  107. data/lib/mongoid/interceptable.rb +69 -9
  108. data/lib/mongoid/persistable/creatable.rb +14 -5
  109. data/lib/mongoid/persistable/updatable.rb +12 -5
  110. data/lib/mongoid/persistence_context.rb +8 -42
  111. data/lib/mongoid/query_cache.rb +6 -258
  112. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  113. data/lib/mongoid/reloadable.rb +7 -3
  114. data/lib/mongoid/scopable.rb +9 -11
  115. data/lib/mongoid/selectable.rb +1 -2
  116. data/lib/mongoid/shardable.rb +11 -35
  117. data/lib/mongoid/stateful.rb +27 -1
  118. data/lib/mongoid/timestamps/created.rb +1 -1
  119. data/lib/mongoid/timestamps/updated.rb +1 -1
  120. data/lib/mongoid/touchable.rb +2 -3
  121. data/lib/mongoid/traversable.rb +1 -0
  122. data/lib/mongoid/validatable/uniqueness.rb +2 -1
  123. data/lib/mongoid/version.rb +1 -5
  124. data/lib/mongoid/warnings.rb +3 -4
  125. data/lib/mongoid.rb +1 -0
  126. data/spec/config/mongoid.yml +16 -0
  127. data/spec/integration/app_spec.rb +8 -12
  128. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  129. data/spec/integration/associations/embedded_spec.rb +15 -0
  130. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  131. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  132. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  133. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  134. data/spec/integration/associations/has_one_spec.rb +97 -1
  135. data/spec/integration/associations/scope_option_spec.rb +1 -1
  136. data/spec/integration/callbacks_models.rb +95 -1
  137. data/spec/integration/callbacks_spec.rb +226 -4
  138. data/spec/integration/criteria/range_spec.rb +95 -1
  139. data/spec/integration/discriminator_key_spec.rb +115 -76
  140. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  141. data/spec/integration/i18n_fallbacks_spec.rb +1 -15
  142. data/spec/integration/matcher_examples_spec.rb +20 -13
  143. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  144. data/spec/integration/matcher_operator_spec.rb +3 -5
  145. data/spec/integration/persistence/range_field_spec.rb +350 -0
  146. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  147. data/spec/mongoid/association/depending_spec.rb +9 -9
  148. data/spec/mongoid/association/eager_spec.rb +2 -1
  149. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  150. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  151. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  152. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  153. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +198 -8
  154. data/spec/mongoid/association/embedded/embeds_many_models.rb +36 -0
  155. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  156. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  157. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  158. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  159. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  160. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  161. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  162. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  163. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  164. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  165. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +38 -5
  166. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  167. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  168. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  169. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  170. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +62 -13
  171. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  172. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  173. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  174. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  175. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  176. data/spec/mongoid/association/syncable_spec.rb +14 -0
  177. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  178. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  179. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  180. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  181. data/spec/mongoid/attributes_spec.rb +480 -27
  182. data/spec/mongoid/cacheable_spec.rb +3 -3
  183. data/spec/mongoid/changeable_spec.rb +130 -13
  184. data/spec/mongoid/clients/factory_spec.rb +23 -30
  185. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  186. data/spec/mongoid/clients_spec.rb +2 -2
  187. data/spec/mongoid/config_spec.rb +52 -15
  188. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  189. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  190. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  191. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  192. data/spec/mongoid/contextual/memory_spec.rb +521 -14
  193. data/spec/mongoid/contextual/mongo_spec.rb +566 -426
  194. data/spec/mongoid/contextual/none_spec.rb +11 -19
  195. data/spec/mongoid/copyable_spec.rb +451 -2
  196. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  197. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  198. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  199. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  200. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  201. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  202. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +1 -2
  203. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  204. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  205. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +1 -2
  206. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  207. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  208. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  209. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  210. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  211. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  212. data/spec/mongoid/criteria/queryable/selectable_spec.rb +77 -85
  213. data/spec/mongoid/criteria/queryable/selector_spec.rb +16 -77
  214. data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
  215. data/spec/mongoid/criteria_spec.rb +469 -1201
  216. data/spec/mongoid/document_fields_spec.rb +173 -24
  217. data/spec/mongoid/document_spec.rb +32 -41
  218. data/spec/mongoid/equality_spec.rb +12 -12
  219. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  220. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  221. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  222. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  223. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  224. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  225. data/spec/mongoid/extensions/array_spec.rb +16 -2
  226. data/spec/mongoid/extensions/big_decimal_spec.rb +697 -212
  227. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  228. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  229. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  230. data/spec/mongoid/extensions/date_spec.rb +71 -1
  231. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  232. data/spec/mongoid/extensions/float_spec.rb +48 -76
  233. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  234. data/spec/mongoid/extensions/integer_spec.rb +45 -66
  235. data/spec/mongoid/extensions/range_spec.rb +255 -54
  236. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  237. data/spec/mongoid/extensions/set_spec.rb +106 -0
  238. data/spec/mongoid/extensions/string_spec.rb +53 -25
  239. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  240. data/spec/mongoid/extensions/time_spec.rb +634 -66
  241. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  242. data/spec/mongoid/factory_spec.rb +61 -1
  243. data/spec/mongoid/fields_spec.rb +321 -50
  244. data/spec/mongoid/findable_spec.rb +64 -29
  245. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  246. data/spec/mongoid/indexable_spec.rb +16 -19
  247. data/spec/mongoid/interceptable_spec.rb +584 -5
  248. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  249. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  250. data/spec/mongoid/mongoizable_spec.rb +285 -0
  251. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  252. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  253. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  254. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  255. data/spec/mongoid/persistence_context_spec.rb +24 -0
  256. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  257. data/spec/mongoid/query_cache_spec.rb +1 -156
  258. data/spec/mongoid/reloadable_spec.rb +35 -2
  259. data/spec/mongoid/scopable_spec.rb +36 -34
  260. data/spec/mongoid/serializable_spec.rb +14 -7
  261. data/spec/mongoid/shardable_models.rb +0 -14
  262. data/spec/mongoid/shardable_spec.rb +61 -153
  263. data/spec/mongoid/stateful_spec.rb +28 -0
  264. data/spec/mongoid/timestamps_spec.rb +390 -0
  265. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  266. data/spec/mongoid/touchable_spec.rb +116 -0
  267. data/spec/mongoid/touchable_spec_models.rb +12 -8
  268. data/spec/mongoid/traversable_spec.rb +4 -11
  269. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  270. data/spec/mongoid/validatable/uniqueness_spec.rb +60 -31
  271. data/spec/mongoid/warnings_spec.rb +35 -0
  272. data/spec/mongoid_spec.rb +1 -7
  273. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  274. data/spec/rails/mongoid_spec.rb +4 -16
  275. data/spec/shared/lib/mrss/docker_runner.rb +1 -8
  276. data/spec/shared/lib/mrss/event_subscriber.rb +5 -15
  277. data/spec/shared/lib/mrss/lite_constraints.rb +2 -10
  278. data/spec/shared/lib/mrss/server_version_registry.rb +24 -17
  279. data/spec/shared/lib/mrss/spec_organizer.rb +3 -32
  280. data/spec/shared/lib/mrss/utils.rb +6 -28
  281. data/spec/shared/share/Dockerfile.erb +107 -33
  282. data/spec/shared/shlib/distro.sh +0 -10
  283. data/spec/shared/shlib/server.sh +33 -64
  284. data/spec/shared/shlib/set_env.sh +71 -12
  285. data/spec/support/constraints.rb +24 -0
  286. data/spec/support/expectations.rb +17 -20
  287. data/spec/support/macros.rb +30 -0
  288. data/spec/support/models/augmentation.rb +12 -0
  289. data/spec/support/models/band.rb +3 -0
  290. data/spec/support/models/catalog.rb +24 -0
  291. data/spec/support/models/circus.rb +3 -0
  292. data/spec/support/models/fanatic.rb +8 -0
  293. data/spec/support/models/implant.rb +9 -0
  294. data/spec/support/models/label.rb +2 -0
  295. data/spec/support/models/passport.rb +9 -0
  296. data/spec/support/models/person.rb +1 -0
  297. data/spec/support/models/player.rb +2 -0
  298. data/spec/support/models/powerup.rb +12 -0
  299. data/spec/support/models/registry.rb +1 -0
  300. data/spec/support/models/school.rb +14 -0
  301. data/spec/support/models/shield.rb +18 -0
  302. data/spec/support/models/student.rb +14 -0
  303. data/spec/support/models/weapon.rb +12 -0
  304. data.tar.gz.sig +0 -0
  305. metadata +695 -641
  306. metadata.gz.sig +0 -0
  307. data/lib/mongoid/errors/eager_load.rb +0 -23
  308. data/lib/mongoid/errors/invalid_value.rb +0 -17
  309. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
  310. data/spec/shared/CANDIDATE.md +0 -28
  311. data/spec/shared/lib/mrss/release/candidate.rb +0 -281
  312. data/spec/shared/lib/mrss/release/product_data.rb +0 -144
  313. data/spec/shared/lib/tasks/candidate.rake +0 -64
@@ -242,7 +242,7 @@ 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.
@@ -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
 
@@ -43,11 +43,18 @@ module Mongoid
43
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)
46
+
47
+ aliased = if aliased_associations.key?(name)
48
+ aliased_associations[name]
49
+ else
50
+ name
51
+ end
52
+
53
+ if relations.has_key?(aliased)
47
54
  pending_relations[name] = value
48
55
  return true
49
56
  end
50
- if nested_attributes.has_key?(name)
57
+ if nested_attributes.has_key?(aliased)
51
58
  pending_nested[name] = value
52
59
  return true
53
60
  end
@@ -86,10 +86,26 @@ module Mongoid
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.
@@ -121,6 +137,7 @@ module Mongoid
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)
@@ -143,6 +160,8 @@ module Mongoid
143
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)
@@ -164,6 +182,11 @@ module Mongoid
164
182
  else
165
183
  attributes[field_name] = typed_value
166
184
  end
185
+
186
+ # when writing an attribute, also remove it from the unsets,
187
+ # so that removing then writing doesn't result in a removal.
188
+ delayed_atomic_unsets.delete(field_name)
189
+
167
190
  typed_value
168
191
  end
169
192
  else
@@ -266,7 +289,11 @@ module Mongoid
266
289
  end
267
290
 
268
291
  if hash_dot_syntax?(normalized)
269
- attributes.__nested__(normalized)
292
+ if fields.key?(normalized)
293
+ attributes[normalized]
294
+ else
295
+ attributes.__nested__(normalized)
296
+ end
270
297
  else
271
298
  attributes[normalized]
272
299
  end
@@ -325,30 +352,6 @@ module Mongoid
325
352
 
326
353
  private
327
354
 
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
355
  def lookup_attribute_presence(name, value)
353
356
  if localized_fields.has_key?(name) && value
354
357
  value = localized_fields[name].send(:lookup, value)
@@ -15,7 +15,7 @@ module Mongoid
15
15
  # plural model name.
16
16
  #
17
17
  # If new_record? - will append /new
18
- # If not - will append /id-updated_at.to_formatted_s(cache_timestamp_format)
18
+ # If not - will append /id-updated_at.to_s(cache_timestamp_format)
19
19
  # Without updated_at - will append /id
20
20
  #
21
21
  # This is usually called inside a cache() block
@@ -26,7 +26,7 @@ module Mongoid
26
26
  # @return [ String ] the string with or without updated_at
27
27
  def cache_key
28
28
  return "#{model_key}/new" if new_record?
29
- return "#{model_key}/#{_id}-#{updated_at.utc.to_formatted_s(cache_timestamp_format)}" if do_or_do_not(:updated_at)
29
+ return "#{model_key}/#{_id}-#{updated_at.utc.to_s(cache_timestamp_format)}" if do_or_do_not(:updated_at)
30
30
  "#{model_key}/#{_id}"
31
31
  end
32
32
  end
@@ -62,13 +62,14 @@ module Mongoid
62
62
 
63
63
  # Call this method after save, so the changes can be properly switched.
64
64
  #
65
- # This will unset the memoized children array, set new record to
65
+ # This will unset the memoized children array, set new record flag to
66
66
  # false, set the document as validated, and move the dirty changes.
67
67
  #
68
68
  # @example Move the changes to previous.
69
69
  # person.move_changes
70
70
  def move_changes
71
71
  @previous_changes = changes
72
+ @previous_attributes = attributes.dup
72
73
  Atomic::UPDATES.each do |update|
73
74
  send(update).clear
74
75
  end
@@ -81,6 +82,7 @@ module Mongoid
81
82
  # document.post_persist
82
83
  def post_persist
83
84
  reset_persisted_descendants
85
+ reset_attributes_before_type_cast
84
86
  move_changes
85
87
  end
86
88
 
@@ -133,6 +135,13 @@ module Mongoid
133
135
 
134
136
  private
135
137
 
138
+ # Get attributes of the document before the document was saved.
139
+ #
140
+ # @return [ Hash ] Previous attributes
141
+ def previous_attributes
142
+ @previous_attributes ||= {}
143
+ end
144
+
136
145
  # Get the old and new value for the provided attribute.
137
146
  #
138
147
  # @example Get the attribute change.
@@ -185,6 +194,25 @@ module Mongoid
185
194
  attribute_changed?(attr) ? changed_attributes[attr] : attributes[attr]
186
195
  end
187
196
 
197
+ # Get the previous attribute value that was changed
198
+ # before the document was saved.
199
+ #
200
+ # It the document has not been saved yet, or was just loaded from database,
201
+ # this method returns nil for all attributes.
202
+ #
203
+ # @param [ String ] attr The attribute name.
204
+ #
205
+ # @return [ Object | nil ] Attribute value before the document was saved,
206
+ # or nil if the document has not been saved yet.
207
+ def attribute_previously_was(attr)
208
+ attr = database_field_name(attr)
209
+ if previous_changes.key?(attr)
210
+ previous_changes[attr].first
211
+ else
212
+ previous_attributes[attr]
213
+ end
214
+ end
215
+
188
216
  # Flag an attribute as going to change.
189
217
  #
190
218
  # @example Flag the attribute.
@@ -221,6 +249,10 @@ module Mongoid
221
249
  end
222
250
  end
223
251
 
252
+ def reset_attributes_before_type_cast
253
+ @attributes_before_type_cast = @attributes.dup
254
+ end
255
+
224
256
  module ClassMethods
225
257
 
226
258
  private
@@ -291,7 +323,7 @@ module Mongoid
291
323
  end
292
324
  end
293
325
 
294
- # Creates the dirty change previous value accessor.
326
+ # Creates the dirty change previous value accessors.
295
327
  #
296
328
  # @example Create the accessor.
297
329
  # Model.create_dirty_previous_value_accessor("name", "alias")
@@ -303,6 +335,9 @@ module Mongoid
303
335
  re_define_method("#{meth}_was") do
304
336
  attribute_was(name)
305
337
  end
338
+ re_define_method("#{meth}_previously_was") do
339
+ attribute_previously_was(name)
340
+ end
306
341
  end
307
342
  end
308
343
 
@@ -45,6 +45,10 @@ module Mongoid
45
45
  PersistenceContext.new(self.class)
46
46
  end
47
47
 
48
+ def persistence_context?
49
+ !!(PersistenceContext.get(self) || PersistenceContext.get(self.class))
50
+ end
51
+
48
52
  private
49
53
 
50
54
  def set_persistence_context(options_or_context)
@@ -43,13 +43,7 @@ module Mongoid
43
43
  Threaded.set_session(session)
44
44
  yield(session)
45
45
  rescue Mongo::Error::InvalidSession => ex
46
- if
47
- # Driver 2.13.0+
48
- defined?(Mongo::Error::SessionsNotSupported) &&
49
- Mongo::Error::SessionsNotSupported === ex ||
50
- # Legacy drivers
51
- ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
52
- then
46
+ if Mongo::Error::SessionsNotSupported === ex
53
47
  raise Mongoid::Errors::InvalidSessionUse.new(:sessions_not_supported)
54
48
  end
55
49
  raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_use)
@@ -100,13 +94,7 @@ module Mongoid
100
94
  Threaded.set_session(session)
101
95
  yield(session)
102
96
  rescue Mongo::Error::InvalidSession => ex
103
- if
104
- # Driver 2.13.0+
105
- defined?(Mongo::Error::SessionsNotSupported) &&
106
- Mongo::Error::SessionsNotSupported === ex ||
107
- # Legacy drivers
108
- ex.message == Mongo::Session::SESSIONS_NOT_SUPPORTED
109
- then
97
+ if Mongo::Error::SessionsNotSupported === ex
110
98
  raise Mongoid::Errors::InvalidSessionUse.new(:sessions_not_supported)
111
99
  end
112
100
  raise Mongoid::Errors::InvalidSessionUse.new(:invalid_session_use)
@@ -75,52 +75,55 @@ module Mongoid
75
75
  # Return stored times as UTC.
76
76
  option :use_utc, default: false
77
77
 
78
+ # Store BigDecimals as Decimal128s instead of strings in the db.
79
+ option :map_big_decimal_to_decimal128, default: true
80
+
78
81
  # Update embedded documents correctly when setting it, unsetting it
79
82
  # and resetting it. See MONGOID-5206 and MONGOID-5240 for more details.
80
- option :broken_updates, default: true
83
+ option :broken_updates, default: false
81
84
 
82
85
  # Maintain legacy behavior of === on Mongoid documents, which returns
83
86
  # true in a number of cases where Ruby's === implementation would
84
87
  # return false.
85
- option :legacy_triple_equals, default: true
88
+ option :legacy_triple_equals, default: false
86
89
 
87
90
  # When exiting a nested `with_scope' block, set the current scope to
88
91
  # nil instead of the parent scope for backwards compatibility.
89
- option :broken_scoping, default: true
92
+ option :broken_scoping, default: false
90
93
 
91
94
  # Maintain broken behavior of sum over empty result sets for backwards
92
95
  # compatibility.
93
- option :broken_aggregables, default: true
96
+ option :broken_aggregables, default: false
94
97
 
95
98
  # Ignore aliased fields in embedded documents when performing pluck and
96
99
  # distinct operations, for backwards compatibility.
97
- option :broken_alias_handling, default: true
100
+ option :broken_alias_handling, default: false
98
101
 
99
102
  # Maintain broken `and' behavior when using the same operator on the same
100
103
  # field multiple times for backwards compatibility.
101
- option :broken_and, default: true
104
+ option :broken_and, default: false
102
105
 
103
106
  # Use millisecond precision when comparing Time objects with the _matches?
104
107
  # function.
105
- option :compare_time_by_ms, default: false
108
+ option :compare_time_by_ms, default: true
106
109
 
107
110
  # Use bson-ruby's implementation of as_json for BSON::ObjectId instead of
108
111
  # the one monkey-patched into Mongoid.
109
- option :object_id_as_json_oid, default: true
112
+ option :object_id_as_json_oid, default: false
110
113
 
111
114
  # Maintain legacy behavior of pluck and distinct, which does not
112
115
  # demongoize the values on returning them.
113
- option :legacy_pluck_distinct, default: true
116
+ option :legacy_pluck_distinct, default: false
114
117
 
115
118
  # Combine chained operators, which use the same field and operator,
116
119
  # using and's instead of overwriting them.
117
- option :overwrite_chained_operators, default: true
120
+ option :overwrite_chained_operators, default: false
118
121
 
119
122
  # When this flag is true, the attributes method on a document will return
120
123
  # a BSON::Document when that document is retrieved from the database, and
121
124
  # a Hash otherwise. When this flag is false, the attributes method will
122
125
  # always return a Hash.
123
- option :legacy_attributes, default: true
126
+ option :legacy_attributes, default: false
124
127
 
125
128
  # Has Mongoid been configured? This is checking that at least a valid
126
129
  # client config exists.
@@ -213,6 +216,7 @@ module Mongoid
213
216
  configuration = settings.with_indifferent_access
214
217
  self.options = configuration[:options]
215
218
  self.clients = configuration[:clients]
219
+ Mongo.options = configuration[:driver_options] || {}
216
220
  set_log_levels
217
221
  end
218
222
 
@@ -27,9 +27,13 @@ module Mongoid
27
27
  #
28
28
  # @param [ Symbol ] field The field to average.
29
29
  #
30
- # @return [ Float ] The average.
30
+ # @return [ Numeric ] The average.
31
31
  def avg(field)
32
- count > 0 ? sum(field).to_f / count.to_f : nil
32
+ total = count { |doc| !doc.send(field).nil? }
33
+ return nil unless total > 0
34
+
35
+ total = total.to_f if total.is_a?(Integer)
36
+ sum(field) / total
33
37
  end
34
38
 
35
39
  # Get the max value of the provided field. If provided a block, will
@@ -46,10 +50,12 @@ module Mongoid
46
50
  #
47
51
  # @param [ Symbol ] field The field to max.
48
52
  #
49
- # @return [ Float, Document ] The max value or document with the max
53
+ # @return [ Numeric | Document ] The max value or document with the max
50
54
  # value.
51
55
  def max(field = nil)
52
- block_given? ? super() : aggregate_by(field, :max_by)
56
+ return super() if block_given?
57
+
58
+ aggregate_by(field, :max)
53
59
  end
54
60
 
55
61
  # Get the min value of the provided field. If provided a block, will
@@ -66,10 +72,12 @@ module Mongoid
66
72
  #
67
73
  # @param [ Symbol ] field The field to min.
68
74
  #
69
- # @return [ Float, Document ] The min value or document with the min
75
+ # @return [ Numeric | Document ] The min value or document with the min
70
76
  # value.
71
77
  def min(field = nil)
72
- block_given? ? super() : aggregate_by(field, :min_by)
78
+ return super() if block_given?
79
+
80
+ aggregate_by(field, :min)
73
81
  end
74
82
 
75
83
  # Get the sum value of the provided field. If provided a block, will
@@ -83,13 +91,11 @@ module Mongoid
83
91
  #
84
92
  # @param [ Symbol ] field The field to sum.
85
93
  #
86
- # @return [ Float ] The sum value.
94
+ # @return [ Numeric ] The sum value.
87
95
  def sum(field = nil)
88
- if block_given?
89
- super()
90
- else
91
- count > 0 ? super(0) { |doc| doc.public_send(field) } : 0
92
- end
96
+ return super() if block_given?
97
+
98
+ aggregate_by(field, :sum) || 0
93
99
  end
94
100
 
95
101
  private
@@ -99,14 +105,16 @@ module Mongoid
99
105
  # @api private
100
106
  #
101
107
  # @example Aggregate by the field and method.
102
- # aggregable.aggregate_by(:name, :min_by)
108
+ # aggregable.aggregate_by(:likes, :min_by)
103
109
  #
104
110
  # @param [ Symbol ] field The field to aggregate on.
105
111
  # @param [ Symbol ] method The method (min_by or max_by).
106
112
  #
107
- # @return [ Integer ] The aggregate.
113
+ # @return [ Numeric | nil ] The aggregate.
108
114
  def aggregate_by(field, method)
109
- count > 0 ? send(method) { |doc| doc.public_send(field) }.public_send(field) : nil
115
+ return nil unless any?
116
+
117
+ map { |doc| doc.public_send(field) }.compact.public_send(method)
110
118
  end
111
119
  end
112
120
  end
@@ -26,7 +26,7 @@ module Mongoid
26
26
  # If no documents are found, then returned Hash will have
27
27
  # count, sum of 0 and max, min, avg of nil.
28
28
  def aggregates(field)
29
- result = collection.find.aggregate(pipeline(field), session: _session).to_a
29
+ result = collection.aggregate(pipeline(field), session: _session).to_a
30
30
  if result.empty?
31
31
  if Mongoid.broken_aggregables
32
32
  { "count" => 0, "sum" => nil, "avg" => nil, "min" => nil, "max" => nil }
@@ -121,7 +121,7 @@ module Mongoid
121
121
  # @return [ MapReduce ] The map/reduce object.
122
122
  def out(location)
123
123
  normalized = location.dup
124
- normalized.update_values do |value|
124
+ normalized.transform_values! do |value|
125
125
  value.is_a?(::Symbol) ? value.to_s : value
126
126
  end
127
127
  @map_reduce = @map_reduce.out(normalized)
@@ -147,7 +147,7 @@ module Mongoid
147
147
  def raw
148
148
  validate_out!
149
149
  cmd = command
150
- opts = { read: cmd.delete(:read) } if cmd[:read]
150
+ opts = { read: criteria.options.fetch(:read) } if criteria.options[:read]
151
151
  @map_reduce.database.command(cmd, (opts || {}).merge(session: _session)).first
152
152
  end
153
153
  alias :results :raw
@@ -74,7 +74,7 @@ module Mongoid
74
74
  # @example Get the distinct values.
75
75
  # context.distinct(:name)
76
76
  #
77
- # @param [ String, Symbol ] field The name of the field.
77
+ # @param [ String | Symbol ] field The name of the field.
78
78
  #
79
79
  # @return [ Array<Object> ] The distinct values for the field.
80
80
  def distinct(field)
@@ -112,7 +112,7 @@ module Mongoid
112
112
  #
113
113
  # @return [ true, false ] If the count is more than zero.
114
114
  def exists?
115
- count > 0
115
+ any?
116
116
  end
117
117
 
118
118
  # Get the first document in the database for the criteria's selector.
@@ -120,15 +120,14 @@ module Mongoid
120
120
  # @example Get the first document.
121
121
  # context.first
122
122
  #
123
- # @param [ Integer | Hash ] limit_or_opts The number of documents to
124
- # return, or a hash of options.
123
+ # @param [ Integer ] limit The number of documents to return.
125
124
  #
126
125
  # @return [ Document ] The first document.
127
- def first(limit_or_opts = nil)
128
- if limit_or_opts.nil? || limit_or_opts.is_a?(Hash)
129
- eager_load([documents.first]).first
126
+ def first(limit = nil)
127
+ if limit
128
+ eager_load(documents.first(limit))
130
129
  else
131
- eager_load(documents.first(limit_or_opts))
130
+ eager_load([documents.first]).first
132
131
  end
133
132
  end
134
133
  alias :one :first
@@ -170,18 +169,14 @@ module Mongoid
170
169
  # @example Get the last document.
171
170
  # context.last
172
171
  #
173
- # @param [ Integer | Hash ] limit_or_opts The number of documents to
174
- # return, or a hash of options.
175
- #
176
- # @option limit_or_opts [ :none ] :id_sort This option is deprecated.
177
- # Don't apply a sort on _id if no other sort is defined on the criteria.
172
+ # @param [ Integer ] limit The number of documents to return.
178
173
  #
179
174
  # @return [ Document ] The last document.
180
- def last(limit_or_opts = nil)
181
- if limit_or_opts.nil? || limit_or_opts.is_a?(Hash)
182
- eager_load([documents.last]).first
175
+ def last(limit = nil)
176
+ if limit
177
+ eager_load(documents.last(limit))
183
178
  else
184
- eager_load(documents.last(limit_or_opts))
179
+ eager_load([documents.last]).first
185
180
  end
186
181
  end
187
182
 
@@ -236,28 +231,44 @@ module Mongoid
236
231
  #
237
232
  # @param [ Integer ] value The number of documents to return.
238
233
  #
239
- # @return [ Mongo ] The context.
234
+ # @return [ Memory ] The context.
240
235
  def limit(value)
241
236
  self.limiting = value
242
237
  self
243
238
  end
244
239
 
240
+ # Pluck the field values in memory.
241
+ #
242
+ # @example Get the values in memory.
243
+ # context.pluck(:name)
244
+ #
245
+ # @param [ String | Symbol ] *fields Field(s) to pluck.
246
+ #
247
+ # @return [ Array ] The array of plucked values.
245
248
  def pluck(*fields)
246
249
  if Mongoid.legacy_pluck_distinct
247
250
  documents.pluck(*fields)
248
251
  else
249
- documents.map do |d|
250
- if fields.length == 1
251
- retrieve_value_at_path(d, fields.first)
252
- else
253
- fields.map do |field|
254
- retrieve_value_at_path(d, field)
255
- end
256
- end
252
+ documents.map do |doc|
253
+ pluck_from_doc(doc, *fields)
257
254
  end
258
255
  end
259
256
  end
260
257
 
258
+ # Pick the field values in memory.
259
+ #
260
+ # @example Get the values in memory.
261
+ # context.pick(:name)
262
+ #
263
+ # @param [ String | Symbol ] *fields Field(s) to pick.
264
+ #
265
+ # @return [ Object, Array<Object> ] The picked values.
266
+ def pick(*fields)
267
+ if doc = documents.first
268
+ pluck_from_doc(doc, *fields)
269
+ end
270
+ end
271
+
261
272
  # Tally the field values in memory.
262
273
  #
263
274
  # @example Get the counts of values in memory.
@@ -281,7 +292,7 @@ module Mongoid
281
292
  #
282
293
  # @param [ Integer ] value The number of documents to skip.
283
294
  #
284
- # @return [ Mongo ] The context.
295
+ # @return [ Memory ] The context.
285
296
  def skip(value)
286
297
  self.skipping = value
287
298
  self
@@ -295,7 +306,7 @@ module Mongoid
295
306
  # @param [ Hash ] values The sorting values as field/direction(1/-1)
296
307
  # pairs.
297
308
  #
298
- # @return [ Mongo ] The context.
309
+ # @return [ Memory ] The context.
299
310
  def sort(values)
300
311
  in_place_sort(values) and self
301
312
  end
@@ -546,6 +557,22 @@ module Mongoid
546
557
  retrieve_value_at_path(curr, remaining)
547
558
  end
548
559
  end
560
+
561
+ # Pluck the field values from the given document.
562
+ #
563
+ # @param [ Document ] doc The document to pluck from.
564
+ # @param [ String | Symbol ] *fields Field(s) to pluck.
565
+ #
566
+ # @return [ Object, Array<Object> ] The plucked values.
567
+ def pluck_from_doc(doc, *fields)
568
+ if fields.length == 1
569
+ retrieve_value_at_path(doc, fields.first)
570
+ else
571
+ fields.map do |field|
572
+ retrieve_value_at_path(doc, field)
573
+ end
574
+ end
575
+ end
549
576
  end
550
577
  end
551
578
  end