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,552 @@
1
+ require 'mongoid/association/embedded/batchable'
2
+
3
+ module Mongoid
4
+ module Association
5
+ module Embedded
6
+ class EmbedsMany
7
+
8
+ class Proxy < Association::Many
9
+ include Batchable
10
+
11
+ # Appends a document or array of documents to the relation. Will set
12
+ # the parent and update the index in the process.
13
+ #
14
+ # @example Append a document.
15
+ # person.addresses << address
16
+ #
17
+ # @example Push a document.
18
+ # person.addresses.push(address)
19
+ #
20
+ # @param [ Document, Array<Document> ] args Any number of documents.
21
+ def <<(*args)
22
+ docs = args.flatten
23
+ return concat(docs) if docs.size > 1
24
+ if doc = docs.first
25
+ append(doc)
26
+ doc.save if persistable? && !_assigning?
27
+ end
28
+ self
29
+ end
30
+
31
+ alias :push :<<
32
+
33
+ # Get this relation as as its representation in the database.
34
+ #
35
+ # @example Convert the relation to an attributes hash.
36
+ # person.addresses.as_document
37
+ #
38
+ # @return [ Array<Hash> ] The relation as stored in the db.
39
+ #
40
+ # @since 2.0.0.rc.1
41
+ def as_document
42
+ as_attributes.collect { |attrs| BSON::Document.new(attrs) }
43
+ end
44
+
45
+ # Appends an array of documents to the relation. Performs a batch
46
+ # insert of the documents instead of persisting one at a time.
47
+ #
48
+ # @example Concat with other documents.
49
+ # person.addresses.concat([ address_one, address_two ])
50
+ #
51
+ # @param [ Array<Document> ] docs The docs to add.
52
+ #
53
+ # @return [ Array<Document> ] The documents.
54
+ #
55
+ # @since 2.4.0
56
+ def concat(docs)
57
+ batch_insert(docs) unless docs.empty?
58
+ self
59
+ end
60
+
61
+ # Builds a new document in the relation and appends it to the target.
62
+ # Takes an optional type if you want to specify a subclass.
63
+ #
64
+ # @example Build a new document on the relation.
65
+ # person.people.build(:name => "Bozo")
66
+ #
67
+ # @param [ Hash ] attributes The attributes to build the document with.
68
+ # @param [ Class ] type Optional class to build the document with.
69
+ #
70
+ # @return [ Document ] The new document.
71
+ def build(attributes = {}, type = nil)
72
+ doc = Factory.build(type || _association.klass, attributes)
73
+ append(doc)
74
+ doc.apply_post_processed_defaults
75
+ yield(doc) if block_given?
76
+ doc.run_callbacks(:build) { doc }
77
+ _base._reset_memoized_children!
78
+ doc
79
+ end
80
+
81
+ alias :new :build
82
+
83
+ # Clear the relation. Will delete the documents from the db if they are
84
+ # already persisted.
85
+ #
86
+ # @example Clear the relation.
87
+ # person.addresses.clear
88
+ #
89
+ # @return [ self ] The empty relation.
90
+ def clear
91
+ batch_clear(_target.dup)
92
+ self
93
+ end
94
+
95
+ # Returns a count of the number of documents in the association that have
96
+ # actually been persisted to the database.
97
+ #
98
+ # Use #size if you want the total number of documents.
99
+ #
100
+ # @example Get the count of persisted documents.
101
+ # person.addresses.count
102
+ #
103
+ # @return [ Integer ] The total number of persisted embedded docs, as
104
+ # flagged by the #persisted? method.
105
+ def count
106
+ _target.select { |doc| doc.persisted? }.size
107
+ end
108
+
109
+ # Delete the supplied document from the target. This method is proxied
110
+ # in order to reindex the array after the operation occurs.
111
+ #
112
+ # @example Delete the document from the relation.
113
+ # person.addresses.delete(address)
114
+ #
115
+ # @param [ Document ] document The document to be deleted.
116
+ #
117
+ # @return [ Document, nil ] The deleted document or nil if nothing deleted.
118
+ #
119
+ # @since 2.0.0.rc.1
120
+ def delete(document)
121
+ execute_callback :before_remove, document
122
+ doc = _target.delete_one(document)
123
+ if doc && !_binding?
124
+ _unscoped.delete_one(doc)
125
+ if _assigning?
126
+ _base.add_atomic_pull(doc)
127
+ else
128
+ doc.delete(suppress: true)
129
+ unbind_one(doc)
130
+ end
131
+ end
132
+ reindex
133
+ execute_callback :after_remove, document
134
+ doc
135
+ end
136
+
137
+ # Delete all the documents in the association without running callbacks.
138
+ #
139
+ # @example Delete all documents from the relation.
140
+ # person.addresses.delete_all
141
+ #
142
+ # @example Conditionally delete documents from the relation.
143
+ # person.addresses.delete_all({ :street => "Bond" })
144
+ #
145
+ # @param [ Hash ] conditions Conditions on which documents to delete.
146
+ #
147
+ # @return [ Integer ] The number of documents deleted.
148
+ def delete_all(conditions = {})
149
+ remove_all(conditions, :delete)
150
+ end
151
+
152
+ # Delete all the documents for which the provided block returns true.
153
+ #
154
+ # @example Delete the matching documents.
155
+ # person.addresses.delete_if do |doc|
156
+ # doc.state == "GA"
157
+ # end
158
+ #
159
+ # @return [ Many, Enumerator ] The relation or an enumerator if no
160
+ # block was provided.
161
+ #
162
+ # @since 3.1.0
163
+ def delete_if
164
+ if block_given?
165
+ dup_target = _target.dup
166
+ dup_target.each do |doc|
167
+ delete(doc) if yield(doc)
168
+ end
169
+ self
170
+ else
171
+ super
172
+ end
173
+ end
174
+
175
+ # Destroy all the documents in the association whilst running callbacks.
176
+ #
177
+ # @example Destroy all documents from the relation.
178
+ # person.addresses.destroy_all
179
+ #
180
+ # @example Conditionally destroy documents from the relation.
181
+ # person.addresses.destroy_all({ :street => "Bond" })
182
+ #
183
+ # @param [ Hash ] conditions Conditions on which documents to destroy.
184
+ #
185
+ # @return [ Integer ] The number of documents destroyed.
186
+ def destroy_all(conditions = {})
187
+ remove_all(conditions, :destroy)
188
+ end
189
+
190
+ # Determine if any documents in this relation exist in the database.
191
+ #
192
+ # @example Are there persisted documents?
193
+ # person.posts.exists?
194
+ #
195
+ # @return [ true, false ] True is persisted documents exist, false if not.
196
+ def exists?
197
+ count > 0
198
+ end
199
+
200
+ # Finds a document in this association through several different
201
+ # methods.
202
+ #
203
+ # @example Find a document by its id.
204
+ # person.addresses.find(BSON::ObjectId.new)
205
+ #
206
+ # @example Find documents for multiple ids.
207
+ # person.addresses.find([ BSON::ObjectId.new, BSON::ObjectId.new ])
208
+ #
209
+ # @param [ Array<Object> ] args Various arguments.
210
+ #
211
+ # @return [ Array<Document>, Document ] A single or multiple documents.
212
+ def find(*args)
213
+ criteria.find(*args)
214
+ end
215
+
216
+ # Instantiate a new embeds_many relation.
217
+ #
218
+ # @example Create the new relation.
219
+ # Many.new(person, addresses, association)
220
+ #
221
+ # @param [ Document ] base The document this relation hangs off of.
222
+ # @param [ Array<Document> ] target The child documents of the relation.
223
+ # @param [ Association ] association The association metadata
224
+ #
225
+ # @return [ Many ] The proxy.
226
+ def initialize(base, target, association)
227
+ init(base, target, association) do
228
+ _target.each_with_index do |doc, index|
229
+ integrate(doc)
230
+ doc._index = index
231
+ end
232
+ @_unscoped = _target.dup
233
+ @_target = scope(_target)
234
+ end
235
+ end
236
+
237
+ # Get all the documents in the relation that are loaded into memory.
238
+ #
239
+ # @example Get the in memory documents.
240
+ # relation.in_memory
241
+ #
242
+ # @return [ Array<Document> ] The documents in memory.
243
+ #
244
+ # @since 2.1.0
245
+ def in_memory
246
+ _target
247
+ end
248
+
249
+ # Pop documents off the relation. This can be a single document or
250
+ # multiples, and will automatically persist the changes.
251
+ #
252
+ # @example Pop a single document.
253
+ # relation.pop
254
+ #
255
+ # @example Pop multiple documents.
256
+ # relation.pop(3)
257
+ #
258
+ # @param [ Integer ] count The number of documents to pop, or 1 if not
259
+ # provided.
260
+ #
261
+ # @return [ Document, Array<Document> ] The popped document(s).
262
+ #
263
+ # @since 3.0.0
264
+ def pop(count = nil)
265
+ if count
266
+ if docs = _target[_target.size - count, _target.size]
267
+ docs.each { |doc| delete(doc) }
268
+ end
269
+ else
270
+ delete(_target[-1])
271
+ end
272
+ end
273
+
274
+ # Shift documents off the relation. This can be a single document or
275
+ # multiples, and will automatically persist the changes.
276
+ #
277
+ # @example Shift a single document.
278
+ # relation.shift
279
+ #
280
+ # @example Shift multiple documents.
281
+ # relation.shift(3)
282
+ #
283
+ # @param [ Integer ] count The number of documents to shift, or 1 if not
284
+ # provided.
285
+ #
286
+ # @return [ Document, Array<Document> ] The shifted document(s).
287
+ def shift(count = nil)
288
+ if count
289
+ if _target.size > 0 && docs = _target[0, count]
290
+ docs.each { |doc| delete(doc) }
291
+ end
292
+ else
293
+ delete(_target[0])
294
+ end
295
+ end
296
+
297
+ # Substitutes the supplied target documents for the existing documents
298
+ # in the relation.
299
+ #
300
+ # @example Substitute the relation's target.
301
+ # person.addresses.substitute([ address ])
302
+ #
303
+ # @param [ Array<Document> ] docs The replacement docs.
304
+ #
305
+ # @return [ Many ] The proxied relation.
306
+ #
307
+ # @since 2.0.0.rc.1
308
+ def substitute(docs)
309
+ batch_replace(docs)
310
+ self
311
+ end
312
+
313
+ # Return the relation with all previous scoping removed. This is the
314
+ # exact representation of the docs in the database.
315
+ #
316
+ # @example Get the unscoped documents.
317
+ # person.addresses.unscoped
318
+ #
319
+ # @return [ Criteria ] The unscoped relation.
320
+ #
321
+ # @since 2.4.0
322
+ def unscoped
323
+ criterion = klass.unscoped
324
+ criterion.embedded = true
325
+ criterion.documents = _unscoped.delete_if(&:marked_for_destruction?)
326
+ criterion
327
+ end
328
+
329
+ private
330
+
331
+ def object_already_related?(document)
332
+ _target.any? { |existing| existing.id && existing === document }
333
+ end
334
+
335
+ # Appends the document to the target array, updating the index on the
336
+ # document at the same time.
337
+ #
338
+ # @example Append to the document.
339
+ # relation.append(document)
340
+ #
341
+ # @param [ Document ] document The document to append to the target.
342
+ #
343
+ # @since 2.0.0.rc.1
344
+ def append(document)
345
+ execute_callback :before_add, document
346
+ unless object_already_related?(document)
347
+ _target.push(*scope([document]))
348
+ end
349
+ _unscoped.push(document)
350
+ integrate(document)
351
+ document._index = _unscoped.size - 1
352
+ execute_callback :after_add, document
353
+ end
354
+
355
+ # Instantiate the binding associated with this relation.
356
+ #
357
+ # @example Create the binding.
358
+ # relation.binding([ address ])
359
+ #
360
+ # @return [ Binding ] The many binding.
361
+ #
362
+ # @since 2.0.0.rc.1
363
+ def binding
364
+ Binding.new(_base, _target, _association)
365
+ end
366
+
367
+ # Returns the "#{criteria}"# object for the target class with its documents set
368
+ # to target.
369
+ #
370
+ # @example Get a criteria for the relation.
371
+ # relation.criteria
372
+ #
373
+ # @return [ Criteria ] A new criteria.
374
+ def criteria
375
+ @criteria ||= _association.criteria(_base, _target)
376
+ end
377
+
378
+ # Deletes one document from the target and unscoped.
379
+ #
380
+ # @api private
381
+ #
382
+ # @example Delete one document.
383
+ # relation.delete_one(doc)
384
+ #
385
+ # @param [ Document ] document The document to delete.
386
+ #
387
+ # @since 2.4.7
388
+ def delete_one(document)
389
+ _target.delete_one(document)
390
+ _unscoped.delete_one(document)
391
+ reindex
392
+ end
393
+
394
+ # Integrate the document into the relation. will set its metadata and
395
+ # attempt to bind the inverse.
396
+ #
397
+ # @example Integrate the document.
398
+ # relation.integrate(document)
399
+ #
400
+ # @param [ Document ] document The document to integrate.
401
+ #
402
+ # @since 2.1.0
403
+ def integrate(document)
404
+ characterize_one(document)
405
+ bind_one(document)
406
+ end
407
+
408
+ # If the target array does not respond to the supplied method then try to
409
+ # find a named scope or criteria on the class and send the call there.
410
+ #
411
+ # If the method exists on the array, use the default proxy behavior.
412
+ #
413
+ # @param [ Symbol, String ] name The name of the method.
414
+ # @param [ Array ] args The method args
415
+ # @param [ Proc ] block Optional block to pass.
416
+ #
417
+ # @return [ Criteria, Object ] A Criteria or return value from the target.
418
+ def method_missing(name, *args, &block)
419
+ return super if _target.respond_to?(name)
420
+ klass.send(:with_scope, criteria) do
421
+ criteria.public_send(name, *args, &block)
422
+ end
423
+ end
424
+
425
+ # Are we able to persist this relation?
426
+ #
427
+ # @example Can we persist the relation?
428
+ # relation.persistable?
429
+ #
430
+ # @return [ true, false ] If the relation is persistable.
431
+ #
432
+ # @since 2.1.0
433
+ def persistable?
434
+ _base.persisted? && !_binding?
435
+ end
436
+
437
+ # Reindex all the target elements. This is useful when performing
438
+ # operations on the proxied target directly and the indices need to
439
+ # match that on the database side.
440
+ #
441
+ # @example Reindex the relation.
442
+ # person.addresses.reindex
443
+ #
444
+ # @since 2.0.0.rc.1
445
+ def reindex
446
+ _unscoped.each_with_index do |doc, index|
447
+ doc._index = index
448
+ end
449
+ end
450
+
451
+ # Apply the association ordering or the default scoping to the provided
452
+ # documents.
453
+ #
454
+ # @example Apply scoping.
455
+ # person.addresses.scope(target)
456
+ #
457
+ # @param [ Array<Document> ] docs The documents to scope.
458
+ #
459
+ # @return [ Array<Document> ] The scoped docs.
460
+ #
461
+ # @since 2.4.0
462
+ def scope(docs)
463
+ return docs unless _association.order || _association.klass.default_scoping?
464
+ crit = _association.klass.order_by(_association.order)
465
+ crit.embedded = true
466
+ crit.documents = docs
467
+ crit.entries
468
+ end
469
+
470
+ # Remove all documents from the relation, either with a delete or a
471
+ # destroy depending on what this was called through.
472
+ #
473
+ # @example Destroy documents from the relation.
474
+ # relation.remove_all({ :num => 1 }, true)
475
+ #
476
+ # @param [ Hash ] conditions Conditions to filter by.
477
+ # @param [ true, false ] method :delete or :destroy.
478
+ #
479
+ # @return [ Integer ] The number of documents removed.
480
+ def remove_all(conditions = {}, method = :delete)
481
+ criteria = where(conditions || {})
482
+ removed = criteria.size
483
+ batch_remove(criteria, method)
484
+ removed
485
+ end
486
+
487
+ # Get the internal unscoped documents.
488
+ #
489
+ # @example Get the unscoped documents.
490
+ # relation._unscoped
491
+ #
492
+ # @return [ Array<Document> ] The unscoped documents.
493
+ #
494
+ # @since 2.4.0
495
+ def _unscoped
496
+ @_unscoped ||= []
497
+ end
498
+
499
+ # Set the internal unscoped documents.
500
+ #
501
+ # @example Set the unscoped documents.
502
+ # relation._unscoped = docs
503
+ #
504
+ # @param [ Array<Document> ] docs The documents.
505
+ #
506
+ # @return [ Array<Document ] The unscoped docs.
507
+ #
508
+ # @since 2.4.0
509
+ def _unscoped=(docs)
510
+ @_unscoped = docs
511
+ end
512
+
513
+ def as_attributes
514
+ attributes = []
515
+ _unscoped.each do |doc|
516
+ attributes.push(doc.as_document)
517
+ end
518
+ attributes
519
+ end
520
+
521
+ class << self
522
+
523
+ # Returns true if the relation is an embedded one. In this case
524
+ # always true.
525
+ #
526
+ # @example Is the relation embedded?
527
+ # Association::Embedded::EmbedsMany.embedded?
528
+ #
529
+ # @return [ true ] true.
530
+ #
531
+ # @since 2.0.0.rc.1
532
+ def embedded?
533
+ true
534
+ end
535
+
536
+ # Returns the suffix of the foreign key field, either "_id" or "_ids".
537
+ #
538
+ # @example Get the suffix for the foreign key.
539
+ # Association::Embedded::EmbedsMany.foreign_key_suffix
540
+ #
541
+ # @return [ nil ] nil.
542
+ #
543
+ # @since 3.0.0
544
+ def foreign_key_suffix
545
+ nil
546
+ end
547
+ end
548
+ end
549
+ end
550
+ end
551
+ end
552
+ end