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,510 @@
1
+ # encoding: utf-8
2
+ module Mongoid
3
+ module Association
4
+ module Referenced
5
+ class HasMany
6
+ module Targets
7
+
8
+ # This class is the wrapper for all relational associations that have a
9
+ # target that can be a criteria or array of _loaded documents. This
10
+ # handles both cases or a combination of the two.
11
+ class Enumerable
12
+ include ::Enumerable
13
+
14
+ # The three main instance variables are collections of documents.
15
+ #
16
+ # @attribute [rw] _added Documents that have been appended.
17
+ # @attribute [rw] _loaded Persisted documents that have been _loaded.
18
+ # @attribute [rw] _unloaded A criteria representing persisted docs.
19
+ attr_accessor :_added, :_loaded, :_unloaded
20
+
21
+ delegate :is_a?, :kind_of?, to: []
22
+
23
+ # Check if the enumerable is equal to the other object.
24
+ #
25
+ # @example Check equality.
26
+ # enumerable == []
27
+ #
28
+ # @param [ Enumerable ] other The other enumerable.
29
+ #
30
+ # @return [ true, false ] If the objects are equal.
31
+ #
32
+ # @since 2.1.0
33
+ def ==(other)
34
+ return false unless other.respond_to?(:entries)
35
+ entries == other.entries
36
+ end
37
+
38
+ # Check equality of the enumerable against the provided object for case
39
+ # statements.
40
+ #
41
+ # @example Check case equality.
42
+ # enumerable === Array
43
+ #
44
+ # @param [ Object ] other The object to check.
45
+ #
46
+ # @return [ true, false ] If the objects are equal in a case.
47
+ #
48
+ # @since 3.1.4
49
+ def ===(other)
50
+ other.class == Class ? (Array == other || Enumerable == other) : self == other
51
+ end
52
+
53
+ # Append a document to the enumerable.
54
+ #
55
+ # @example Append the document.
56
+ # enumerable << document
57
+ #
58
+ # @param [ Document ] document The document to append.
59
+ #
60
+ # @return [ Document ] The document.
61
+ #
62
+ # @since 2.1.0
63
+ def <<(document)
64
+ _added[document._id] = document
65
+ self
66
+ end
67
+
68
+ alias :push :<<
69
+
70
+ # Clears out all the documents in this enumerable. If passed a block it
71
+ # will yield to each document that is in memory.
72
+ #
73
+ # @example Clear out the enumerable.
74
+ # enumerable.clear
75
+ #
76
+ # @example Clear out the enumerable with a block.
77
+ # enumerable.clear do |doc|
78
+ # doc.unbind
79
+ # end
80
+ #
81
+ # @return [ Array<Document> ] The cleared out _added docs.
82
+ #
83
+ # @since 2.1.0
84
+ def clear
85
+ if block_given?
86
+ in_memory { |doc| yield(doc) }
87
+ end
88
+ _loaded.clear and _added.clear
89
+ end
90
+
91
+ # Clones each document in the enumerable.
92
+ #
93
+ # @note This loads all documents into memory.
94
+ #
95
+ # @example Clone the enumerable.
96
+ # enumerable.clone
97
+ #
98
+ # @return [ Array<Document> ] An array clone of the enumerable.
99
+ #
100
+ # @since 2.1.6
101
+ def clone
102
+ collect { |doc| doc.clone }
103
+ end
104
+
105
+ # Delete the supplied document from the enumerable.
106
+ #
107
+ # @example Delete the document.
108
+ # enumerable.delete(document)
109
+ #
110
+ # @param [ Document ] document The document to delete.
111
+ #
112
+ # @return [ Document ] The deleted document.
113
+ #
114
+ # @since 2.1.0
115
+ def delete(document)
116
+ doc = (_loaded.delete(document._id) || _added.delete(document._id))
117
+ unless doc
118
+ if _unloaded && _unloaded.where(_id: document._id).exists?
119
+ yield(document) if block_given?
120
+ return document
121
+ end
122
+ end
123
+ yield(doc) if block_given?
124
+ doc
125
+ end
126
+
127
+ # Deletes every document in the enumerable for where the block returns
128
+ # true.
129
+ #
130
+ # @note This operation loads all documents from the database.
131
+ #
132
+ # @example Delete all matching documents.
133
+ # enumerable.delete_if do |doc|
134
+ # dod._id == _id
135
+ # end
136
+ #
137
+ # @return [ Array<Document> ] The remaining docs.
138
+ #
139
+ # @since 2.1.0
140
+ def delete_if(&block)
141
+ load_all!
142
+ deleted = in_memory.select(&block)
143
+ deleted.each do |doc|
144
+ _loaded.delete(doc._id)
145
+ _added.delete(doc._id)
146
+ end
147
+ self
148
+ end
149
+
150
+ # Iterating over this enumerable has to handle a few different
151
+ # scenarios.
152
+ #
153
+ # If the enumerable has its criteria _loaded into memory then it yields
154
+ # to all the _loaded docs and all the _added docs.
155
+ #
156
+ # If the enumerable has not _loaded the criteria then it iterates over
157
+ # the cursor while loading the documents and then iterates over the
158
+ # _added docs.
159
+ #
160
+ # If no block is passed then it returns an enumerator containing all
161
+ # docs.
162
+ #
163
+ # @example Iterate over the enumerable.
164
+ # enumerable.each do |doc|
165
+ # puts doc
166
+ # end
167
+ #
168
+ # @example return an enumerator containing all the docs
169
+ #
170
+ # a = enumerable.each
171
+ #
172
+ # @return [ true ] That the enumerable is now _loaded.
173
+ #
174
+ # @since 2.1.0
175
+ def each
176
+ unless block_given?
177
+ return to_enum
178
+ end
179
+ if _loaded?
180
+ _loaded.each_pair do |id, doc|
181
+ document = _added.delete(doc._id) || doc
182
+ set_base(document)
183
+ yield(document)
184
+ end
185
+ else
186
+ unloaded_documents.each do |doc|
187
+ document = _added.delete(doc._id) || _loaded.delete(doc._id) || doc
188
+ _loaded[document._id] = document
189
+ set_base(document)
190
+ yield(document)
191
+ end
192
+ end
193
+ _added.each_pair do |id, doc|
194
+ yield(doc)
195
+ end
196
+ @executed = true
197
+ end
198
+
199
+ # Is the enumerable empty? Will determine if the count is zero based on
200
+ # whether or not it is _loaded.
201
+ #
202
+ # @example Is the enumerable empty?
203
+ # enumerable.empty?
204
+ #
205
+ # @return [ true, false ] If the enumerable is empty.
206
+ #
207
+ # @since 2.1.0
208
+ def empty?
209
+ if _loaded?
210
+ in_memory.count == 0
211
+ else
212
+ _unloaded.count + _added.count == 0
213
+ end
214
+ end
215
+
216
+ # Get the first document in the enumerable. Will check the persisted
217
+ # documents first. Does not load the entire enumerable.
218
+ #
219
+ # @example Get the first document.
220
+ # enumerable.first
221
+ #
222
+ # @note Automatically adding a sort on _id when no other sort is
223
+ # defined on the criteria has the potential to cause bad performance issues.
224
+ # If you experience unexpected poor performance when using #first or #last,
225
+ # use the option { id_sort: :none }.
226
+ # Be aware that #first/#last won't guarantee order in this case.
227
+ #
228
+ # @param [ Hash ] opts The options for the query returning the first document.
229
+ #
230
+ # @option opts [ :none ] :id_sort Don't apply a sort on _id.
231
+ #
232
+ # @return [ Document ] The first document found.
233
+ #
234
+ # @since 2.1.0
235
+ def first(opts = {})
236
+ _loaded.try(:values).try(:first) ||
237
+ _added[(ul = _unloaded.try(:first, opts)).try(:id)] ||
238
+ ul ||
239
+ _added.values.try(:first)
240
+ end
241
+
242
+ # Initialize the new enumerable either with a criteria or an array.
243
+ #
244
+ # @example Initialize the enumerable with a criteria.
245
+ # Enumberable.new(Post.where(:person_id => id))
246
+ #
247
+ # @example Initialize the enumerable with an array.
248
+ # Enumerable.new([ post ])
249
+ #
250
+ # @param [ Criteria, Array<Document> ] target The wrapped object.
251
+ #
252
+ # @since 2.1.0
253
+ def initialize(target, base = nil, association = nil)
254
+ @_base = base
255
+ @_association = association
256
+ if target.is_a?(Criteria)
257
+ @_added, @executed, @_loaded, @_unloaded = {}, false, {}, target
258
+ else
259
+ @_added, @executed = {}, true
260
+ @_loaded = target.inject({}) do |_target, doc|
261
+ _target[doc._id] = doc if doc
262
+ _target
263
+ end
264
+ end
265
+ end
266
+
267
+ # Does the target include the provided document?
268
+ #
269
+ # @example Does the target include the document?
270
+ # enumerable.include?(document)
271
+ #
272
+ # @param [ Document ] doc The document to check.
273
+ #
274
+ # @return [ true, false ] If the document is in the target.
275
+ #
276
+ # @since 3.0.0
277
+ def include?(doc)
278
+ return super unless _unloaded
279
+ _unloaded.where(_id: doc._id).exists? || _added.has_key?(doc._id)
280
+ end
281
+
282
+ # Inspection will just inspect the entries for nice array-style
283
+ # printing.
284
+ #
285
+ # @example Inspect the enumerable.
286
+ # enumerable.inspect
287
+ #
288
+ # @return [ String ] The inspected enum.
289
+ #
290
+ # @since 2.1.0
291
+ def inspect
292
+ entries.inspect
293
+ end
294
+
295
+ # Return all the documents in the enumerable that have been _loaded or
296
+ # _added.
297
+ #
298
+ # @note When passed a block it yields to each document.
299
+ #
300
+ # @example Get the in memory docs.
301
+ # enumerable.in_memory
302
+ #
303
+ # @return [ Array<Document> ] The in memory docs.
304
+ #
305
+ # @since 2.1.0
306
+ def in_memory
307
+ docs = (_loaded.values + _added.values)
308
+ docs.each do |doc|
309
+ yield(doc) if block_given?
310
+ end
311
+ end
312
+
313
+ # Get the last document in the enumerable. Will check the new
314
+ # documents first. Does not load the entire enumerable.
315
+ #
316
+ # @example Get the last document.
317
+ # enumerable.last
318
+ #
319
+ # @note Automatically adding a sort on _id when no other sort is
320
+ # defined on the criteria has the potential to cause bad performance issues.
321
+ # If you experience unexpected poor performance when using #first or #last,
322
+ # use the option { id_sort: :none }.
323
+ # Be aware that #first/#last won't guarantee order in this case.
324
+ #
325
+ # @param [ Hash ] opts The options for the query returning the first document.
326
+ #
327
+ # @option opts [ :none ] :id_sort Don't apply a sort on _id.
328
+ #
329
+ # @return [ Document ] The last document found.
330
+ #
331
+ # @since 2.1.0
332
+ def last(opts = {})
333
+ _added.values.try(:last) ||
334
+ _loaded.try(:values).try(:last) ||
335
+ _added[(ul = _unloaded.try(:last, opts)).try(:id)] ||
336
+ ul
337
+ end
338
+
339
+ # Loads all the documents in the enumerable from the database.
340
+ #
341
+ # @example Load all the documents.
342
+ # enumerable.load_all!
343
+ #
344
+ # @return [ true ] That the enumerable is _loaded.
345
+ #
346
+ # @since 2.1.0
347
+ alias :load_all! :entries
348
+
349
+ # Has the enumerable been _loaded? This will be true if the criteria has
350
+ # been executed or we manually load the entire thing.
351
+ #
352
+ # @example Is the enumerable _loaded?
353
+ # enumerable._loaded?
354
+ #
355
+ # @return [ true, false ] If the enumerable has been _loaded.
356
+ #
357
+ # @since 2.1.0
358
+ def _loaded?
359
+ !!@executed
360
+ end
361
+
362
+ # Provides the data needed to Marshal.dump an enumerable proxy.
363
+ #
364
+ # @example Dump the proxy.
365
+ # Marshal.dump(proxy)
366
+ #
367
+ # @return [ Array<Object> ] The dumped data.
368
+ #
369
+ # @since 3.0.15
370
+ def marshal_dump
371
+ [_added, _loaded, _unloaded, @executed]
372
+ end
373
+
374
+ # Loads the data needed to Marshal.load an enumerable proxy.
375
+ #
376
+ # @example Load the proxy.
377
+ # Marshal.load(proxy)
378
+ #
379
+ # @return [ Array<Object> ] The dumped data.
380
+ #
381
+ # @since 3.0.15
382
+ def marshal_load(data)
383
+ @_added, @_loaded, @_unloaded, @executed = data
384
+ end
385
+
386
+ # Reset the enumerable back to its persisted state.
387
+ #
388
+ # @example Reset the enumerable.
389
+ # enumerable.reset
390
+ #
391
+ # @return [ false ] Always false.
392
+ #
393
+ # @since 2.1.0
394
+ def reset
395
+ _loaded.clear and _added.clear
396
+ @executed = false
397
+ end
398
+
399
+ # Resets the underlying unloaded criteria object with a new one. Used
400
+ # my HABTM relations to keep the underlying array in sync.
401
+ #
402
+ # @example Reset the unloaded documents.
403
+ # enumerable.reset_unloaded(criteria)
404
+ #
405
+ # @param [ Criteria ] criteria The criteria to replace with.
406
+ #
407
+ # @since 3.0.14
408
+ def reset_unloaded(criteria)
409
+ @_unloaded = criteria if _unloaded.is_a?(Criteria)
410
+ end
411
+
412
+ # Does this enumerable respond to the provided method?
413
+ #
414
+ # @example Does the enumerable respond to the method?
415
+ # enumerable.respond_to?(:sum)
416
+ #
417
+ # @param [ String, Symbol ] name The name of the method.
418
+ # @param [ true, false ] include_private Whether to include private
419
+ # methods.
420
+ #
421
+ # @return [ true, false ] Whether the enumerable responds.
422
+ #
423
+ # @since 2.1.0
424
+ def respond_to?(name, include_private = false)
425
+ [].respond_to?(name, include_private) || super
426
+ end
427
+
428
+ # Gets the total size of this enumerable. This is a combination of all
429
+ # the persisted and unpersisted documents.
430
+ #
431
+ # @example Get the size.
432
+ # enumerable.size
433
+ #
434
+ # @return [ Integer ] The size of the enumerable.
435
+ #
436
+ # @since 2.1.0
437
+ def size
438
+ count = (_unloaded ? _unloaded.count : _loaded.count)
439
+ if count.zero?
440
+ count + _added.count
441
+ else
442
+ count + _added.values.count { |d| d.new_record? }
443
+ end
444
+ end
445
+
446
+ alias :length :size
447
+
448
+ # Send #to_json to the entries.
449
+ #
450
+ # @example Get the enumerable as json.
451
+ # enumerable.to_json
452
+ #
453
+ # @param [ Hash ] options Optional parameters.
454
+ #
455
+ # @return [ String ] The entries all _loaded as a string.
456
+ #
457
+ # @since 2.2.0
458
+ def to_json(options = {})
459
+ entries.to_json(options)
460
+ end
461
+
462
+ # Send #as_json to the entries, without encoding.
463
+ #
464
+ # @example Get the enumerable as json.
465
+ # enumerable.as_json
466
+ #
467
+ # @param [ Hash ] options Optional parameters.
468
+ #
469
+ # @return [ Hash ] The entries all _loaded as a hash.
470
+ #
471
+ # @since 2.2.0
472
+ def as_json(options = {})
473
+ entries.as_json(options)
474
+ end
475
+
476
+ # Return all the unique documents in the enumerable.
477
+ #
478
+ # @note This operation loads all documents from the database.
479
+ #
480
+ # @example Get all the unique documents.
481
+ # enumerable.uniq
482
+ #
483
+ # @return [ Array<Document> ] The unique documents.
484
+ #
485
+ # @since 2.1.0
486
+ def uniq
487
+ entries.uniq
488
+ end
489
+
490
+ private
491
+
492
+ def set_base(document)
493
+ if @_association.is_a?(Referenced::HasMany)
494
+ document.set_relation(@_association.inverse, @_base) if @_association
495
+ end
496
+ end
497
+
498
+ def method_missing(name, *args, &block)
499
+ entries.send(name, *args, &block)
500
+ end
501
+
502
+ def unloaded_documents
503
+ _unloaded.selector.values.any?(&:blank_criteria?) ? [] : _unloaded
504
+ end
505
+ end
506
+ end
507
+ end
508
+ end
509
+ end
510
+ end