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,312 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Association
4
+ module Referenced
5
+ class HasAndBelongsToMany
6
+
7
+ # This class defines the behaviour for all relations that are a
8
+ # many-to-many between documents in different collections.
9
+ class Proxy < Referenced::HasMany::Proxy
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.posts << post
16
+ #
17
+ # @example Push a document.
18
+ # person.posts.push(post)
19
+ #
20
+ # @example Concat with other documents.
21
+ # person.posts.concat([ post_one, post_two ])
22
+ #
23
+ # @param [ Document, Array<Document> ] args Any number of documents.
24
+ #
25
+ # @return [ Array<Document> ] The loaded docs.
26
+ #
27
+ # @since 2.0.0.beta.1
28
+ def <<(*args)
29
+ docs = args.flatten
30
+ return concat(docs) if docs.size > 1
31
+ if doc = docs.first
32
+ append(doc)
33
+ _base.add_to_set(foreign_key => doc.send(_association.primary_key))
34
+ if child_persistable?(doc)
35
+ doc.save
36
+ end
37
+ end
38
+ unsynced(_base, foreign_key) and 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
+ ids, docs, inserts = {}, [], []
56
+ documents.each do |doc|
57
+ next unless doc
58
+ append(doc)
59
+ if persistable? || _creating?
60
+ ids[doc._id] = true
61
+ save_or_delay(doc, docs, inserts)
62
+ else
63
+ existing = _base.send(foreign_key)
64
+ unless existing.include?(doc._id)
65
+ existing.push(doc._id) and unsynced(_base, foreign_key)
66
+ end
67
+ end
68
+ end
69
+ if persistable? || _creating?
70
+ _base.push(foreign_key => ids.keys)
71
+ end
72
+ persist_delayed(docs, inserts)
73
+ self
74
+ end
75
+
76
+ # Build a new document from the attributes and append it to this
77
+ # relation without saving.
78
+ #
79
+ # @example Build a new document on the relation.
80
+ # person.posts.build(:title => "A new post")
81
+ #
82
+ # @param [ Hash ] attributes The attributes of the new document.
83
+ # @param [ Class ] type The optional subclass to build.
84
+ #
85
+ # @return [ Document ] The new document.
86
+ #
87
+ # @since 2.0.0.beta.1
88
+ def build(attributes = {}, type = nil)
89
+ doc = Factory.build(type || klass, attributes)
90
+ _base.send(foreign_key).push(doc._id)
91
+ append(doc)
92
+ doc.apply_post_processed_defaults
93
+ unsynced(doc, inverse_foreign_key)
94
+ yield(doc) if block_given?
95
+ doc
96
+ end
97
+
98
+ alias :new :build
99
+
100
+ # Delete the document from the relation. This will set the foreign key
101
+ # on the document to nil. If the dependent options on the relation are
102
+ # :delete or :destroy the appropriate removal will occur.
103
+ #
104
+ # @example Delete the document.
105
+ # person.posts.delete(post)
106
+ #
107
+ # @param [ Document ] document The document to remove.
108
+ #
109
+ # @return [ Document ] The matching document.
110
+ #
111
+ # @since 2.1.0
112
+ def delete(document)
113
+ doc = super
114
+ if doc && persistable?
115
+ _base.pull(foreign_key => doc.send(_association.primary_key))
116
+ _target._unloaded = criteria
117
+ unsynced(_base, foreign_key)
118
+ end
119
+ doc
120
+ end
121
+
122
+ # Removes all associations between the base document and the target
123
+ # documents by deleting the foreign keys and the references, orphaning
124
+ # the target documents in the process.
125
+ #
126
+ # @example Nullify the relation.
127
+ # person.preferences.nullify
128
+ #
129
+ # @param [ Array<Document> ] replacement The replacement documents.
130
+ #
131
+ # @since 2.0.0.rc.1
132
+ def nullify(replacement = [])
133
+ _target.each do |doc|
134
+ execute_callback :before_remove, doc
135
+ end
136
+ unless _association.forced_nil_inverse?
137
+ if replacement
138
+ objects_to_clear = _base.send(foreign_key) - replacement.collect do |object|
139
+ object.send(_association.primary_key)
140
+ end
141
+ criteria(objects_to_clear).pull(inverse_foreign_key => _base._id)
142
+ else
143
+ criteria.pull(inverse_foreign_key => _base._id)
144
+ end
145
+ end
146
+ if persistable?
147
+ _base.set(foreign_key => _base.send(foreign_key).clear)
148
+ end
149
+ after_remove_error = nil
150
+ many_to_many = _target.clear do |doc|
151
+ unbind_one(doc)
152
+ unless _association.forced_nil_inverse?
153
+ doc.changed_attributes.delete(inverse_foreign_key)
154
+ end
155
+ begin
156
+ execute_callback :after_remove, doc
157
+ rescue => e
158
+ after_remove_error = e
159
+ end
160
+ end
161
+ raise after_remove_error if after_remove_error
162
+ many_to_many
163
+ end
164
+
165
+ alias :nullify_all :nullify
166
+ alias :clear :nullify
167
+ alias :purge :nullify
168
+
169
+ # Substitutes the supplied target documents for the existing documents
170
+ # in the relation. If the new target is nil, perform the necessary
171
+ # deletion.
172
+ #
173
+ # @example Replace the relation.
174
+ # person.preferences.substitute([ new_post ])
175
+ #
176
+ # @param [ Array<Document> ] replacement The replacement target.
177
+ #
178
+ # @return [ Many ] The relation.
179
+ #
180
+ # @since 2.0.0.rc.1
181
+ def substitute(replacement)
182
+ purge(replacement)
183
+ unless replacement.blank?
184
+ push(replacement.compact.uniq)
185
+ else
186
+ reset_unloaded
187
+ end
188
+ self
189
+ end
190
+
191
+ # Get a criteria for the documents without the default scoping
192
+ # applied.
193
+ #
194
+ # @example Get the unscoped criteria.
195
+ # person.preferences.unscoped
196
+ #
197
+ # @return [ Criteria ] The unscoped criteria.
198
+ #
199
+ # @since 2.4.0
200
+ def unscoped
201
+ klass.unscoped.any_in(_id: _base.send(foreign_key))
202
+ end
203
+
204
+ private
205
+
206
+ # Appends the document to the target array, updating the index on the
207
+ # document at the same time.
208
+ #
209
+ # @example Append the document to the relation.
210
+ # relation.append(document)
211
+ #
212
+ # @param [ Document ] document The document to append to the target.
213
+ #
214
+ # @since 2.0.0.rc.1
215
+ def append(document)
216
+ execute_callback :before_add, document
217
+ _target.push(document)
218
+ characterize_one(document)
219
+ bind_one(document)
220
+ execute_callback :after_add, document
221
+ end
222
+
223
+ # Instantiate the binding associated with this relation.
224
+ #
225
+ # @example Get the binding.
226
+ # relation.binding([ address ])
227
+ #
228
+ # @return [ Binding ] The binding.
229
+ #
230
+ # @since 2.0.0.rc.1
231
+ def binding
232
+ HasAndBelongsToMany::Binding.new(_base, _target, _association)
233
+ end
234
+
235
+ # Determine if the child document should be persisted.
236
+ #
237
+ # @api private
238
+ #
239
+ # @example Is the child persistable?
240
+ # relation.child_persistable?(doc)
241
+ #
242
+ # @param [ Document ] doc The document.
243
+ #
244
+ # @return [ true, false ] If the document can be persisted.
245
+ #
246
+ # @since 3.0.20
247
+ def child_persistable?(doc)
248
+ (persistable? || _creating?) &&
249
+ !(doc.persisted? && _association.forced_nil_inverse?)
250
+ end
251
+
252
+ # Returns the criteria object for the target class with its documents set
253
+ # to target.
254
+ #
255
+ # @example Get a criteria for the relation.
256
+ # relation.criteria
257
+ #
258
+ # @return [ Criteria ] A new criteria.
259
+ def criteria(id_list = nil)
260
+ _association.criteria(_base, id_list)
261
+ end
262
+
263
+ # Flag the base as unsynced with respect to the foreign key.
264
+ #
265
+ # @api private
266
+ #
267
+ # @example Flag as unsynced.
268
+ # relation.unsynced(doc, :preference_ids)
269
+ #
270
+ # @param [ Document ] doc The document to flag.
271
+ # @param [ Symbol ] key The key to flag on the document.
272
+ #
273
+ # @return [ true ] true.
274
+ #
275
+ # @since 3.0.0
276
+ def unsynced(doc, key)
277
+ doc._synced[key] = false
278
+ true
279
+ end
280
+
281
+ class << self
282
+
283
+ # Get the Eager object for this type of association.
284
+ #
285
+ # @example Get the eager loader object
286
+ #
287
+ # @param [ Association ] association The association object.
288
+ # @param [ Array<Document> ] docs The array of documents.
289
+ #
290
+ # @since 7.0
291
+ def eager_loader(association, docs)
292
+ Eager.new(association, docs)
293
+ end
294
+
295
+ # Returns true if the relation is an embedded one. In this case
296
+ # always false.
297
+ #
298
+ # @example Is this relation embedded?
299
+ # Referenced::ManyToMany.embedded?
300
+ #
301
+ # @return [ false ] Always false.
302
+ #
303
+ # @since 2.0.0.rc.1
304
+ def embedded?
305
+ false
306
+ end
307
+ end
308
+ end
309
+ end
310
+ end
311
+ end
312
+ end
@@ -0,0 +1,290 @@
1
+ require 'mongoid/association/referenced/has_and_belongs_to_many/binding'
2
+ require 'mongoid/association/referenced/has_and_belongs_to_many/buildable'
3
+ require 'mongoid/association/referenced/has_and_belongs_to_many/proxy'
4
+ require 'mongoid/association/referenced/has_and_belongs_to_many/eager'
5
+
6
+ module Mongoid
7
+ module Association
8
+ module Referenced
9
+
10
+ # The HasAndBelongsToMany type association.
11
+ #
12
+ # @since 7.0
13
+ class HasAndBelongsToMany
14
+ include Relatable
15
+ include Buildable
16
+
17
+ # The options available for this type of association, in addition to the
18
+ # common ones.
19
+ #
20
+ # @return [ Array<Symbol> ] The extra valid options.
21
+ #
22
+ # @since 7.0
23
+ ASSOCIATION_OPTIONS = [
24
+ :after_add,
25
+ :after_remove,
26
+ :autosave,
27
+ :before_add,
28
+ :before_remove,
29
+ :counter_cache,
30
+ :dependent,
31
+ :foreign_key,
32
+ :index,
33
+ :order,
34
+ :primary_key
35
+ ].freeze
36
+
37
+ # The complete list of valid options for this association, including
38
+ # the shared ones.
39
+ #
40
+ # @return [ Array<Symbol> ] The valid options.
41
+ #
42
+ # @since 7.0
43
+ VALID_OPTIONS = (ASSOCIATION_OPTIONS + SHARED_OPTIONS).freeze
44
+
45
+ # The type of the field holding the foreign key.
46
+ #
47
+ # @return [ Array ]
48
+ #
49
+ # @since 7.0
50
+ FOREIGN_KEY_FIELD_TYPE = Array
51
+
52
+ # The default foreign key suffix.
53
+ #
54
+ # @return [ String ] '_ids'
55
+ #
56
+ # @since 7.0
57
+ FOREIGN_KEY_SUFFIX = '_ids'.freeze
58
+
59
+ # The list of association complements.
60
+ #
61
+ # @return [ Array<Association> ] The association complements.
62
+ #
63
+ # @since 7.0
64
+ def relation_complements
65
+ @relation_complements ||= [ self.class ].freeze
66
+ end
67
+
68
+ # Setup the instance methods, fields, etc. on the association owning class.
69
+ #
70
+ # @return [ self ]
71
+ #
72
+ # @since 7.0
73
+ def setup!
74
+ setup_instance_methods!
75
+ self
76
+ end
77
+
78
+ # Is this association type embedded?
79
+ #
80
+ # @return [ false ] Always false.
81
+ #
82
+ # @since 7.0
83
+ def embedded?; false; end
84
+
85
+ # The default for validation the association object.
86
+ #
87
+ # @return [ false ] Always false.
88
+ #
89
+ # @since 7.0
90
+ def validation_default; true; end
91
+
92
+ # Are ids only saved on this side of the relation?
93
+ #
94
+ # @return [ true, false ] Whether this association has a forced nil inverse.
95
+ #
96
+ # @since 7.0
97
+ def forced_nil_inverse?
98
+ @forced_nil_inverse ||= @options.key?(:inverse_of) && !@options[:inverse_of]
99
+ end
100
+
101
+ # Does this association type store the foreign key?
102
+ #
103
+ # @return [ true ] Always true.
104
+ #
105
+ # @since 7.0
106
+ def stores_foreign_key?; true; end
107
+
108
+ # Get the relation proxy class for this association type.
109
+ #
110
+ # @return [ Association::HasAndBelongsToMany::Proxy ] The proxy class.
111
+ #
112
+ # @since 7.0
113
+ def relation
114
+ Proxy
115
+ end
116
+
117
+ # Get the foreign key field for saving the association reference.
118
+ #
119
+ # @return [ String ] The foreign key field for saving the association reference.
120
+ #
121
+ # @since 7.0
122
+ def foreign_key
123
+ @foreign_key ||= @options[:foreign_key] ? @options[:foreign_key].to_s :
124
+ default_foreign_key_field
125
+ end
126
+
127
+ # The criteria used for querying this relation.
128
+ #
129
+ # @return [ Mongoid::Criteria ] The criteria used for querying this relation.
130
+ #
131
+ # @since 7.0
132
+ def criteria(base, id_list = nil)
133
+ query_criteria(id_list || base.send(foreign_key))
134
+ end
135
+
136
+ # Get the foreign key field on the inverse.
137
+ #
138
+ # @return [ String ] The foreign key field for saving the association reference
139
+ # on the inverse side.
140
+ #
141
+ # @since 7.0
142
+ def inverse_foreign_key
143
+ if @options.key?(:inverse_of)
144
+ inverse_of ? "#{inverse_of.to_s.singularize}#{FOREIGN_KEY_SUFFIX}" : nil
145
+ else
146
+ "#{inverse_class_name.demodulize.underscore}#{FOREIGN_KEY_SUFFIX}"
147
+ end
148
+ end
149
+
150
+ # Whether trying to bind an object using this association should raise
151
+ # an error.
152
+ #
153
+ # @param [ Document ] doc The document to be bound.
154
+ #
155
+ # @return [ true, false ] Whether the document can be bound.
156
+ def bindable?(doc)
157
+ forced_nil_inverse? || (!!inverse && doc.fields.keys.include?(foreign_key))
158
+ end
159
+
160
+ # Get the foreign key setter on the inverse.
161
+ #
162
+ # @return [ String ] The foreign key setter for saving the association reference
163
+ # on the inverse side.
164
+ #
165
+ # @since 7.0
166
+ def inverse_foreign_key_setter
167
+ @inverse_foreign_key_setter ||= "#{inverse_foreign_key}=" if inverse_foreign_key
168
+ end
169
+
170
+ # The nested builder object.
171
+ #
172
+ # @param [ Hash ] attributes The attributes to use to build the association object.
173
+ # @param [ Hash ] options The options for the association.
174
+ #
175
+ # @return [ Association::Nested::One ] The Nested Builder object.
176
+ #
177
+ # @since 7.0
178
+ def nested_builder(attributes, options)
179
+ Nested::Many.new(self, attributes, options)
180
+ end
181
+
182
+ # Get the path calculator for the supplied document.
183
+ #
184
+ # @example Get the path calculator.
185
+ # association.path(document)
186
+ #
187
+ # @param [ Document ] document The document to calculate on.
188
+ #
189
+ # @return [ Root ] The root atomic path calculator.
190
+ #
191
+ # @since 2.1.0
192
+ def path(document)
193
+ Mongoid::Atomic::Paths::Root.new(document)
194
+ end
195
+
196
+ private
197
+
198
+ def setup_instance_methods!
199
+ define_getter!
200
+ define_setter!
201
+ define_dependency!
202
+ define_existence_check!
203
+ define_autosaver!
204
+ define_counter_cache_callbacks!
205
+ create_foreign_key_field!
206
+ setup_index!
207
+ setup_syncing!
208
+ @owner_class.validates_associated(name) if validate?
209
+ self
210
+ end
211
+
212
+ def index_spec
213
+ { key => 1 }
214
+ end
215
+
216
+ def default_primary_key
217
+ PRIMARY_KEY_DEFAULT
218
+ end
219
+
220
+ def default_foreign_key_field
221
+ @default_foreign_key_field ||= "#{name.to_s.singularize}#{FOREIGN_KEY_SUFFIX}"
222
+ end
223
+
224
+ def setup_syncing!
225
+ unless forced_nil_inverse?
226
+ synced_save
227
+ synced_destroy
228
+ end
229
+ end
230
+
231
+ def synced_destroy
232
+ assoc = self
233
+ inverse_class.set_callback(
234
+ :destroy,
235
+ :after
236
+ ) do |doc|
237
+ doc.remove_inverse_keys(assoc)
238
+ end
239
+ end
240
+
241
+ def synced_save
242
+ assoc = self
243
+ inverse_class.set_callback(
244
+ :save,
245
+ :after,
246
+ if: ->(doc){ doc._syncable?(assoc) }
247
+ ) do |doc|
248
+ doc.update_inverse_keys(assoc)
249
+ end
250
+ end
251
+
252
+ def create_foreign_key_field!
253
+ @owner_class.field(
254
+ foreign_key,
255
+ type: FOREIGN_KEY_FIELD_TYPE,
256
+ identity: true,
257
+ overwrite: true,
258
+ association: self,
259
+ default: nil
260
+ )
261
+ end
262
+
263
+ def determine_inverses(other)
264
+ matches = (other || relation_class).relations.values.select do |rel|
265
+ relation_complements.include?(rel.class) &&
266
+ rel.relation_class_name == inverse_class_name
267
+
268
+ end
269
+ if matches.size > 1
270
+ raise Errors::AmbiguousRelationship.new(relation_class, @owner_class, name, matches)
271
+ end
272
+ matches.collect { |m| m.name } unless matches.blank?
273
+ end
274
+
275
+ def with_ordering(criteria)
276
+ if order
277
+ criteria.order_by(order)
278
+ else
279
+ criteria
280
+ end
281
+ end
282
+
283
+ def query_criteria(id_list)
284
+ crit = relation_class.all_of(primary_key => {"$in" => id_list || []})
285
+ with_ordering(crit)
286
+ end
287
+ end
288
+ end
289
+ end
290
+ end
@@ -1,11 +1,12 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid
3
- module Relations
4
- module Bindings
5
- module Referenced
3
+ module Association
4
+ module Referenced
5
+ class HasMany
6
6
 
7
- # Binding class for references_many relations.
8
- class Many < Binding
7
+ # Binding class for has_many associations.
8
+ class Binding
9
+ include Bindable
9
10
 
10
11
  # Binds a single document with the inverse relation. Used
11
12
  # specifically when appending to the proxy.
@@ -0,0 +1,38 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Association
4
+ module Referenced
5
+ class HasMany
6
+
7
+ # The Builder behavior for has_many associations.
8
+ #
9
+ # @since 7.0
10
+ module Buildable
11
+
12
+ # This method either takes an _id or an object and queries for the
13
+ # inverse side using the id or sets the object.
14
+ #
15
+ # @example Build the document.
16
+ # relation.build(meta, attrs)
17
+ #
18
+ # @param [ Object ] base The base object.
19
+ # @param [ Object ] object The object to use to build the relation.
20
+ # @param [ String ] type The type of document to query for.
21
+ #
22
+ # @return [ Document ] A single document.
23
+ def build(base, object, type = nil)
24
+ return (object || []) unless query?(object)
25
+ return [] if object.is_a?(Array)
26
+ query_criteria(object, base)
27
+ end
28
+
29
+ private
30
+
31
+ def query?(object)
32
+ object && Array(object).all? { |d| !d.is_a?(Mongoid::Document) }
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Association
4
+ module Referenced
5
+ class HasMany
6
+
7
+ # Eager class for has_many associations.
8
+ class Eager < Association::Referenced::Eager::Base
9
+
10
+ private
11
+
12
+ def preload
13
+ @docs.each do |d|
14
+ set_relation(d, [])
15
+ end
16
+
17
+ entries = Hash.new { |hash, key| hash[key] = [] }
18
+ each_loaded_document do |doc|
19
+ fk = doc.send(key)
20
+ entries[fk] << doc
21
+ end
22
+
23
+ entries.each do |id, docs|
24
+ set_on_parent(id, docs)
25
+ end
26
+ end
27
+
28
+ def set_relation(doc, element)
29
+ doc.__build__(@association.name, element, @association) unless doc.blank?
30
+ end
31
+
32
+ def group_by_key
33
+ @association.primary_key
34
+ end
35
+
36
+ def key
37
+ @association.foreign_key
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end