mongoid 6.4.2 → 7.0.3

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 (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
@@ -0,0 +1,578 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Association
4
+ module Referenced
5
+ class HasMany
6
+
7
+ # This class defines the behaviour for all relations that are a
8
+ # one-to-many between documents in different collections.
9
+ class Proxy < Association::Many
10
+
11
+ delegate :count, to: :criteria
12
+ delegate :first, :in_memory, :last, :reset, :uniq, to: :_target
13
+
14
+ # Appends a document or array of documents to the relation. Will set
15
+ # the parent and update the index in the process.
16
+ #
17
+ # @example Append a document.
18
+ # person.posts << post
19
+ #
20
+ # @example Push a document.
21
+ # person.posts.push(post)
22
+ #
23
+ # @example Concat with other documents.
24
+ # person.posts.concat([ post_one, post_two ])
25
+ #
26
+ # @param [ Document, Array<Document> ] args Any number of documents.
27
+ #
28
+ # @return [ Array<Document> ] The loaded docs.
29
+ #
30
+ # @since 2.0.0.beta.1
31
+ def <<(*args)
32
+ docs = args.flatten
33
+ return concat(docs) if docs.size > 1
34
+ if doc = docs.first
35
+ append(doc)
36
+ doc.save if persistable? && !_assigning? && !doc.validated?
37
+ end
38
+ self
39
+ end
40
+
41
+ alias :push :<<
42
+
43
+ # Appends an array of documents to the relation. Performs a batch
44
+ # insert of the documents instead of persisting one at a time.
45
+ #
46
+ # @example Concat with other documents.
47
+ # person.posts.concat([ post_one, post_two ])
48
+ #
49
+ # @param [ Array<Document> ] documents The docs to add.
50
+ #
51
+ # @return [ Array<Document> ] The documents.
52
+ #
53
+ # @since 2.4.0
54
+ def concat(documents)
55
+ docs, inserts = [], []
56
+ documents.each do |doc|
57
+ next unless doc
58
+ append(doc)
59
+ save_or_delay(doc, docs, inserts) if persistable?
60
+ end
61
+ persist_delayed(docs, inserts)
62
+ self
63
+ end
64
+
65
+ # Build a new document from the attributes and append it to this
66
+ # relation without saving.
67
+ #
68
+ # @example Build a new document on the relation.
69
+ # person.posts.build(:title => "A new post")
70
+ #
71
+ # @param [ Hash ] attributes The attributes of the new document.
72
+ # @param [ Class ] type The optional subclass to build.
73
+ #
74
+ # @return [ Document ] The new document.
75
+ #
76
+ # @since 2.0.0.beta.1
77
+ def build(attributes = {}, type = nil)
78
+ doc = Factory.build(type || klass, attributes)
79
+ append(doc)
80
+ doc.apply_post_processed_defaults
81
+ yield(doc) if block_given?
82
+ doc.run_callbacks(:build) { doc }
83
+ doc
84
+ end
85
+
86
+ alias :new :build
87
+
88
+ # Delete the document from the relation. This will set the foreign key
89
+ # on the document to nil. If the dependent options on the relation are
90
+ # :delete or :destroy the appropriate removal will occur.
91
+ #
92
+ # @example Delete the document.
93
+ # person.posts.delete(post)
94
+ #
95
+ # @param [ Document ] document The document to remove.
96
+ #
97
+ # @return [ Document ] The matching document.
98
+ #
99
+ # @since 2.1.0
100
+ def delete(document)
101
+ execute_callback :before_remove, document
102
+ _target.delete(document) do |doc|
103
+ if doc
104
+ unbind_one(doc)
105
+ cascade!(doc) if !_assigning?
106
+ end
107
+ execute_callback :after_remove, doc
108
+ end
109
+ end
110
+
111
+ # Deletes all related documents from the database given the supplied
112
+ # conditions.
113
+ #
114
+ # @example Delete all documents in the relation.
115
+ # person.posts.delete_all
116
+ #
117
+ # @example Conditonally delete all documents in the relation.
118
+ # person.posts.delete_all({ :title => "Testing" })
119
+ #
120
+ # @param [ Hash ] conditions Optional conditions to delete with.
121
+ #
122
+ # @return [ Integer ] The number of documents deleted.
123
+ #
124
+ # @since 2.0.0.beta.1
125
+ def delete_all(conditions = nil)
126
+ remove_all(conditions, :delete_all)
127
+ end
128
+
129
+ # Destroys all related documents from the database given the supplied
130
+ # conditions.
131
+ #
132
+ # @example Destroy all documents in the relation.
133
+ # person.posts.destroy_all
134
+ #
135
+ # @example Conditonally destroy all documents in the relation.
136
+ # person.posts.destroy_all({ :title => "Testing" })
137
+ #
138
+ # @param [ Hash ] conditions Optional conditions to destroy with.
139
+ #
140
+ # @return [ Integer ] The number of documents destroyd.
141
+ #
142
+ # @since 2.0.0.beta.1
143
+ def destroy_all(conditions = nil)
144
+ remove_all(conditions, :destroy_all)
145
+ end
146
+
147
+ # Iterate over each document in the relation and yield to the provided
148
+ # block.
149
+ #
150
+ # @note This will load the entire relation into memory.
151
+ #
152
+ # @example Iterate over the documents.
153
+ # person.posts.each do |post|
154
+ # post.save
155
+ # end
156
+ #
157
+ # @return [ Array<Document> ] The loaded docs.
158
+ #
159
+ # @since 2.1.0
160
+ def each
161
+ if block_given?
162
+ _target.each { |doc| yield(doc) }
163
+ else
164
+ to_enum
165
+ end
166
+ end
167
+
168
+ # Determine if any documents in this relation exist in the database.
169
+ #
170
+ # @example Are there persisted documents?
171
+ # person.posts.exists?
172
+ #
173
+ # @return [ true, false ] True is persisted documents exist, false if not.
174
+ def exists?
175
+ criteria.exists?
176
+ end
177
+
178
+ # Find the matchind document on the association, either based on id or
179
+ # conditions.
180
+ #
181
+ # @example Find by an id.
182
+ # person.posts.find(BSON::ObjectId.new)
183
+ #
184
+ # @example Find by multiple ids.
185
+ # person.posts.find([ BSON::ObjectId.new, BSON::ObjectId.new ])
186
+ #
187
+ # @note This will keep matching documents in memory for iteration
188
+ # later.
189
+ #
190
+ # @param [ BSON::ObjectId, Array<BSON::ObjectId> ] args The ids.
191
+ #
192
+ # @return [ Document, Criteria ] The matching document(s).
193
+ #
194
+ # @since 2.0.0.beta.1
195
+ def find(*args)
196
+ matching = criteria.find(*args)
197
+ Array(matching).each { |doc| _target.push(doc) }
198
+ matching
199
+ end
200
+
201
+ # Instantiate a new references_many relation. Will set the foreign key
202
+ # and the base on the inverse object.
203
+ #
204
+ # @example Create the new relation.
205
+ # Referenced::Many.new(base, target, association)
206
+ #
207
+ # @param [ Document ] base The document this relation hangs off of.
208
+ # @param [ Array<Document> ] target The target of the relation.
209
+ # @param [ Association ] association The association metadata.
210
+ #
211
+ # @since 2.0.0.beta.1
212
+ def initialize(base, target, association)
213
+ enum = HasMany::Targets::Enumerable.new(target, base, association)
214
+ init(base, enum, association) do
215
+ raise_mixed if klass.embedded? && !klass.cyclic?
216
+ end
217
+ end
218
+
219
+ # Removes all associations between the base document and the target
220
+ # documents by deleting the foreign keys and the references, orphaning
221
+ # the target documents in the process.
222
+ #
223
+ # @example Nullify the relation.
224
+ # person.posts.nullify
225
+ #
226
+ # @since 2.0.0.rc.1
227
+ def nullify
228
+ criteria.update_all(foreign_key => nil)
229
+ _target.clear do |doc|
230
+ unbind_one(doc)
231
+ doc.changed_attributes.delete(foreign_key)
232
+ end
233
+ end
234
+
235
+ alias :nullify_all :nullify
236
+
237
+ # Clear the relation. Will delete the documents from the db if they are
238
+ # already persisted.
239
+ #
240
+ # @example Clear the relation.
241
+ # person.posts.clear
242
+ #
243
+ # @return [ Many ] The relation emptied.
244
+ #
245
+ # @since 2.0.0.beta.1
246
+ def purge
247
+ unless _association.destructive?
248
+ nullify
249
+ else
250
+ after_remove_error = nil
251
+ criteria.delete_all
252
+ many = _target.clear do |doc|
253
+ execute_callback :before_remove, doc
254
+ unbind_one(doc)
255
+ doc.destroyed = true
256
+ begin
257
+ execute_callback :after_remove, doc
258
+ rescue => e
259
+ after_remove_error = e
260
+ end
261
+ end
262
+ raise after_remove_error if after_remove_error
263
+ many
264
+ end
265
+ end
266
+
267
+ alias :clear :purge
268
+
269
+ # Substitutes the supplied target documents for the existing documents
270
+ # in the relation. If the new target is nil, perform the necessary
271
+ # deletion.
272
+ #
273
+ # @example Replace the relation.
274
+ # person.posts.substitute([ new_post ])
275
+ #
276
+ # @param [ Array<Document> ] replacement The replacement target.
277
+ #
278
+ # @return [ Many ] The relation.
279
+ #
280
+ # @since 2.0.0.rc.1
281
+ def substitute(replacement)
282
+ if replacement
283
+ new_docs, docs = replacement.compact, []
284
+ new_ids = new_docs.map { |doc| doc._id }
285
+ remove_not_in(new_ids)
286
+ new_docs.each do |doc|
287
+ docs.push(doc) if doc.send(foreign_key) != _base.send(_association.primary_key)
288
+ end
289
+ concat(docs)
290
+ else
291
+ purge
292
+ end
293
+ self
294
+ end
295
+
296
+ # Get a criteria for the documents without the default scoping
297
+ # applied.
298
+ #
299
+ # @example Get the unscoped criteria.
300
+ # person.posts.unscoped
301
+ #
302
+ # @return [ Criteria ] The unscoped criteria.
303
+ #
304
+ # @since 2.4.0
305
+ def unscoped
306
+ klass.unscoped.where(foreign_key => _base.send(_association.primary_key))
307
+ end
308
+
309
+ private
310
+
311
+ # Appends the document to the target array, updating the index on the
312
+ # document at the same time.
313
+ #
314
+ # @example Append the document to the relation.
315
+ # relation.append(document)
316
+ #
317
+ # @param [ Document ] document The document to append to the target.
318
+ #
319
+ # @since 2.0.0.rc.1
320
+ def append(document)
321
+ with_add_callbacks(document, already_related?(document)) do
322
+ _target.push(document)
323
+ characterize_one(document)
324
+ bind_one(document)
325
+ end
326
+ end
327
+
328
+ # Execute before/after add callbacks around the block unless the objects
329
+ # already have a persisted relation.
330
+ #
331
+ # @example Execute before/after add callbacks around the block.
332
+ # relation.with_add_callbacks(document, false)
333
+ #
334
+ # @param [ Document ] document The document to append to the target.
335
+ # @param [ true, false ] already_related Whether the document is already related
336
+ # to the target.
337
+ #
338
+ # @since 5.1.0
339
+ def with_add_callbacks(document, already_related)
340
+ execute_callback :before_add, document unless already_related
341
+ yield
342
+ execute_callback :after_add, document unless already_related
343
+ end
344
+
345
+ # Whether the document and the base already have a persisted relation.
346
+ #
347
+ # @example Is the document already related to the base.
348
+ # relation.already_related?(document)
349
+ #
350
+ # @param [ Document ] document The document to possibly append to the target.
351
+ #
352
+ # @return [ true, false ] Whether the document is already related to the base and the
353
+ # relation is persisted.
354
+ #
355
+ # @since 5.1.0
356
+ def already_related?(document)
357
+ document.persisted? &&
358
+ document._association &&
359
+ document.respond_to?(document._association.foreign_key) &&
360
+ document.__send__(document._association.foreign_key) == _base.id
361
+ end
362
+
363
+ # Instantiate the binding associated with this relation.
364
+ #
365
+ # @example Get the binding.
366
+ # relation.binding([ address ])
367
+ #
368
+ # @return [ Binding ] The binding.
369
+ #
370
+ # @since 2.0.0.rc.1
371
+ def binding
372
+ HasMany::Binding.new(_base, _target, _association)
373
+ end
374
+
375
+ # Get the collection of the relation in question.
376
+ #
377
+ # @example Get the collection of the relation.
378
+ # relation.collection
379
+ #
380
+ # @return [ Collection ] The collection of the relation.
381
+ #
382
+ # @since 2.0.2
383
+ def collection
384
+ klass.collection
385
+ end
386
+
387
+ # Returns the criteria object for the target class with its documents set
388
+ # to target.
389
+ #
390
+ # @example Get a criteria for the relation.
391
+ # relation.criteria
392
+ #
393
+ # @return [ Criteria ] A new criteria.
394
+ #
395
+ # @since 2.0.0.beta.1
396
+ def criteria
397
+ @criteria ||= _association.criteria(_base)
398
+ end
399
+
400
+ # Perform the necessary cascade operations for documents that just got
401
+ # deleted or nullified.
402
+ #
403
+ # @example Cascade the change.
404
+ # relation.cascade!(document)
405
+ #
406
+ # @param [ Document ] document The document to cascade on.
407
+ #
408
+ # @return [ true, false ] If the association is destructive.
409
+ #
410
+ # @since 2.1.0
411
+ def cascade!(document)
412
+ if persistable?
413
+ case _association.dependent
414
+ when :delete_all
415
+ document.delete
416
+ when :destroy
417
+ document.destroy
418
+ else
419
+ document.save
420
+ end
421
+ end
422
+ end
423
+
424
+ # If the target array does not respond to the supplied method then try to
425
+ # find a named scope or criteria on the class and send the call there.
426
+ #
427
+ # If the method exists on the array, use the default proxy behavior.
428
+ #
429
+ # @param [ Symbol, String ] name The name of the method.
430
+ # @param [ Array ] args The method args
431
+ # @param [ Proc ] block Optional block to pass.
432
+ #
433
+ # @return [ Criteria, Object ] A Criteria or return value from the target.
434
+ #
435
+ # @since 2.0.0.beta.1
436
+ def method_missing(name, *args, &block)
437
+ if _target.respond_to?(name)
438
+ _target.send(name, *args, &block)
439
+ else
440
+ klass.send(:with_scope, criteria) do
441
+ criteria.public_send(name, *args, &block)
442
+ end
443
+ end
444
+ end
445
+
446
+ # Persist all the delayed batch inserts.
447
+ #
448
+ # @api private
449
+ #
450
+ # @example Persist the delayed batch inserts.
451
+ # relation.persist_delayed([ doc ])
452
+ #
453
+ # @param [ Array<Document> ] docs The delayed inserts.
454
+ # @param [ Array<Hash> ] inserts The raw insert document.
455
+ #
456
+ # @since 3.0.0
457
+ def persist_delayed(docs, inserts)
458
+ unless docs.empty?
459
+ collection.insert_many(inserts, session: _session)
460
+ docs.each do |doc|
461
+ doc.new_record = false
462
+ doc.run_after_callbacks(:create, :save) unless _association.autosave?
463
+ doc.post_persist
464
+ end
465
+ end
466
+ end
467
+
468
+ # Are we able to persist this relation?
469
+ #
470
+ # @example Can we persist the relation?
471
+ # relation.persistable?
472
+ #
473
+ # @return [ true, false ] If the relation is persistable.
474
+ #
475
+ # @since 2.1.0
476
+ def persistable?
477
+ !_binding? && (_creating? || _base.persisted? && !_building?)
478
+ end
479
+
480
+ # Deletes all related documents from the database given the supplied
481
+ # conditions.
482
+ #
483
+ # @example Delete all documents in the relation.
484
+ # person.posts.delete_all
485
+ #
486
+ # @example Conditonally delete all documents in the relation.
487
+ # person.posts.delete_all({ :title => "Testing" })
488
+ #
489
+ # @param [ Hash ] conditions Optional conditions to delete with.
490
+ # @param [ Symbol ] method The deletion method to call.
491
+ #
492
+ # @return [ Integer ] The number of documents deleted.
493
+ #
494
+ # @since 2.1.0
495
+ def remove_all(conditions = nil, method = :delete_all)
496
+ selector = conditions || {}
497
+ removed = klass.send(method, selector.merge!(criteria.selector))
498
+ _target.delete_if do |doc|
499
+ if doc._matches?(selector)
500
+ unbind_one(doc) and true
501
+ end
502
+ end
503
+ removed
504
+ end
505
+
506
+ # Remove all the documents in the proxy that do not have the provided
507
+ # ids.
508
+ #
509
+ # @example Remove all documents without the ids.
510
+ # proxy.remove_not_in([ id ])
511
+ #
512
+ # @param [ Array<Object> ] ids The ids.
513
+ #
514
+ # @since 2.4.0
515
+ def remove_not_in(ids)
516
+ removed = criteria.not_in(_id: ids)
517
+ if _association.destructive?
518
+ removed.delete_all
519
+ else
520
+ removed.update_all(foreign_key => nil)
521
+ end
522
+ in_memory.each do |doc|
523
+ if !ids.include?(doc._id)
524
+ unbind_one(doc)
525
+ _target.delete(doc)
526
+ if _association.destructive?
527
+ doc.destroyed = true
528
+ end
529
+ end
530
+ end
531
+ end
532
+
533
+ # Save a persisted document immediately or delay a new document for
534
+ # batch insert.
535
+ #
536
+ # @api private
537
+ #
538
+ # @example Save or delay the document.
539
+ # relation.save_or_delay(doc, [])
540
+ #
541
+ # @param [ Document ] doc The document.
542
+ # @param [ Array<Document> ] inserts The inserts.
543
+ #
544
+ # @since 3.0.0
545
+ def save_or_delay(doc, docs, inserts)
546
+ if doc.new_record? && doc.valid?(:create)
547
+ doc.run_before_callbacks(:save, :create)
548
+ docs.push(doc)
549
+ inserts.push(doc.send(:as_attributes))
550
+ else
551
+ doc.save
552
+ end
553
+ end
554
+
555
+ class << self
556
+
557
+ def eager_loader(association, docs)
558
+ Eager.new(association, docs)
559
+ end
560
+
561
+ # Returns true if the relation is an embedded one. In this case
562
+ # always false.
563
+ #
564
+ # @example Is this relation embedded?
565
+ # Referenced::Many.embedded?
566
+ #
567
+ # @return [ false ] Always false.
568
+ #
569
+ # @since 2.0.0.rc.1
570
+ def embedded?
571
+ false
572
+ end
573
+ end
574
+ end
575
+ end
576
+ end
577
+ end
578
+ end