mongoid 6.4.8 → 7.0.0.beta

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 (315) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +0 -26
  5. data/lib/config/locales/en.yml +17 -21
  6. data/lib/mongoid.rb +2 -2
  7. data/lib/mongoid/association.rb +150 -0
  8. data/lib/mongoid/association/accessors.rb +339 -0
  9. data/lib/mongoid/{relations/binding.rb → association/bindable.rb} +32 -52
  10. data/lib/mongoid/association/builders.rb +92 -0
  11. data/lib/mongoid/{relations/constraint.rb → association/constrainable.rb} +11 -22
  12. data/lib/mongoid/association/depending.rb +116 -0
  13. data/lib/mongoid/{relations/eager.rb → association/eager_loadable.rb} +11 -11
  14. data/lib/mongoid/association/embedded.rb +4 -0
  15. data/lib/mongoid/{relations → association}/embedded/batchable.rb +27 -53
  16. data/lib/mongoid/association/embedded/cyclic.rb +109 -0
  17. data/lib/mongoid/association/embedded/embedded_in.rb +154 -0
  18. data/lib/mongoid/association/embedded/embedded_in/binding.rb +56 -0
  19. data/lib/mongoid/{relations/builders/embedded/in.rb → association/embedded/embedded_in/buildable.rb} +12 -6
  20. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +121 -0
  21. data/lib/mongoid/association/embedded/embeds_many.rb +210 -0
  22. data/lib/mongoid/{relations/bindings/embedded/many.rb → association/embedded/embeds_many/binding.rb} +11 -9
  23. data/lib/mongoid/{relations/builders/embedded/many.rb → association/embedded/embeds_many/buildable.rb} +13 -7
  24. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +529 -0
  25. data/lib/mongoid/association/embedded/embeds_one.rb +173 -0
  26. data/lib/mongoid/{relations/bindings/embedded/one.rb → association/embedded/embeds_one/binding.rb} +12 -10
  27. data/lib/mongoid/{relations/builders/embedded/one.rb → association/embedded/embeds_one/buildable.rb} +13 -7
  28. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +130 -0
  29. data/lib/mongoid/association/macros.rb +204 -0
  30. data/lib/mongoid/{relations → association}/many.rb +18 -52
  31. data/lib/mongoid/{relations → association}/marshalable.rb +6 -4
  32. data/lib/mongoid/association/nested.rb +15 -0
  33. data/lib/mongoid/association/nested/many.rb +200 -0
  34. data/lib/mongoid/association/nested/nested_buildable.rb +72 -0
  35. data/lib/mongoid/association/nested/one.rb +127 -0
  36. data/lib/mongoid/{relations → association}/one.rb +6 -6
  37. data/lib/mongoid/association/options.rb +152 -0
  38. data/lib/mongoid/{relations → association}/proxy.rb +31 -58
  39. data/lib/mongoid/association/referenced.rb +7 -0
  40. data/lib/mongoid/association/referenced/auto_save.rb +79 -0
  41. data/lib/mongoid/association/referenced/belongs_to.rb +248 -0
  42. data/lib/mongoid/association/referenced/belongs_to/binding.rb +87 -0
  43. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +46 -0
  44. data/lib/mongoid/association/referenced/belongs_to/eager.rb +36 -0
  45. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +136 -0
  46. data/lib/mongoid/association/referenced/counter_cache.rb +163 -0
  47. data/lib/mongoid/association/referenced/eager.rb +159 -0
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +290 -0
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +71 -0
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +40 -0
  51. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +52 -0
  52. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +310 -0
  53. data/lib/mongoid/association/referenced/has_many.rb +273 -0
  54. data/lib/mongoid/{relations/bindings/referenced/many.rb → association/referenced/has_many/binding.rb} +6 -5
  55. data/lib/mongoid/association/referenced/has_many/buildable.rb +38 -0
  56. data/lib/mongoid/association/referenced/has_many/eager.rb +43 -0
  57. data/lib/mongoid/association/referenced/has_many/enumerable.rb +479 -0
  58. data/lib/mongoid/association/referenced/has_many/proxy.rb +577 -0
  59. data/lib/mongoid/association/referenced/has_one.rb +204 -0
  60. data/lib/mongoid/{relations/bindings/referenced/one.rb → association/referenced/has_one/binding.rb} +11 -8
  61. data/lib/mongoid/association/referenced/has_one/buildable.rb +60 -0
  62. data/lib/mongoid/association/referenced/has_one/eager.rb +35 -0
  63. data/lib/mongoid/{relations/builders/nested_attributes/one.rb → association/referenced/has_one/nested_builder.rb} +9 -9
  64. data/lib/mongoid/association/referenced/has_one/proxy.rb +113 -0
  65. data/lib/mongoid/association/referenced/syncable.rb +170 -0
  66. data/lib/mongoid/{relations → association}/reflections.rb +21 -17
  67. data/lib/mongoid/association/relatable.rb +415 -0
  68. data/lib/mongoid/association/touchable.rb +97 -0
  69. data/lib/mongoid/atomic.rb +6 -6
  70. data/lib/mongoid/atomic/modifiers.rb +8 -12
  71. data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
  72. data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
  73. data/lib/mongoid/attributes.rb +2 -1
  74. data/lib/mongoid/attributes/nested.rb +10 -10
  75. data/lib/mongoid/attributes/processing.rb +2 -2
  76. data/lib/mongoid/attributes/readonly.rb +2 -4
  77. data/lib/mongoid/clients.rb +0 -2
  78. data/lib/mongoid/clients/options.rb +1 -1
  79. data/lib/mongoid/clients/storage_options.rb +0 -1
  80. data/lib/mongoid/composable.rb +3 -4
  81. data/lib/mongoid/config.rb +1 -0
  82. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  83. data/lib/mongoid/contextual/atomic.rb +3 -6
  84. data/lib/mongoid/contextual/map_reduce.rb +3 -7
  85. data/lib/mongoid/contextual/memory.rb +5 -10
  86. data/lib/mongoid/contextual/mongo.rb +10 -27
  87. data/lib/mongoid/copyable.rb +6 -6
  88. data/lib/mongoid/criteria.rb +1 -2
  89. data/lib/mongoid/criteria/includable.rb +14 -14
  90. data/lib/mongoid/criteria/modifiable.rb +8 -14
  91. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -3
  92. data/lib/mongoid/criteria/queryable/pipeline.rb +10 -5
  93. data/lib/mongoid/criteria/queryable/selectable.rb +10 -34
  94. data/lib/mongoid/document.rb +6 -6
  95. data/lib/mongoid/errors.rb +3 -1
  96. data/lib/mongoid/errors/invalid_dependent_strategy.rb +32 -0
  97. data/lib/mongoid/errors/invalid_relation_option.rb +29 -0
  98. data/lib/mongoid/errors/unknown_model.rb +25 -0
  99. data/lib/mongoid/extensions/array.rb +5 -5
  100. data/lib/mongoid/extensions/big_decimal.rb +1 -1
  101. data/lib/mongoid/extensions/object.rb +4 -4
  102. data/lib/mongoid/extensions/range.rb +1 -0
  103. data/lib/mongoid/extensions/regexp.rb +0 -1
  104. data/lib/mongoid/extensions/string.rb +1 -3
  105. data/lib/mongoid/factory.rb +4 -3
  106. data/lib/mongoid/fields.rb +1 -1
  107. data/lib/mongoid/fields/foreign_key.rb +5 -5
  108. data/lib/mongoid/fields/standard.rb +2 -14
  109. data/lib/mongoid/fields/validators/macro.rb +1 -1
  110. data/lib/mongoid/indexable.rb +8 -5
  111. data/lib/mongoid/interceptable.rb +5 -5
  112. data/lib/mongoid/matchable.rb +0 -3
  113. data/lib/mongoid/persistable.rb +4 -5
  114. data/lib/mongoid/persistable/creatable.rb +2 -4
  115. data/lib/mongoid/persistable/deletable.rb +9 -10
  116. data/lib/mongoid/persistable/destroyable.rb +5 -1
  117. data/lib/mongoid/persistable/incrementable.rb +1 -1
  118. data/lib/mongoid/persistable/logical.rb +1 -1
  119. data/lib/mongoid/persistable/settable.rb +5 -5
  120. data/lib/mongoid/persistable/updatable.rb +2 -2
  121. data/lib/mongoid/persistable/upsertable.rb +1 -2
  122. data/lib/mongoid/persistence_context.rb +4 -9
  123. data/lib/mongoid/query_cache.rb +18 -65
  124. data/lib/mongoid/railtie.rb +0 -17
  125. data/lib/mongoid/reloadable.rb +1 -1
  126. data/lib/mongoid/scopable.rb +3 -3
  127. data/lib/mongoid/serializable.rb +3 -3
  128. data/lib/mongoid/tasks/database.rb +2 -3
  129. data/lib/mongoid/threaded.rb +0 -74
  130. data/lib/mongoid/traversable.rb +2 -2
  131. data/lib/mongoid/validatable.rb +8 -8
  132. data/lib/mongoid/validatable/presence.rb +2 -2
  133. data/lib/mongoid/validatable/uniqueness.rb +4 -4
  134. data/lib/mongoid/version.rb +1 -1
  135. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +3 -4
  136. data/spec/app/models/animal.rb +2 -1
  137. data/spec/app/models/band.rb +0 -1
  138. data/spec/app/models/bomb.rb +1 -1
  139. data/spec/app/models/message.rb +1 -1
  140. data/spec/app/models/person.rb +5 -2
  141. data/spec/app/models/vertex.rb +6 -0
  142. data/spec/app/models/wiki_page.rb +1 -1
  143. data/spec/config/mongoid.yml +1 -0
  144. data/spec/mongoid/{relations → association}/accessors_spec.rb +1 -1
  145. data/spec/mongoid/{relations → association}/auto_save_spec.rb +60 -12
  146. data/spec/mongoid/{relations → association}/builders_spec.rb +1 -1
  147. data/spec/mongoid/association/constrainable_spec.rb +115 -0
  148. data/spec/mongoid/{relations → association}/counter_cache_spec.rb +1 -1
  149. data/spec/mongoid/association/depending_spec.rb +613 -0
  150. data/spec/mongoid/{relations → association}/eager_spec.rb +12 -12
  151. data/spec/mongoid/{relations → association/embedded}/cyclic_spec.rb +1 -1
  152. data/spec/mongoid/{relations → association}/embedded/dirty_spec.rb +0 -0
  153. data/spec/mongoid/{relations/bindings/embedded/in_spec.rb → association/embedded/embedded_in/binding_spec.rb} +13 -13
  154. data/spec/mongoid/{relations/builders/embedded/in_spec.rb → association/embedded/embedded_in/buildable_spec.rb} +9 -9
  155. data/spec/mongoid/{relations/embedded/in_spec.rb → association/embedded/embedded_in/proxy_spec.rb} +5 -77
  156. data/spec/mongoid/association/embedded/embedded_in_spec.rb +843 -0
  157. data/spec/mongoid/{relations/bindings/embedded/many_spec.rb → association/embedded/embeds_many/binding_spec.rb} +3 -3
  158. data/spec/mongoid/{relations/builders/embedded/many_spec.rb → association/embedded/embeds_many/buildable_spec.rb} +17 -45
  159. data/spec/mongoid/{relations/embedded/many_spec.rb → association/embedded/embeds_many/proxy_spec.rb} +140 -428
  160. data/spec/mongoid/association/embedded/embeds_many_spec.rb +852 -0
  161. data/spec/mongoid/{relations/bindings/embedded/one_spec.rb → association/embedded/embeds_one/binding_spec.rb} +4 -4
  162. data/spec/mongoid/{relations/builders/embedded/one_spec.rb → association/embedded/embeds_one/buildable_spec.rb} +14 -34
  163. data/spec/mongoid/{relations/embedded/one_spec.rb → association/embedded/embeds_one/proxy_spec.rb} +39 -84
  164. data/spec/mongoid/association/embedded/embeds_one_spec.rb +908 -0
  165. data/spec/mongoid/{relations → association}/macros_spec.rb +148 -93
  166. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/many_spec.rb +16 -19
  167. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/one_spec.rb +17 -20
  168. data/spec/mongoid/association/options_spec.rb +1321 -0
  169. data/spec/mongoid/{relations → association}/polymorphic_spec.rb +7 -34
  170. data/spec/mongoid/{relations/bindings/referenced/in_spec.rb → association/referenced/belongs_to/binding_spec.rb} +7 -7
  171. data/spec/mongoid/{relations/builders/referenced/in_spec.rb → association/referenced/belongs_to/buildable_spec.rb} +46 -79
  172. data/spec/mongoid/{relations/eager/belongs_to_spec.rb → association/referenced/belongs_to/eager_spec.rb} +9 -9
  173. data/spec/mongoid/{relations/referenced/in_spec.rb → association/referenced/belongs_to/proxy_spec.rb} +57 -91
  174. data/spec/mongoid/association/referenced/belongs_to_spec.rb +1963 -0
  175. data/spec/mongoid/{relations/bindings/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/binding_spec.rb} +5 -5
  176. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +121 -0
  177. data/spec/mongoid/{relations/eager/has_and_belongs_to_many_spec.rb → association/referenced/has_and_belongs_to_many/eager_spec.rb} +5 -5
  178. data/spec/mongoid/{relations/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/proxy_spec.rb} +107 -98
  179. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1027 -0
  180. data/spec/mongoid/{relations/bindings/referenced/many_spec.rb → association/referenced/has_many/binding_spec.rb} +5 -5
  181. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +119 -0
  182. data/spec/mongoid/{relations/eager/has_many_spec.rb → association/referenced/has_many/eager_spec.rb} +11 -11
  183. data/spec/mongoid/{relations/targets → association/referenced/has_many}/enumerable_spec.rb +1 -109
  184. data/spec/mongoid/{relations/referenced/many_spec.rb → association/referenced/has_many/proxy_spec.rb} +28 -93
  185. data/spec/mongoid/association/referenced/has_many_spec.rb +1225 -0
  186. data/spec/mongoid/{relations/bindings/referenced/one_spec.rb → association/referenced/has_one/binding_spec.rb} +4 -4
  187. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +113 -0
  188. data/spec/mongoid/{relations/eager/has_one_spec.rb → association/referenced/has_one/eager_spec.rb} +10 -10
  189. data/spec/mongoid/{relations/referenced/one_spec.rb → association/referenced/has_one/proxy_spec.rb} +9 -109
  190. data/spec/mongoid/association/referenced/has_one_spec.rb +1244 -0
  191. data/spec/mongoid/{relations → association}/reflections_spec.rb +1 -12
  192. data/spec/mongoid/{relations/synchronization_spec.rb → association/syncable_spec.rb} +4 -2
  193. data/spec/mongoid/{relations → association}/touchable_spec.rb +19 -1
  194. data/spec/mongoid/{relations_spec.rb → association_spec.rb} +1 -1
  195. data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
  196. data/spec/mongoid/atomic_spec.rb +17 -17
  197. data/spec/mongoid/attributes/nested_spec.rb +14 -12
  198. data/spec/mongoid/attributes/readonly_spec.rb +80 -125
  199. data/spec/mongoid/clients/factory_spec.rb +28 -52
  200. data/spec/mongoid/clients/options_spec.rb +65 -69
  201. data/spec/mongoid/config_spec.rb +24 -0
  202. data/spec/mongoid/contextual/geo_near_spec.rb +0 -1
  203. data/spec/mongoid/contextual/mongo_spec.rb +4 -112
  204. data/spec/mongoid/criteria/modifiable_spec.rb +183 -60
  205. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -3
  206. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +12 -0
  207. data/spec/mongoid/criteria/queryable/selectable_spec.rb +6 -74
  208. data/spec/mongoid/criteria/queryable/selector_spec.rb +2 -2
  209. data/spec/mongoid/criteria/scopable_spec.rb +0 -81
  210. data/spec/mongoid/criteria_spec.rb +16 -19
  211. data/spec/mongoid/document_spec.rb +2 -56
  212. data/spec/mongoid/extensions/array_spec.rb +11 -15
  213. data/spec/mongoid/extensions/big_decimal_spec.rb +9 -9
  214. data/spec/mongoid/extensions/object_spec.rb +7 -11
  215. data/spec/mongoid/extensions/range_spec.rb +7 -0
  216. data/spec/mongoid/extensions/regexp_spec.rb +0 -23
  217. data/spec/mongoid/extensions/string_spec.rb +7 -35
  218. data/spec/mongoid/factory_spec.rb +18 -11
  219. data/spec/mongoid/fields/foreign_key_spec.rb +24 -32
  220. data/spec/mongoid/fields_spec.rb +2 -2
  221. data/spec/mongoid/findable_spec.rb +1 -1
  222. data/spec/mongoid/indexable_spec.rb +18 -8
  223. data/spec/mongoid/interceptable_spec.rb +21 -2
  224. data/spec/mongoid/matchable_spec.rb +1 -26
  225. data/spec/mongoid/persistable/deletable_spec.rb +0 -19
  226. data/spec/mongoid/persistable/destroyable_spec.rb +0 -19
  227. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  228. data/spec/mongoid/persistable/savable_spec.rb +3 -3
  229. data/spec/mongoid/persistable/settable_spec.rb +1 -35
  230. data/spec/mongoid/persistable/updatable_spec.rb +2 -2
  231. data/spec/mongoid/persistable_spec.rb +16 -16
  232. data/spec/mongoid/persistence_context_spec.rb +0 -14
  233. data/spec/mongoid/positional_spec.rb +10 -10
  234. data/spec/mongoid/query_cache_spec.rb +18 -87
  235. data/spec/mongoid/relations/proxy_spec.rb +124 -124
  236. data/spec/mongoid/scopable_spec.rb +0 -13
  237. data/spec/mongoid/threaded_spec.rb +0 -68
  238. data/spec/mongoid/validatable/associated_spec.rb +1 -1
  239. data/spec/mongoid/validatable/presence_spec.rb +7 -6
  240. data/spec/mongoid/validatable_spec.rb +1 -1
  241. data/spec/spec_helper.rb +7 -83
  242. metadata +586 -611
  243. metadata.gz.sig +2 -5
  244. data/lib/mongoid/clients/sessions.rb +0 -113
  245. data/lib/mongoid/errors/invalid_session_use.rb +0 -24
  246. data/lib/mongoid/matchable/nor.rb +0 -37
  247. data/lib/mongoid/railties/controller_runtime.rb +0 -86
  248. data/lib/mongoid/relations.rb +0 -148
  249. data/lib/mongoid/relations/accessors.rb +0 -267
  250. data/lib/mongoid/relations/auto_save.rb +0 -94
  251. data/lib/mongoid/relations/bindings.rb +0 -9
  252. data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
  253. data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
  254. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
  255. data/lib/mongoid/relations/builder.rb +0 -57
  256. data/lib/mongoid/relations/builders.rb +0 -106
  257. data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
  258. data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
  259. data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
  260. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
  261. data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
  262. data/lib/mongoid/relations/cascading.rb +0 -56
  263. data/lib/mongoid/relations/cascading/delete.rb +0 -44
  264. data/lib/mongoid/relations/cascading/destroy.rb +0 -43
  265. data/lib/mongoid/relations/cascading/nullify.rb +0 -35
  266. data/lib/mongoid/relations/cascading/restrict.rb +0 -39
  267. data/lib/mongoid/relations/conversions.rb +0 -34
  268. data/lib/mongoid/relations/counter_cache.rb +0 -160
  269. data/lib/mongoid/relations/cyclic.rb +0 -107
  270. data/lib/mongoid/relations/eager/base.rb +0 -153
  271. data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
  272. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
  273. data/lib/mongoid/relations/eager/has_many.rb +0 -38
  274. data/lib/mongoid/relations/eager/has_one.rb +0 -30
  275. data/lib/mongoid/relations/embedded/in.rb +0 -241
  276. data/lib/mongoid/relations/embedded/many.rb +0 -683
  277. data/lib/mongoid/relations/embedded/one.rb +0 -235
  278. data/lib/mongoid/relations/macros.rb +0 -367
  279. data/lib/mongoid/relations/metadata.rb +0 -1179
  280. data/lib/mongoid/relations/nested_builder.rb +0 -74
  281. data/lib/mongoid/relations/options.rb +0 -49
  282. data/lib/mongoid/relations/polymorphic.rb +0 -39
  283. data/lib/mongoid/relations/referenced/in.rb +0 -304
  284. data/lib/mongoid/relations/referenced/many.rb +0 -812
  285. data/lib/mongoid/relations/referenced/many_to_many.rb +0 -479
  286. data/lib/mongoid/relations/referenced/one.rb +0 -290
  287. data/lib/mongoid/relations/synchronization.rb +0 -169
  288. data/lib/mongoid/relations/targets.rb +0 -2
  289. data/lib/mongoid/relations/targets/enumerable.rb +0 -493
  290. data/lib/mongoid/relations/touchable.rb +0 -97
  291. data/spec/app/models/array_field.rb +0 -7
  292. data/spec/app/models/delegating_patient.rb +0 -16
  293. data/spec/integration/document_spec.rb +0 -22
  294. data/spec/mongoid/clients/sessions_spec.rb +0 -334
  295. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
  296. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
  297. data/spec/mongoid/matchable/nor_spec.rb +0 -209
  298. data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
  299. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
  300. data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
  301. data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
  302. data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
  303. data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
  304. data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
  305. data/spec/mongoid/relations/cascading_spec.rb +0 -355
  306. data/spec/mongoid/relations/constraint_spec.rb +0 -75
  307. data/spec/mongoid/relations/conversions_spec.rb +0 -128
  308. data/spec/mongoid/relations/metadata_spec.rb +0 -1985
  309. data/spec/mongoid/relations/options_spec.rb +0 -35
  310. data/spec/rails/controller_extension/controller_runtime_spec.rb +0 -110
  311. data/spec/support/cluster_config.rb +0 -158
  312. data/spec/support/constraints.rb +0 -101
  313. data/spec/support/macros.rb +0 -20
  314. data/spec/support/session_registry.rb +0 -50
  315. data/spec/support/spec_config.rb +0 -42
@@ -0,0 +1,310 @@
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(&:id)
139
+ criteria(objects_to_clear).pull(inverse_foreign_key => _base._id)
140
+ else
141
+ criteria.pull(inverse_foreign_key => _base._id)
142
+ end
143
+ end
144
+ if persistable?
145
+ _base.set(foreign_key => _base.send(foreign_key).clear)
146
+ end
147
+ after_remove_error = nil
148
+ many_to_many = _target.clear do |doc|
149
+ unbind_one(doc)
150
+ unless _association.forced_nil_inverse?
151
+ doc.changed_attributes.delete(inverse_foreign_key)
152
+ end
153
+ begin
154
+ execute_callback :after_remove, doc
155
+ rescue => e
156
+ after_remove_error = e
157
+ end
158
+ end
159
+ raise after_remove_error if after_remove_error
160
+ many_to_many
161
+ end
162
+
163
+ alias :nullify_all :nullify
164
+ alias :clear :nullify
165
+ alias :purge :nullify
166
+
167
+ # Substitutes the supplied target documents for the existing documents
168
+ # in the relation. If the new target is nil, perform the necessary
169
+ # deletion.
170
+ #
171
+ # @example Replace the relation.
172
+ # person.preferences.substitute([ new_post ])
173
+ #
174
+ # @param [ Array<Document> ] replacement The replacement target.
175
+ #
176
+ # @return [ Many ] The relation.
177
+ #
178
+ # @since 2.0.0.rc.1
179
+ def substitute(replacement)
180
+ purge(replacement)
181
+ unless replacement.blank?
182
+ push(replacement.compact.uniq)
183
+ else
184
+ reset_unloaded
185
+ end
186
+ self
187
+ end
188
+
189
+ # Get a criteria for the documents without the default scoping
190
+ # applied.
191
+ #
192
+ # @example Get the unscoped criteria.
193
+ # person.preferences.unscoped
194
+ #
195
+ # @return [ Criteria ] The unscoped criteria.
196
+ #
197
+ # @since 2.4.0
198
+ def unscoped
199
+ klass.unscoped.any_in(_id: _base.send(foreign_key))
200
+ end
201
+
202
+ private
203
+
204
+ # Appends the document to the target array, updating the index on the
205
+ # document at the same time.
206
+ #
207
+ # @example Append the document to the relation.
208
+ # relation.append(document)
209
+ #
210
+ # @param [ Document ] document The document to append to the target.
211
+ #
212
+ # @since 2.0.0.rc.1
213
+ def append(document)
214
+ execute_callback :before_add, document
215
+ _target.push(document)
216
+ characterize_one(document)
217
+ bind_one(document)
218
+ execute_callback :after_add, document
219
+ end
220
+
221
+ # Instantiate the binding associated with this relation.
222
+ #
223
+ # @example Get the binding.
224
+ # relation.binding([ address ])
225
+ #
226
+ # @return [ Binding ] The binding.
227
+ #
228
+ # @since 2.0.0.rc.1
229
+ def binding
230
+ HasAndBelongsToMany::Binding.new(_base, _target, _association)
231
+ end
232
+
233
+ # Determine if the child document should be persisted.
234
+ #
235
+ # @api private
236
+ #
237
+ # @example Is the child persistable?
238
+ # relation.child_persistable?(doc)
239
+ #
240
+ # @param [ Document ] doc The document.
241
+ #
242
+ # @return [ true, false ] If the document can be persisted.
243
+ #
244
+ # @since 3.0.20
245
+ def child_persistable?(doc)
246
+ (persistable? || _creating?) &&
247
+ !(doc.persisted? && _association.forced_nil_inverse?)
248
+ end
249
+
250
+ # Returns the criteria object for the target class with its documents set
251
+ # to target.
252
+ #
253
+ # @example Get a criteria for the relation.
254
+ # relation.criteria
255
+ #
256
+ # @return [ Criteria ] A new criteria.
257
+ def criteria(id_list = nil)
258
+ _association.criteria(_base, id_list)
259
+ end
260
+
261
+ # Flag the base as unsynced with respect to the foreign key.
262
+ #
263
+ # @api private
264
+ #
265
+ # @example Flag as unsynced.
266
+ # relation.unsynced(doc, :preference_ids)
267
+ #
268
+ # @param [ Document ] doc The document to flag.
269
+ # @param [ Symbol ] key The key to flag on the document.
270
+ #
271
+ # @return [ true ] true.
272
+ #
273
+ # @since 3.0.0
274
+ def unsynced(doc, key)
275
+ doc._synced[key] = false
276
+ true
277
+ end
278
+
279
+ class << self
280
+
281
+ # Get the Eager object for this type of association.
282
+ #
283
+ # @example Get the eager loader object
284
+ #
285
+ # @param [ Association ] association The association object.
286
+ # @param [ Array<Document> ] docs The array of documents.
287
+ #
288
+ # @since 7.0
289
+ def eager_loader(association, docs)
290
+ Eager.new(association, docs)
291
+ end
292
+
293
+ # Returns true if the relation is an embedded one. In this case
294
+ # always false.
295
+ #
296
+ # @example Is this relation embedded?
297
+ # Referenced::ManyToMany.embedded?
298
+ #
299
+ # @return [ false ] Always false.
300
+ #
301
+ # @since 2.0.0.rc.1
302
+ def embedded?
303
+ false
304
+ end
305
+ end
306
+ end
307
+ end
308
+ end
309
+ end
310
+ end
@@ -0,0 +1,273 @@
1
+ require 'mongoid/association/referenced/has_many/binding'
2
+ require 'mongoid/association/referenced/has_many/buildable'
3
+ require 'mongoid/association/referenced/has_many/proxy'
4
+ require 'mongoid/association/referenced/has_many/enumerable'
5
+ require 'mongoid/association/referenced/has_many/eager'
6
+
7
+ module Mongoid
8
+ module Association
9
+ module Referenced
10
+
11
+ # The has_many association.
12
+ #
13
+ # @since 7.0
14
+ class HasMany
15
+ include Relatable
16
+ include Buildable
17
+
18
+ # The options available for this type of association, in addition to the
19
+ # common ones.
20
+ #
21
+ # @return [ Array<Symbol> ] The extra valid options.
22
+ #
23
+ # @since 7.0
24
+ ASSOCIATION_OPTIONS = [
25
+ :after_add,
26
+ :after_remove,
27
+ :as,
28
+ :autosave,
29
+ :before_add,
30
+ :before_remove,
31
+ :dependent,
32
+ :foreign_key,
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 default foreign key suffix.
46
+ #
47
+ # @return [ String ] '_id'
48
+ #
49
+ # @since 7.0
50
+ FOREIGN_KEY_SUFFIX = '_id'.freeze
51
+
52
+ # The list of association complements.
53
+ #
54
+ # @return [ Array<Association> ] The association complements.
55
+ #
56
+ # @since 7.0
57
+ def relation_complements
58
+ @relation_complements ||= [ Referenced::BelongsTo ].freeze
59
+ end
60
+
61
+ # Setup the instance methods, fields, etc. on the association owning class.
62
+ #
63
+ # @return [ self ]
64
+ #
65
+ # @since 7.0
66
+ def setup!
67
+ setup_instance_methods!
68
+ self
69
+ end
70
+
71
+ # Setup the instance methods on the class having this association type.
72
+ #
73
+ # @return [ self ]
74
+ #
75
+ # @since 7.0
76
+ def setup_instance_methods!
77
+ define_getter!
78
+ define_ids_getter!
79
+ define_setter!
80
+ define_ids_setter!
81
+ define_existence_check!
82
+ define_autosaver!
83
+ polymorph!
84
+ define_dependency!
85
+ @owner_class.validates_associated(name) if validate?
86
+ self
87
+ end
88
+
89
+
90
+ # Get the foreign key field on the inverse for saving the association reference.
91
+ #
92
+ # @return [ String ] The foreign key field on the inverse for saving the
93
+ # association reference.
94
+ #
95
+ # @since 7.0
96
+ def foreign_key
97
+ @foreign_key ||= @options[:foreign_key] ? @options[:foreign_key].to_s :
98
+ default_foreign_key_field
99
+ end
100
+
101
+ # Is this association type embedded?
102
+ #
103
+ # @return [ false ] Always false.
104
+ #
105
+ # @since 7.0
106
+ def embedded?; false; end
107
+
108
+ # The default for validation the association object.
109
+ #
110
+ # @return [ true ] Always true.
111
+ #
112
+ # @since 7.0
113
+ def validation_default; true; end
114
+
115
+ # Does this association type store the foreign key?
116
+ #
117
+ # @return [ true ] Always true.
118
+ #
119
+ # @since 7.0
120
+ def stores_foreign_key?; false; end
121
+
122
+ # Get the relation proxy class for this association type.
123
+ #
124
+ # @return [ Association::HasMany::Proxy ] The proxy class.
125
+ #
126
+ # @since 7.0
127
+ def relation
128
+ Proxy
129
+ end
130
+
131
+ # The criteria used for querying this relation.
132
+ #
133
+ # @return [ Mongoid::Criteria ] The criteria used for querying this relation.
134
+ #
135
+ # @since 7.0
136
+ def criteria(base)
137
+ query_criteria(base.send(primary_key), base)
138
+ end
139
+
140
+ # The type of this association if it's polymorphic.
141
+ #
142
+ # @note Only relevant for polymorphic relations.
143
+ #
144
+ # @return [ String, nil ] The type field.
145
+ #
146
+ # @since 7.0
147
+ def type
148
+ @type ||= "#{as}_type" if polymorphic?
149
+ end
150
+
151
+ # Add polymorphic query criteria to a Criteria object, if this association is
152
+ # polymorphic.
153
+ #
154
+ # @param [ Mongoid::Criteria ] criteria The criteria object to add to.
155
+ # @param [ Class ] object_class The object class.
156
+ #
157
+ # @return [ Mongoid::Criteria ] The criteria object.
158
+ #
159
+ # @since 7.0
160
+ def add_polymorphic_criterion(criteria, object_class)
161
+ if polymorphic?
162
+ criteria.where(type => object_class.name)
163
+ else
164
+ criteria
165
+ end
166
+ end
167
+
168
+ # Is this association polymorphic?
169
+ #
170
+ # @return [ true, false ] Whether this association is polymorphic.
171
+ #
172
+ # @since 7.0
173
+ def polymorphic?
174
+ @polymorphic ||= !!as
175
+ end
176
+
177
+ # Whether trying to bind an object using this association should raise
178
+ # an error.
179
+ #
180
+ # @param [ Document ] doc The document to be bound.
181
+ #
182
+ # @return [ true, false ] Whether the document can be bound.
183
+ def bindable?(doc)
184
+ forced_nil_inverse? || (!!inverse && doc.fields.keys.include?(foreign_key))
185
+ end
186
+
187
+ # The nested builder object.
188
+ #
189
+ # @param [ Hash ] attributes The attributes to use to build the association object.
190
+ # @param [ Hash ] options The options for the association.
191
+ #
192
+ # @return [ Association::Nested::Many ] The Nested Builder object.
193
+ #
194
+ # @since 7.0
195
+ def nested_builder(attributes, options)
196
+ Nested::Many.new(self, attributes, options)
197
+ end
198
+
199
+ # Get the path calculator for the supplied document.
200
+ #
201
+ # @example Get the path calculator.
202
+ # Proxy.path(document)
203
+ #
204
+ # @param [ Document ] document The document to calculate on.
205
+ #
206
+ # @return [ Root ] The root atomic path calculator.
207
+ #
208
+ # @since 2.1.0
209
+ def path(document)
210
+ Mongoid::Atomic::Paths::Root.new(document)
211
+ end
212
+
213
+ private
214
+
215
+ def default_foreign_key_field
216
+ @default_foreign_key_field ||= "#{inverse}#{FOREIGN_KEY_SUFFIX}"
217
+ end
218
+
219
+ def polymorphic_inverses(other)
220
+ [ as ]
221
+ end
222
+
223
+ def determine_inverses(other)
224
+ matches = (other || relation_class).relations.values.select do |rel|
225
+ relation_complements.include?(rel.class) &&
226
+ rel.relation_class_name == inverse_class_name
227
+
228
+ end
229
+ if matches.size > 1
230
+ return [ default_inverse.name ] if default_inverse
231
+ raise Errors::AmbiguousRelationship.new(relation_class, @owner_class, name, matches)
232
+ end
233
+ matches.collect { |m| m.name } unless matches.blank?
234
+ end
235
+
236
+ def default_primary_key
237
+ PRIMARY_KEY_DEFAULT
238
+ end
239
+
240
+ def query_criteria(object, base)
241
+ crit = klass.where(foreign_key => object)
242
+ crit = with_polymorphic_criterion(crit, base)
243
+ with_ordering(crit)
244
+ end
245
+
246
+ def with_polymorphic_criterion(criteria, base)
247
+ if polymorphic?
248
+ criteria.where(type => base.class.name)
249
+ else
250
+ criteria
251
+ end
252
+ end
253
+
254
+ def with_ordering(criteria)
255
+ if order
256
+ criteria.order_by(order)
257
+ else
258
+ criteria
259
+ end
260
+ end
261
+
262
+ def with_inverse_field_criterion(criteria)
263
+ inverse_association = inverse_association(klass)
264
+ if inverse_association.try(:inverse_of)
265
+ criteria.any_in(inverse_association.inverse_of => [name, nil])
266
+ else
267
+ criteria
268
+ end
269
+ end
270
+ end
271
+ end
272
+ end
273
+ end