mongoid 6.4.2 → 7.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (318) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/config/locales/en.yml +17 -0
  4. data/lib/mongoid/association/accessors.rb +339 -0
  5. data/lib/mongoid/{relations/binding.rb → association/bindable.rb} +32 -52
  6. data/lib/mongoid/association/builders.rb +92 -0
  7. data/lib/mongoid/{relations/constraint.rb → association/constrainable.rb} +11 -22
  8. data/lib/mongoid/association/depending.rb +137 -0
  9. data/lib/mongoid/{relations/eager.rb → association/eager_loadable.rb} +11 -11
  10. data/lib/mongoid/{relations → association}/embedded/batchable.rb +19 -19
  11. data/lib/mongoid/association/embedded/cyclic.rb +109 -0
  12. data/lib/mongoid/association/embedded/embedded_in/binding.rb +56 -0
  13. data/lib/mongoid/{relations/builders/embedded/in.rb → association/embedded/embedded_in/buildable.rb} +12 -6
  14. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +121 -0
  15. data/lib/mongoid/association/embedded/embedded_in.rb +154 -0
  16. data/lib/mongoid/{relations/bindings/embedded/many.rb → association/embedded/embeds_many/binding.rb} +11 -9
  17. data/lib/mongoid/{relations/builders/embedded/many.rb → association/embedded/embeds_many/buildable.rb} +13 -7
  18. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +552 -0
  19. data/lib/mongoid/association/embedded/embeds_many.rb +210 -0
  20. data/lib/mongoid/{relations/bindings/embedded/one.rb → association/embedded/embeds_one/binding.rb} +12 -10
  21. data/lib/mongoid/{relations/builders/embedded/one.rb → association/embedded/embeds_one/buildable.rb} +13 -7
  22. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +130 -0
  23. data/lib/mongoid/association/embedded/embeds_one.rb +173 -0
  24. data/lib/mongoid/association/embedded.rb +4 -0
  25. data/lib/mongoid/association/macros.rb +204 -0
  26. data/lib/mongoid/{relations → association}/many.rb +19 -49
  27. data/lib/mongoid/{relations → association}/marshalable.rb +6 -4
  28. data/lib/mongoid/association/nested/many.rb +200 -0
  29. data/lib/mongoid/association/nested/nested_buildable.rb +72 -0
  30. data/lib/mongoid/association/nested/one.rb +127 -0
  31. data/lib/mongoid/association/nested.rb +15 -0
  32. data/lib/mongoid/{relations → association}/one.rb +6 -6
  33. data/lib/mongoid/association/options.rb +152 -0
  34. data/lib/mongoid/{relations → association}/proxy.rb +31 -58
  35. data/lib/mongoid/association/referenced/auto_save.rb +79 -0
  36. data/lib/mongoid/association/referenced/belongs_to/binding.rb +87 -0
  37. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +46 -0
  38. data/lib/mongoid/association/referenced/belongs_to/eager.rb +36 -0
  39. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +136 -0
  40. data/lib/mongoid/association/referenced/belongs_to.rb +248 -0
  41. data/lib/mongoid/association/referenced/counter_cache.rb +163 -0
  42. data/lib/mongoid/association/referenced/eager.rb +162 -0
  43. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +71 -0
  44. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +40 -0
  45. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +52 -0
  46. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +312 -0
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +290 -0
  48. data/lib/mongoid/{relations/bindings/referenced/many.rb → association/referenced/has_many/binding.rb} +6 -5
  49. data/lib/mongoid/association/referenced/has_many/buildable.rb +38 -0
  50. data/lib/mongoid/association/referenced/has_many/eager.rb +43 -0
  51. data/lib/mongoid/association/referenced/has_many/enumerable.rb +510 -0
  52. data/lib/mongoid/association/referenced/has_many/proxy.rb +578 -0
  53. data/lib/mongoid/association/referenced/has_many.rb +275 -0
  54. data/lib/mongoid/{relations/bindings/referenced/one.rb → association/referenced/has_one/binding.rb} +11 -8
  55. data/lib/mongoid/association/referenced/has_one/buildable.rb +60 -0
  56. data/lib/mongoid/association/referenced/has_one/eager.rb +35 -0
  57. data/lib/mongoid/{relations/builders/nested_attributes/one.rb → association/referenced/has_one/nested_builder.rb} +9 -9
  58. data/lib/mongoid/association/referenced/has_one/proxy.rb +113 -0
  59. data/lib/mongoid/association/referenced/has_one.rb +204 -0
  60. data/lib/mongoid/association/referenced/syncable.rb +170 -0
  61. data/lib/mongoid/association/referenced.rb +7 -0
  62. data/lib/mongoid/{relations → association}/reflections.rb +21 -17
  63. data/lib/mongoid/association/relatable.rb +509 -0
  64. data/lib/mongoid/{relations.rb → association.rb} +57 -56
  65. data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
  66. data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
  67. data/lib/mongoid/atomic.rb +4 -4
  68. data/lib/mongoid/attributes/dynamic.rb +2 -2
  69. data/lib/mongoid/attributes/nested.rb +22 -11
  70. data/lib/mongoid/attributes/processing.rb +2 -2
  71. data/lib/mongoid/attributes/readonly.rb +2 -4
  72. data/lib/mongoid/attributes.rb +22 -13
  73. data/lib/mongoid/changeable.rb +1 -1
  74. data/lib/mongoid/clients/options.rb +7 -5
  75. data/lib/mongoid/composable.rb +4 -4
  76. data/lib/mongoid/config.rb +1 -0
  77. data/lib/mongoid/contextual/atomic.rb +1 -1
  78. data/lib/mongoid/contextual/geo_near.rb +1 -1
  79. data/lib/mongoid/contextual/memory.rb +21 -3
  80. data/lib/mongoid/contextual/mongo.rb +10 -8
  81. data/lib/mongoid/copyable.rb +7 -6
  82. data/lib/mongoid/criteria/includable.rb +14 -14
  83. data/lib/mongoid/criteria/modifiable.rb +8 -14
  84. data/lib/mongoid/criteria/options.rb +2 -2
  85. data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -1
  86. data/lib/mongoid/criteria/queryable/pipeline.rb +10 -5
  87. data/lib/mongoid/criteria/queryable/selectable.rb +37 -7
  88. data/lib/mongoid/criteria.rb +2 -2
  89. data/lib/mongoid/document.rb +15 -6
  90. data/lib/mongoid/errors/invalid_dependent_strategy.rb +32 -0
  91. data/lib/mongoid/errors/invalid_relation_option.rb +29 -0
  92. data/lib/mongoid/errors/unknown_model.rb +25 -0
  93. data/lib/mongoid/errors.rb +3 -0
  94. data/lib/mongoid/extensions/array.rb +5 -5
  95. data/lib/mongoid/extensions/big_decimal.rb +1 -1
  96. data/lib/mongoid/extensions/hash.rb +5 -2
  97. data/lib/mongoid/extensions/object.rb +4 -4
  98. data/lib/mongoid/extensions/range.rb +1 -0
  99. data/lib/mongoid/extensions/regexp.rb +1 -0
  100. data/lib/mongoid/extensions.rb +0 -4
  101. data/lib/mongoid/factory.rb +13 -3
  102. data/lib/mongoid/fields/foreign_key.rb +5 -5
  103. data/lib/mongoid/fields/standard.rb +2 -14
  104. data/lib/mongoid/fields/validators/macro.rb +1 -1
  105. data/lib/mongoid/fields.rb +3 -3
  106. data/lib/mongoid/indexable.rb +4 -1
  107. data/lib/mongoid/interceptable.rb +5 -5
  108. data/lib/mongoid/matchable/and.rb +1 -1
  109. data/lib/mongoid/matchable/elem_match.rb +9 -3
  110. data/lib/mongoid/matchable/eq.rb +22 -0
  111. data/lib/mongoid/matchable/ne.rb +1 -1
  112. data/lib/mongoid/matchable.rb +3 -1
  113. data/lib/mongoid/persistable/deletable.rb +7 -6
  114. data/lib/mongoid/persistable/incrementable.rb +1 -1
  115. data/lib/mongoid/persistable/logical.rb +1 -1
  116. data/lib/mongoid/persistable/settable.rb +57 -12
  117. data/lib/mongoid/persistable.rb +4 -5
  118. data/lib/mongoid/persistence_context.rb +20 -5
  119. data/lib/mongoid/query_cache.rb +8 -4
  120. data/lib/mongoid/railtie.rb +17 -0
  121. data/lib/mongoid/railties/controller_runtime.rb +86 -0
  122. data/lib/mongoid/scopable.rb +3 -3
  123. data/lib/mongoid/serializable.rb +4 -4
  124. data/lib/mongoid/shardable.rb +1 -1
  125. data/lib/mongoid/threaded.rb +36 -0
  126. data/lib/mongoid/touchable.rb +102 -0
  127. data/lib/mongoid/traversable.rb +3 -3
  128. data/lib/mongoid/validatable/presence.rb +2 -2
  129. data/lib/mongoid/validatable/uniqueness.rb +4 -4
  130. data/lib/mongoid/validatable.rb +8 -8
  131. data/lib/mongoid/version.rb +1 -1
  132. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +3 -0
  133. data/spec/app/models/animal.rb +2 -1
  134. data/spec/app/models/bomb.rb +1 -1
  135. data/spec/app/models/message.rb +1 -1
  136. data/spec/app/models/minim.rb +7 -0
  137. data/spec/app/models/person.rb +5 -2
  138. data/spec/app/models/shipment_address.rb +1 -0
  139. data/spec/app/models/store_as_dup_test3.rb +7 -0
  140. data/spec/app/models/store_as_dup_test4.rb +7 -0
  141. data/spec/app/models/updatable.rb +7 -0
  142. data/spec/app/models/vertex.rb +6 -0
  143. data/spec/app/models/wiki_page.rb +1 -1
  144. data/spec/config/mongoid.yml +13 -3
  145. data/spec/integration/associations/belongs_to_spec.rb +13 -0
  146. data/spec/lite_spec_helper.rb +56 -0
  147. data/spec/mongoid/{relations → association}/accessors_spec.rb +40 -1
  148. data/spec/mongoid/{relations → association}/auto_save_spec.rb +60 -12
  149. data/spec/mongoid/{relations → association}/builders_spec.rb +1 -1
  150. data/spec/mongoid/association/constrainable_spec.rb +115 -0
  151. data/spec/mongoid/{relations → association}/counter_cache_spec.rb +1 -1
  152. data/spec/mongoid/association/depending_spec.rb +866 -0
  153. data/spec/mongoid/{relations → association}/eager_spec.rb +12 -12
  154. data/spec/mongoid/{relations → association/embedded}/cyclic_spec.rb +1 -1
  155. data/spec/mongoid/{relations/bindings/embedded/in_spec.rb → association/embedded/embedded_in/binding_spec.rb} +13 -13
  156. data/spec/mongoid/{relations/builders/embedded/in_spec.rb → association/embedded/embedded_in/buildable_spec.rb} +9 -9
  157. data/spec/mongoid/{relations/embedded/in_spec.rb → association/embedded/embedded_in/proxy_spec.rb} +5 -77
  158. data/spec/mongoid/association/embedded/embedded_in_spec.rb +843 -0
  159. data/spec/mongoid/{relations/bindings/embedded/many_spec.rb → association/embedded/embeds_many/binding_spec.rb} +3 -3
  160. data/spec/mongoid/{relations/builders/embedded/many_spec.rb → association/embedded/embeds_many/buildable_spec.rb} +17 -45
  161. data/spec/mongoid/{relations/embedded/many_spec.rb → association/embedded/embeds_many/proxy_spec.rb} +124 -182
  162. data/spec/mongoid/association/embedded/embeds_many_spec.rb +852 -0
  163. data/spec/mongoid/{relations/bindings/embedded/one_spec.rb → association/embedded/embeds_one/binding_spec.rb} +4 -4
  164. data/spec/mongoid/{relations/builders/embedded/one_spec.rb → association/embedded/embeds_one/buildable_spec.rb} +14 -34
  165. data/spec/mongoid/{relations/embedded/one_spec.rb → association/embedded/embeds_one/proxy_spec.rb} +39 -84
  166. data/spec/mongoid/association/embedded/embeds_one_spec.rb +908 -0
  167. data/spec/mongoid/{relations → association}/macros_spec.rb +148 -73
  168. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/many_spec.rb +16 -19
  169. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/one_spec.rb +17 -20
  170. data/spec/mongoid/association/options_spec.rb +1321 -0
  171. data/spec/mongoid/{relations → association}/polymorphic_spec.rb +66 -34
  172. data/spec/mongoid/{relations/bindings/referenced/in_spec.rb → association/referenced/belongs_to/binding_spec.rb} +7 -7
  173. data/spec/mongoid/{relations/builders/referenced/in_spec.rb → association/referenced/belongs_to/buildable_spec.rb} +46 -79
  174. data/spec/mongoid/{relations/eager/belongs_to_spec.rb → association/referenced/belongs_to/eager_spec.rb} +33 -14
  175. data/spec/mongoid/{relations/referenced/in_spec.rb → association/referenced/belongs_to/proxy_spec.rb} +57 -91
  176. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2006 -0
  177. data/spec/mongoid/{relations/bindings/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/binding_spec.rb} +5 -5
  178. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +121 -0
  179. data/spec/mongoid/{relations/eager/has_and_belongs_to_many_spec.rb → association/referenced/has_and_belongs_to_many/eager_spec.rb} +26 -7
  180. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +56 -0
  181. data/spec/mongoid/{relations/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/proxy_spec.rb} +107 -98
  182. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +26 -0
  183. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1027 -0
  184. data/spec/mongoid/{relations/bindings/referenced/many_spec.rb → association/referenced/has_many/binding_spec.rb} +5 -5
  185. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +119 -0
  186. data/spec/mongoid/{relations/eager/has_many_spec.rb → association/referenced/has_many/eager_spec.rb} +26 -11
  187. data/spec/mongoid/{relations/targets → association/referenced/has_many}/enumerable_spec.rb +122 -1
  188. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
  189. data/spec/mongoid/{relations/referenced/many_spec.rb → association/referenced/has_many/proxy_spec.rb} +28 -93
  190. data/spec/mongoid/association/referenced/has_many_models.rb +37 -0
  191. data/spec/mongoid/association/referenced/has_many_spec.rb +1225 -0
  192. data/spec/mongoid/{relations/bindings/referenced/one_spec.rb → association/referenced/has_one/binding_spec.rb} +4 -4
  193. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +113 -0
  194. data/spec/mongoid/{relations/eager/has_one_spec.rb → association/referenced/has_one/eager_spec.rb} +10 -10
  195. data/spec/mongoid/{relations/referenced/one_spec.rb → association/referenced/has_one/proxy_spec.rb} +9 -109
  196. data/spec/mongoid/association/referenced/has_one_models.rb +48 -0
  197. data/spec/mongoid/association/referenced/has_one_spec.rb +1350 -0
  198. data/spec/mongoid/{relations → association}/reflections_spec.rb +1 -12
  199. data/spec/mongoid/{relations/synchronization_spec.rb → association/syncable_spec.rb} +4 -2
  200. data/spec/mongoid/{relations_spec.rb → association_spec.rb} +1 -1
  201. data/spec/mongoid/atomic/modifiers_spec.rb +2 -2
  202. data/spec/mongoid/atomic_spec.rb +4 -4
  203. data/spec/mongoid/attributes/nested_spec.rb +29 -11
  204. data/spec/mongoid/attributes/readonly_spec.rb +80 -125
  205. data/spec/mongoid/attributes_spec.rb +38 -2
  206. data/spec/mongoid/clients/factory_spec.rb +24 -18
  207. data/spec/mongoid/clients/options_spec.rb +58 -44
  208. data/spec/mongoid/clients/sessions_spec.rb +1 -1
  209. data/spec/mongoid/clients/transactions_spec.rb +369 -0
  210. data/spec/mongoid/clients_spec.rb +68 -8
  211. data/spec/mongoid/config_spec.rb +27 -1
  212. data/spec/mongoid/contextual/memory_spec.rb +19 -0
  213. data/spec/mongoid/contextual/mongo_spec.rb +33 -5
  214. data/spec/mongoid/copyable_spec.rb +90 -6
  215. data/spec/mongoid/copyable_spec_models.rb +17 -0
  216. data/spec/mongoid/criteria/modifiable_spec.rb +183 -60
  217. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -3
  218. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +43 -0
  219. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +12 -0
  220. data/spec/mongoid/criteria/queryable/selectable_spec.rb +42 -3
  221. data/spec/mongoid/criteria/queryable/selector_spec.rb +2 -2
  222. data/spec/mongoid/criteria/scopable_spec.rb +81 -0
  223. data/spec/mongoid/criteria_spec.rb +33 -18
  224. data/spec/mongoid/document_spec.rb +83 -4
  225. data/spec/mongoid/extensions/array_spec.rb +11 -15
  226. data/spec/mongoid/extensions/big_decimal_spec.rb +9 -9
  227. data/spec/mongoid/extensions/hash_spec.rb +18 -1
  228. data/spec/mongoid/extensions/object_spec.rb +7 -11
  229. data/spec/mongoid/extensions/range_spec.rb +7 -0
  230. data/spec/mongoid/extensions/regexp_spec.rb +23 -0
  231. data/spec/mongoid/factory_spec.rb +19 -1
  232. data/spec/mongoid/fields/foreign_key_spec.rb +24 -32
  233. data/spec/mongoid/fields_spec.rb +2 -2
  234. data/spec/mongoid/findable_spec.rb +1 -1
  235. data/spec/mongoid/indexable_spec.rb +18 -8
  236. data/spec/mongoid/interceptable_spec.rb +22 -1
  237. data/spec/mongoid/matchable/elem_match_spec.rb +20 -0
  238. data/spec/mongoid/matchable/eq_spec.rb +48 -0
  239. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  240. data/spec/mongoid/persistable/savable_spec.rb +2 -2
  241. data/spec/mongoid/persistable/settable_spec.rb +95 -10
  242. data/spec/mongoid/persistable_spec.rb +21 -6
  243. data/spec/mongoid/persistence_context_spec.rb +1 -1
  244. data/spec/mongoid/query_cache_spec.rb +61 -22
  245. data/spec/mongoid/relations/proxy_spec.rb +124 -124
  246. data/spec/mongoid/scopable_spec.rb +13 -0
  247. data/spec/mongoid/shardable_spec.rb +32 -12
  248. data/spec/mongoid/threaded_spec.rb +68 -0
  249. data/spec/mongoid/{relations/touchable_spec.rb → touchable_spec.rb} +40 -1
  250. data/spec/mongoid/validatable/associated_spec.rb +1 -1
  251. data/spec/mongoid/validatable/presence_spec.rb +7 -6
  252. data/spec/mongoid/validatable_spec.rb +1 -1
  253. data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
  254. data/spec/spec_helper.rb +51 -25
  255. data/spec/support/constraints.rb +101 -0
  256. data/spec/support/macros.rb +20 -0
  257. data/spec/support/spec_config.rb +39 -0
  258. metadata +602 -582
  259. checksums.yaml.gz.sig +0 -2
  260. data/lib/mongoid/relations/accessors.rb +0 -267
  261. data/lib/mongoid/relations/auto_save.rb +0 -94
  262. data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
  263. data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
  264. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
  265. data/lib/mongoid/relations/bindings.rb +0 -9
  266. data/lib/mongoid/relations/builder.rb +0 -57
  267. data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
  268. data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
  269. data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
  270. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
  271. data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
  272. data/lib/mongoid/relations/builders.rb +0 -106
  273. data/lib/mongoid/relations/cascading/delete.rb +0 -44
  274. data/lib/mongoid/relations/cascading/destroy.rb +0 -43
  275. data/lib/mongoid/relations/cascading/nullify.rb +0 -35
  276. data/lib/mongoid/relations/cascading/restrict.rb +0 -39
  277. data/lib/mongoid/relations/cascading.rb +0 -56
  278. data/lib/mongoid/relations/conversions.rb +0 -34
  279. data/lib/mongoid/relations/counter_cache.rb +0 -160
  280. data/lib/mongoid/relations/cyclic.rb +0 -107
  281. data/lib/mongoid/relations/eager/base.rb +0 -153
  282. data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
  283. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
  284. data/lib/mongoid/relations/eager/has_many.rb +0 -38
  285. data/lib/mongoid/relations/eager/has_one.rb +0 -30
  286. data/lib/mongoid/relations/embedded/in.rb +0 -241
  287. data/lib/mongoid/relations/embedded/many.rb +0 -683
  288. data/lib/mongoid/relations/embedded/one.rb +0 -235
  289. data/lib/mongoid/relations/macros.rb +0 -367
  290. data/lib/mongoid/relations/metadata.rb +0 -1179
  291. data/lib/mongoid/relations/nested_builder.rb +0 -74
  292. data/lib/mongoid/relations/options.rb +0 -49
  293. data/lib/mongoid/relations/polymorphic.rb +0 -39
  294. data/lib/mongoid/relations/referenced/in.rb +0 -304
  295. data/lib/mongoid/relations/referenced/many.rb +0 -812
  296. data/lib/mongoid/relations/referenced/many_to_many.rb +0 -479
  297. data/lib/mongoid/relations/referenced/one.rb +0 -290
  298. data/lib/mongoid/relations/synchronization.rb +0 -169
  299. data/lib/mongoid/relations/targets/enumerable.rb +0 -493
  300. data/lib/mongoid/relations/targets.rb +0 -2
  301. data/lib/mongoid/relations/touchable.rb +0 -97
  302. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
  303. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
  304. data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
  305. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
  306. data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
  307. data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
  308. data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
  309. data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
  310. data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
  311. data/spec/mongoid/relations/cascading_spec.rb +0 -355
  312. data/spec/mongoid/relations/constraint_spec.rb +0 -75
  313. data/spec/mongoid/relations/conversions_spec.rb +0 -128
  314. data/spec/mongoid/relations/metadata_spec.rb +0 -1985
  315. data/spec/mongoid/relations/options_spec.rb +0 -35
  316. data.tar.gz.sig +0 -0
  317. metadata.gz.sig +0 -0
  318. /data/spec/mongoid/{relations → association}/embedded/dirty_spec.rb +0 -0
@@ -2,6 +2,7 @@
2
2
  require "mongoid/matchable/default"
3
3
  require "mongoid/matchable/all"
4
4
  require "mongoid/matchable/and"
5
+ require "mongoid/matchable/eq"
5
6
  require "mongoid/matchable/exists"
6
7
  require "mongoid/matchable/gt"
7
8
  require "mongoid/matchable/gte"
@@ -32,6 +33,7 @@ module Mongoid
32
33
  "$all" => All,
33
34
  "$elemMatch" => ElemMatch,
34
35
  "$and" => And,
36
+ "$eq" => Eq,
35
37
  "$exists" => Exists,
36
38
  "$gt" => Gt,
37
39
  "$gte" => Gte,
@@ -42,7 +44,7 @@ module Mongoid
42
44
  "$nin" => Nin,
43
45
  "$or" => Or,
44
46
  "$nor" => Nor,
45
- "$size" => Size
47
+ "$size" => Size,
46
48
  }.with_indifferent_access.freeze
47
49
 
48
50
  # Determines if this document has the attributes to match the supplied
@@ -21,10 +21,12 @@ module Mongoid
21
21
  def delete(options = {})
22
22
  raise Errors::ReadonlyDocument.new(self.class) if readonly?
23
23
  prepare_delete do
24
- if embedded?
25
- delete_as_embedded(options)
26
- else
27
- delete_as_root
24
+ unless options[:persist] == false
25
+ if embedded?
26
+ delete_as_embedded(options)
27
+ else
28
+ delete_as_root
29
+ end
28
30
  end
29
31
  end
30
32
  end
@@ -113,11 +115,10 @@ module Mongoid
113
115
  #
114
116
  # @since 4.0.0
115
117
  def prepare_delete
116
- cascade!
118
+ return false unless catch(:abort) { apply_delete_dependencies! }
117
119
  yield(self)
118
120
  freeze
119
121
  self.destroyed = true
120
- true
121
122
  end
122
123
 
123
124
  module ClassMethods
@@ -28,7 +28,7 @@ module Mongoid
28
28
  attributes[field] = (current || 0) + increment
29
29
  ops[atomic_attribute_name(field)] = increment
30
30
  end
31
- { "$inc" => ops }
31
+ { "$inc" => ops } unless ops.empty?
32
32
  end
33
33
  end
34
34
  end
@@ -30,7 +30,7 @@ module Mongoid
30
30
  attributes[field] = value
31
31
  ops[atomic_attribute_name(field)] = values
32
32
  end
33
- { "$bit" => ops }
33
+ { "$bit" => ops } unless ops.empty?
34
34
  end
35
35
  end
36
36
  end
@@ -14,6 +14,34 @@ module Mongoid
14
14
  # @example Set the values.
15
15
  # document.set(title: "sir", dob: Date.new(1970, 1, 1))
16
16
  #
17
+ # The key can be a dotted sequence of keys, in which case the
18
+ # top level field is treated as a nested hash and any missing keys
19
+ # are created automatically:
20
+ #
21
+ # @example Set the values using nested hash semantics.
22
+ # document.set('author.title' => 'Sir')
23
+ # # => document.author == {'title' => 'Sir'}
24
+ #
25
+ # Performing a nested set like this merges values of intermediate keys:
26
+ #
27
+ # @example Nested hash value merging.
28
+ # document.set('author.title' => 'Sir')
29
+ # document.set('author.name' => 'Linus Torvalds')
30
+ # # => document.author == {'title' => 'Sir', 'name' => 'Linus Torvalds'}
31
+ #
32
+ # If the top level field was not a hash, its original value is discarded
33
+ # and the field is replaced with a hash.
34
+ #
35
+ # @example Nested hash overwriting a non-hash value.
36
+ # document.set('author' => 'John Doe')
37
+ # document.set('author.title' => 'Sir')
38
+ # # => document.author == {'title' => 'Sir'}
39
+ #
40
+ # Note that unlike MongoDB's $set, Mongoid's set writes out the entire
41
+ # field even when setting a subset of the field via the nested hash
42
+ # semantics. This means performing a $set with nested hash semantics
43
+ # can overwrite other hash keys within the top level field in the database.
44
+ #
17
45
  # @param [ Hash ] setters The field/value pairs to set.
18
46
  #
19
47
  # @return [ Document ] The document.
@@ -23,16 +51,38 @@ module Mongoid
23
51
  prepare_atomic_operation do |ops|
24
52
  process_atomic_operations(setters) do |field, value|
25
53
 
26
- field_and_value_hash = hasherizer(field.split('.'), value)
27
- field = field_and_value_hash.keys.first.to_s
28
- value = field_and_value_hash[field]
54
+ field_seq = field.to_s.split('.')
55
+ field = field_seq.shift
56
+ if field_seq.length > 0
57
+ # nested hash path
58
+ old_value = attributes[field]
59
+
60
+ # if the old value is not a hash, clobber it
61
+ unless Hash === old_value
62
+ old_value = {}
63
+ end
64
+
65
+ # descend into the hash, creating intermediate keys as needed
66
+ cur_value = old_value
67
+ while field_seq.length > 1
68
+ cur_key = field_seq.shift
69
+ # clobber on each level if type is not a hash
70
+ unless Hash === cur_value[cur_key]
71
+ cur_value[cur_key] = {}
72
+ end
73
+ cur_value = cur_value[cur_key]
74
+ end
29
75
 
30
- if fields[field] && fields[field].type == Hash && attributes.key?(field) && Hash === value && !value.empty?
31
- merger = proc { |key, v1, v2| Hash === v1 && Hash === v2 ? v1.merge(v2, &merger) : v2 }
32
- value = (attributes[field] || {}).merge(value, &merger)
76
+ # now we are on the leaf level, perform the set
77
+ # and overwrite whatever was on this level before
78
+ cur_value[field_seq.shift] = value
79
+
80
+ # and set value to the value of the top level field
81
+ # because this is what we pass to $set
82
+ value = old_value
33
83
  end
34
84
 
35
- process_attribute(field.to_s, value)
85
+ process_attribute(field, value)
36
86
 
37
87
  unless relations.include?(field.to_s)
38
88
  ops[atomic_attribute_name(field)] = attributes[field]
@@ -42,10 +92,5 @@ module Mongoid
42
92
  end
43
93
  end
44
94
  end
45
-
46
- def hasherizer(keys, value)
47
- return value if keys.empty?
48
- {}.tap { |hash| hash[keys.shift] = hasherizer(keys, value) }
49
- end
50
95
  end
51
96
  end
@@ -162,10 +162,9 @@ module Mongoid
162
162
  # @since 4.0.0
163
163
  def process_atomic_operations(operations)
164
164
  operations.each do |field, value|
165
- as_writable_attribute!(field, value) do |access|
166
- yield(access, value)
167
- remove_change(access)
168
- end
165
+ access = database_field_name(field)
166
+ yield(access, value)
167
+ remove_change(access)
169
168
  end
170
169
  end
171
170
 
@@ -202,7 +201,7 @@ module Mongoid
202
201
  #
203
202
  # @since 4.0.0
204
203
  def persist_atomic_operations(operations)
205
- if persisted? && operations
204
+ if persisted? && operations && !operations.empty?
206
205
  selector = atomic_selector
207
206
  _root.collection.find(selector).update_one(positionally(selector, operations), session: _session)
208
207
  end
@@ -169,6 +169,9 @@ module Mongoid
169
169
 
170
170
  # Set the persistence context for a particular class or model instance.
171
171
  #
172
+ # If there already is a persistence context set, options in the existing
173
+ # context are combined with options given to the set call.
174
+ #
172
175
  # @example Set the persistence context for a class or model instance.
173
176
  # PersistenceContext.set(model)
174
177
  #
@@ -180,9 +183,19 @@ module Mongoid
180
183
  #
181
184
  # @since 6.0.0
182
185
  def set(object, options_or_context)
183
- context = PersistenceContext.new(object, options_or_context.is_a?(PersistenceContext) ?
184
- options_or_context.options : options_or_context)
185
- Thread.current["[mongoid][#{object.object_id}]:context"] = context
186
+ key = "[mongoid][#{object.object_id}]:context"
187
+ existing_context = Thread.current[key]
188
+ existing_options = if existing_context
189
+ existing_context.options
190
+ else
191
+ {}
192
+ end
193
+ if options_or_context.is_a?(PersistenceContext)
194
+ options_or_context = options_or_context.options
195
+ end
196
+ new_options = existing_options.merge(options_or_context)
197
+ context = PersistenceContext.new(object, new_options)
198
+ Thread.current[key] = context
186
199
  end
187
200
 
188
201
  # Get the persistence context for a particular class or model instance.
@@ -206,14 +219,16 @@ module Mongoid
206
219
  #
207
220
  # @param [ Class, Object ] object The class or model instance.
208
221
  # @param [ Mongo::Cluster ] cluster The original cluster before this context was used.
222
+ # @param [ Mongoid::PersistenceContext ] original_context The original persistence
223
+ # context that was set before this context was used.
209
224
  #
210
225
  # @since 6.0.0
211
- def clear(object, cluster = nil)
226
+ def clear(object, cluster = nil, original_context = nil)
212
227
  if context = get(object)
213
228
  context.client.close unless (context.cluster.equal?(cluster) || cluster.nil?)
214
229
  end
215
230
  ensure
216
- Thread.current["[mongoid][#{object.object_id}]:context"] = nil
231
+ Thread.current["[mongoid][#{object.object_id}]:context"] = original_context
217
232
  end
218
233
  end
219
234
  end
@@ -138,7 +138,9 @@ module Mongoid
138
138
  # @since 5.0.0
139
139
  def each
140
140
  if @cached_documents
141
- @cached_documents.each{ |doc| yield doc }
141
+ @cached_documents.each do |doc|
142
+ yield doc
143
+ end
142
144
  else
143
145
  super
144
146
  end
@@ -163,7 +165,10 @@ module Mongoid
163
165
  @cursor_id = result.cursor_id
164
166
  @coll_name ||= result.namespace.sub("#{database.name}.", '') if result.namespace
165
167
  documents = result.documents
166
- (@cached_documents ||= []).concat(documents)
168
+ if @cursor_id.zero? && !@after_first_batch
169
+ (@cached_documents ||= []).concat(documents)
170
+ end
171
+ @after_first_batch = true
167
172
  documents
168
173
  end
169
174
  end
@@ -242,8 +247,7 @@ module Mongoid
242
247
  key = [ collection.namespace, selector, nil, skip, sort, projection, collation ]
243
248
  cursor = QueryCache.cache_table[key]
244
249
  if cursor
245
- limited_docs = cursor.to_a[0...limit.abs]
246
- cursor.instance_variable_set(:@cached_documents, limited_docs)
250
+ cursor.to_a[0...limit.abs]
247
251
  end
248
252
  end
249
253
  cursor || QueryCache.cache_table[cache_key]
@@ -102,6 +102,23 @@ module Rails
102
102
  puts "There is a configuration error with the current mongoid.yml."
103
103
  puts e.message
104
104
  end
105
+
106
+ # Include Controller extension that measures Mongoid runtime
107
+ # during request processing. The value then appears in Rails'
108
+ # instrumentation event `process_action.action_controller`.
109
+ #
110
+ # The measurement is made via internal Mongo monitoring subscription
111
+ initializer "mongoid.runtime-metric" do
112
+ require "mongoid/railties/controller_runtime"
113
+
114
+ ActiveSupport.on_load :action_controller do
115
+ include ::Mongoid::Railties::ControllerRuntime::ControllerExtension
116
+ end
117
+
118
+ Mongo::Monitoring::Global.subscribe Mongo::Monitoring::COMMAND,
119
+ ::Mongoid::Railties::ControllerRuntime::Collector.new
120
+ end
121
+
105
122
  end
106
123
  end
107
124
  end
@@ -0,0 +1,86 @@
1
+ module Mongoid
2
+ module Railties
3
+ module ControllerRuntime
4
+
5
+ # This extension mimics the Rails' internal method to
6
+ # measure ActiveRecord runtime during request processing.
7
+ # It appends MongoDB runtime value (`mongoid_runtime`) into payload
8
+ # of instrumentation event `process_action.action_controller`.
9
+ module ControllerExtension
10
+ extend ActiveSupport::Concern
11
+
12
+ protected
13
+
14
+ attr_internal :mongoid_runtime
15
+
16
+ # Reset the runtime before each action.
17
+ def process_action(action, *args)
18
+ Collector.reset_runtime
19
+ super
20
+ end
21
+
22
+ # Override to collect the measurements.
23
+ def cleanup_view_runtime
24
+ mongo_rt_before_render = Collector.reset_runtime
25
+ runtime = super
26
+ mongo_rt_after_render = Collector.reset_runtime
27
+ self.mongoid_runtime = mongo_rt_before_render + mongo_rt_after_render
28
+ runtime - mongo_rt_after_render
29
+ end
30
+
31
+ # Add the measurement to the instrumentation event payload.
32
+ def append_info_to_payload(payload)
33
+ super
34
+ payload[:mongoid_runtime] = (mongoid_runtime || 0) + Collector.reset_runtime
35
+ end
36
+
37
+ module ClassMethods
38
+
39
+ # Append MongoDB runtime information to ActionController runtime
40
+ # log message.
41
+ def log_process_action(payload)
42
+ messages = super
43
+ mongoid_runtime = payload[:mongoid_runtime]
44
+ messages << ("MongoDB: %.1fms" % mongoid_runtime.to_f) if mongoid_runtime
45
+ messages
46
+ end
47
+
48
+ end
49
+
50
+ end
51
+
52
+ # The Collector of MongoDB runtime metric, that subscribes to Mongo
53
+ # driver command monitoring. Stores the value within a thread-local
54
+ # variable to provide correct accounting when an application issues
55
+ # MongoDB operations from background threads.
56
+ class Collector
57
+
58
+ VARIABLE_NAME = "Mongoid.controller_runtime".freeze
59
+
60
+ def started _; end
61
+
62
+ def _completed e
63
+ Collector.runtime += e.duration
64
+ end
65
+ alias :succeeded :_completed
66
+ alias :failed :_completed
67
+
68
+ def self.runtime
69
+ Thread.current[VARIABLE_NAME] ||= 0
70
+ end
71
+
72
+ def self.runtime= value
73
+ Thread.current[VARIABLE_NAME] = value
74
+ end
75
+
76
+ def self.reset_runtime
77
+ to_now = runtime
78
+ self.runtime = 0
79
+ to_now
80
+ end
81
+
82
+ end
83
+
84
+ end
85
+ end
86
+ end
@@ -102,7 +102,7 @@ module Mongoid
102
102
  #
103
103
  # @since 3.0.0
104
104
  def default_scopable?
105
- default_scoping? && !Threaded.executing?(:without_default_scope)
105
+ default_scoping? && !Threaded.without_default_scope?(self)
106
106
  end
107
107
 
108
108
  # Get a queryable, either the last one on the scope stack or a fresh one.
@@ -244,10 +244,10 @@ module Mongoid
244
244
  #
245
245
  # @since 3.0.0
246
246
  def without_default_scope
247
- Threaded.begin_execution("without_default_scope")
247
+ Threaded.begin_without_default_scope(self)
248
248
  yield
249
249
  ensure
250
- Threaded.exit_execution("without_default_scope")
250
+ Threaded.exit_without_default_scope(self)
251
251
  end
252
252
 
253
253
  private
@@ -101,7 +101,7 @@ module Mongoid
101
101
  value = send(name)
102
102
  attrs[name] = value ? value.serializable_hash(options) : nil
103
103
  elsif names.include?(name) && !fields.key?(name)
104
- attrs[name] = read_attribute(name)
104
+ attrs[name] = read_raw_attribute(name)
105
105
  elsif !attribute_missing?(name)
106
106
  attrs[name] = send(name)
107
107
  end
@@ -124,9 +124,9 @@ module Mongoid
124
124
  def serialize_relations(attributes = {}, options = {})
125
125
  inclusions = options[:include]
126
126
  relation_names(inclusions).each do |name|
127
- metadata = relations[name.to_s]
128
- if metadata && relation = send(metadata.name)
129
- attributes[metadata.name.to_s] =
127
+ association = relations[name.to_s]
128
+ if association && relation = send(association.name)
129
+ attributes[association.name.to_s] =
130
130
  relation.serializable_hash(relation_options(inclusions, options, name))
131
131
  end
132
132
  end
@@ -37,7 +37,7 @@ module Mongoid
37
37
  def shard_key_selector
38
38
  selector = {}
39
39
  shard_key_fields.each do |field|
40
- selector[field.to_s] = send(field)
40
+ selector[field.to_s] = new_record? ? send(field) : attribute_was(field)
41
41
  end
42
42
  selector
43
43
  end
@@ -163,6 +163,30 @@ module Mongoid
163
163
  validations_for(document.class).delete_one(document._id)
164
164
  end
165
165
 
166
+ # Begin suppressing default scopes for given model on the current thread.
167
+ #
168
+ # @example Begin without default scope stack.
169
+ # Threaded.begin_without_default_scope(klass)
170
+ #
171
+ # @param [ Class ] klass The model to suppress default scoping on.
172
+ #
173
+ # @api private
174
+ def begin_without_default_scope(klass)
175
+ stack(:without_default_scope).push(klass)
176
+ end
177
+
178
+ # Exit suppressing default scopes for given model on the current thread.
179
+ #
180
+ # @example Exit without default scope stack.
181
+ # Threaded.exit_without_default_scope(klass)
182
+ #
183
+ # @param [ Class ] klass The model to unsuppress default scoping on.
184
+ #
185
+ # @api private
186
+ def exit_without_default_scope(klass)
187
+ stack(:without_default_scope).delete(klass)
188
+ end
189
+
166
190
  # Get the global client override.
167
191
  #
168
192
  # @example Get the global client override.
@@ -247,6 +271,18 @@ module Mongoid
247
271
  end
248
272
  end
249
273
 
274
+ # Is the given klass' default scope suppressed on the current thread?
275
+ #
276
+ # @example Is the given klass' default scope suppressed?
277
+ # Threaded.without_default_scope?(klass)
278
+ #
279
+ # @param [ Class ] klass The model to check for default scope suppression.
280
+ #
281
+ # @api private
282
+ def without_default_scope?(klass)
283
+ stack(:without_default_scope).include?(klass)
284
+ end
285
+
250
286
  # Is the document autosaved on the current thread?
251
287
  #
252
288
  # @example Is the document autosaved?
@@ -0,0 +1,102 @@
1
+ # frozen_string_literal: true
2
+ # encoding: utf-8
3
+ module Mongoid
4
+ module Touchable
5
+
6
+ module InstanceMethods
7
+
8
+ # Touch the document, in effect updating its updated_at timestamp and
9
+ # optionally the provided field to the current time. If any belongs_to
10
+ # relations exist with a touch option, they will be updated as well.
11
+ #
12
+ # @example Update the updated_at timestamp.
13
+ # document.touch
14
+ #
15
+ # @example Update the updated_at and provided timestamps.
16
+ # document.touch(:audited)
17
+ #
18
+ # @note This will not autobuild relations if those options are set.
19
+ #
20
+ # @param [ Symbol ] field The name of an additional field to update.
21
+ #
22
+ # @return [ true/false ] false if record is new_record otherwise true.
23
+ #
24
+ # @since 3.0.0
25
+ def touch(field = nil)
26
+ return false if _root.new_record?
27
+ current = Time.now
28
+ field = database_field_name(field)
29
+ write_attribute(:updated_at, current) if respond_to?("updated_at=")
30
+ write_attribute(field, current) if field
31
+
32
+ touches = touch_atomic_updates(field)
33
+ unless touches["$set"].blank?
34
+ selector = atomic_selector
35
+ _root.collection.find(selector).update_one(positionally(selector, touches), session: _session)
36
+ end
37
+ run_callbacks(:touch)
38
+ true
39
+ end
40
+ end
41
+
42
+ extend self
43
+
44
+ # Add the association to the touchable relations if the touch option was
45
+ # provided.
46
+ #
47
+ # @example Add the touchable.
48
+ # Model.define_touchable!(assoc)
49
+ #
50
+ # @param [ Association ] association The association metadata.
51
+ #
52
+ # @return [ Class ] The model class.
53
+ #
54
+ # @since 3.0.0
55
+ def define_touchable!(association)
56
+ name = association.name
57
+ method_name = define_relation_touch_method(name, association)
58
+ association.inverse_class.tap do |klass|
59
+ klass.after_save method_name
60
+ klass.after_destroy method_name
61
+ klass.after_touch method_name
62
+ end
63
+ end
64
+
65
+ private
66
+
67
+ # Define the method that will get called for touching belongs_to
68
+ # relations.
69
+ #
70
+ # @api private
71
+ #
72
+ # @example Define the touch relation.
73
+ # Model.define_relation_touch_method(:band)
74
+ # Model.define_relation_touch_method(:band, :band_updated_at)
75
+ #
76
+ # @param [ Symbol ] name The name of the relation.
77
+ # @param [ Association ] association The association metadata.
78
+ #
79
+ # @since 3.1.0
80
+ #
81
+ # @return [ Symbol ] The method name.
82
+ def define_relation_touch_method(name, association)
83
+ relation_classes = if association.polymorphic?
84
+ association.send(:inverse_association_classes)
85
+ else
86
+ [ association.relation_class ]
87
+ end
88
+
89
+ relation_classes.each { |c| c.send(:include, InstanceMethods) }
90
+ method_name = "touch_#{name}_after_create_or_destroy"
91
+ association.inverse_class.class_eval <<-TOUCH, __FILE__, __LINE__ + 1
92
+ def #{method_name}
93
+ without_autobuild do
94
+ relation = __send__(:#{name})
95
+ relation.touch #{":#{association.touch_field}" if association.touch_field} if relation
96
+ end
97
+ end
98
+ TOUCH
99
+ method_name.to_sym
100
+ end
101
+ end
102
+ end
@@ -8,7 +8,7 @@ module Mongoid
8
8
  extend ActiveSupport::Concern
9
9
 
10
10
  def _parent
11
- @__parent
11
+ @__parent ||= nil
12
12
  end
13
13
 
14
14
  def _parent=(p)
@@ -40,7 +40,7 @@ module Mongoid
40
40
  # @since 2.4.0
41
41
  def collect_children
42
42
  children = []
43
- embedded_relations.each_pair do |name, metadata|
43
+ embedded_relations.each_pair do |name, association|
44
44
  without_autobuild do
45
45
  child = send(name)
46
46
  Array.wrap(child).each do |doc|
@@ -101,7 +101,7 @@ module Mongoid
101
101
  #
102
102
  # @since 2.0.0.beta.1
103
103
  def remove_child(child)
104
- name = child.metadata_name
104
+ name = child.association_name
105
105
  if child.embedded_one?
106
106
  remove_ivar(name)
107
107
  else
@@ -62,8 +62,8 @@ module Mongoid
62
62
  # @since 3.0.0
63
63
  def relation_or_fk_missing?(doc, attr, value)
64
64
  return true if value.blank? && doc.send(attr).blank?
65
- metadata = doc.relations[attr.to_s]
66
- metadata.stores_foreign_key? && doc.send(metadata.foreign_key).blank?
65
+ association = doc.relations[attr.to_s]
66
+ association.stores_foreign_key? && doc.send(association.foreign_key).blank?
67
67
  end
68
68
 
69
69
  # For guarding against false values.
@@ -224,9 +224,9 @@ module Mongoid
224
224
  #
225
225
  # @since 2.4.4
226
226
  def to_validate(document, attribute, value)
227
- metadata = document.relations[attribute.to_s]
228
- if metadata && metadata.stores_foreign_key?
229
- [ metadata.foreign_key, value && value._id ]
227
+ association = document.relations[attribute.to_s]
228
+ if association && association.stores_foreign_key?
229
+ [ association.foreign_key, value && value._id ]
230
230
  else
231
231
  [ attribute, value ]
232
232
  end
@@ -246,7 +246,7 @@ module Mongoid
246
246
  # @since 2.4.10
247
247
  def validate_embedded(document, attribute, value)
248
248
  return if skip_validation?(document)
249
- relation = document._parent.send(document.metadata_name)
249
+ relation = document._parent.send(document.association_name)
250
250
  criteria = create_criteria(relation, document, attribute, value)
251
251
  criteria = criteria.merge(options[:conditions].call) if options[:conditions]
252
252
  add_error(document, attribute, value) if criteria.count > 1