mongoid 6.4.8 → 7.0.13

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 (376) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/LICENSE +1 -0
  4. data/README.md +4 -3
  5. data/Rakefile +33 -7
  6. data/lib/config/locales/en.yml +17 -0
  7. data/lib/mongoid/association/accessors.rb +339 -0
  8. data/lib/mongoid/{relations/binding.rb → association/bindable.rb} +32 -52
  9. data/lib/mongoid/association/builders.rb +92 -0
  10. data/lib/mongoid/{relations/constraint.rb → association/constrainable.rb} +11 -22
  11. data/lib/mongoid/association/depending.rb +137 -0
  12. data/lib/mongoid/{relations/eager.rb → association/eager_loadable.rb} +11 -11
  13. data/lib/mongoid/{relations → association}/embedded/batchable.rb +19 -19
  14. data/lib/mongoid/association/embedded/cyclic.rb +109 -0
  15. data/lib/mongoid/association/embedded/embedded_in/binding.rb +56 -0
  16. data/lib/mongoid/{relations/builders/embedded/in.rb → association/embedded/embedded_in/buildable.rb} +12 -6
  17. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +121 -0
  18. data/lib/mongoid/association/embedded/embedded_in.rb +154 -0
  19. data/lib/mongoid/{relations/bindings/embedded/many.rb → association/embedded/embeds_many/binding.rb} +11 -9
  20. data/lib/mongoid/{relations/builders/embedded/many.rb → association/embedded/embeds_many/buildable.rb} +13 -7
  21. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +552 -0
  22. data/lib/mongoid/association/embedded/embeds_many.rb +211 -0
  23. data/lib/mongoid/{relations/bindings/embedded/one.rb → association/embedded/embeds_one/binding.rb} +12 -10
  24. data/lib/mongoid/{relations/builders/embedded/one.rb → association/embedded/embeds_one/buildable.rb} +13 -7
  25. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +130 -0
  26. data/lib/mongoid/association/embedded/embeds_one.rb +174 -0
  27. data/lib/mongoid/association/embedded.rb +4 -0
  28. data/lib/mongoid/association/macros.rb +204 -0
  29. data/lib/mongoid/{relations → association}/many.rb +19 -49
  30. data/lib/mongoid/{relations → association}/marshalable.rb +6 -4
  31. data/lib/mongoid/association/nested/many.rb +200 -0
  32. data/lib/mongoid/association/nested/nested_buildable.rb +72 -0
  33. data/lib/mongoid/association/nested/one.rb +127 -0
  34. data/lib/mongoid/association/nested.rb +15 -0
  35. data/lib/mongoid/{relations → association}/one.rb +6 -6
  36. data/lib/mongoid/association/options.rb +152 -0
  37. data/lib/mongoid/{relations → association}/proxy.rb +45 -59
  38. data/lib/mongoid/association/referenced/auto_save.rb +79 -0
  39. data/lib/mongoid/association/referenced/belongs_to/binding.rb +87 -0
  40. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +46 -0
  41. data/lib/mongoid/association/referenced/belongs_to/eager.rb +36 -0
  42. data/lib/mongoid/association/referenced/belongs_to/proxy.rb +136 -0
  43. data/lib/mongoid/association/referenced/belongs_to.rb +248 -0
  44. data/lib/mongoid/association/referenced/counter_cache.rb +163 -0
  45. data/lib/mongoid/association/referenced/eager.rb +162 -0
  46. data/lib/mongoid/association/referenced/has_and_belongs_to_many/binding.rb +71 -0
  47. data/lib/mongoid/association/referenced/has_and_belongs_to_many/buildable.rb +40 -0
  48. data/lib/mongoid/association/referenced/has_and_belongs_to_many/eager.rb +52 -0
  49. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +312 -0
  50. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +290 -0
  51. data/lib/mongoid/{relations/bindings/referenced/many.rb → association/referenced/has_many/binding.rb} +6 -5
  52. data/lib/mongoid/association/referenced/has_many/buildable.rb +38 -0
  53. data/lib/mongoid/association/referenced/has_many/eager.rb +43 -0
  54. data/lib/mongoid/association/referenced/has_many/enumerable.rb +510 -0
  55. data/lib/mongoid/association/referenced/has_many/proxy.rb +578 -0
  56. data/lib/mongoid/association/referenced/has_many.rb +275 -0
  57. data/lib/mongoid/{relations/bindings/referenced/one.rb → association/referenced/has_one/binding.rb} +11 -8
  58. data/lib/mongoid/association/referenced/has_one/buildable.rb +60 -0
  59. data/lib/mongoid/association/referenced/has_one/eager.rb +35 -0
  60. data/lib/mongoid/{relations/builders/nested_attributes/one.rb → association/referenced/has_one/nested_builder.rb} +9 -9
  61. data/lib/mongoid/association/referenced/has_one/proxy.rb +113 -0
  62. data/lib/mongoid/association/referenced/has_one.rb +204 -0
  63. data/lib/mongoid/association/referenced/syncable.rb +170 -0
  64. data/lib/mongoid/association/referenced.rb +7 -0
  65. data/lib/mongoid/{relations → association}/reflections.rb +21 -17
  66. data/lib/mongoid/association/relatable.rb +511 -0
  67. data/lib/mongoid/{relations.rb → association.rb} +57 -56
  68. data/lib/mongoid/atomic/paths/embedded/many.rb +1 -1
  69. data/lib/mongoid/atomic/paths/embedded/one.rb +1 -1
  70. data/lib/mongoid/atomic/paths/embedded.rb +1 -1
  71. data/lib/mongoid/atomic.rb +14 -4
  72. data/lib/mongoid/attributes/dynamic.rb +16 -15
  73. data/lib/mongoid/attributes/nested.rb +22 -11
  74. data/lib/mongoid/attributes/processing.rb +2 -2
  75. data/lib/mongoid/attributes/readonly.rb +2 -4
  76. data/lib/mongoid/attributes.rb +55 -31
  77. data/lib/mongoid/changeable.rb +1 -1
  78. data/lib/mongoid/clients/options.rb +7 -5
  79. data/lib/mongoid/clients/sessions.rb +20 -4
  80. data/lib/mongoid/composable.rb +4 -4
  81. data/lib/mongoid/config/environment.rb +21 -8
  82. data/lib/mongoid/config.rb +1 -0
  83. data/lib/mongoid/contextual/atomic.rb +1 -1
  84. data/lib/mongoid/contextual/geo_near.rb +1 -1
  85. data/lib/mongoid/contextual/memory.rb +21 -3
  86. data/lib/mongoid/contextual/mongo.rb +10 -8
  87. data/lib/mongoid/copyable.rb +11 -6
  88. data/lib/mongoid/criteria/includable.rb +14 -14
  89. data/lib/mongoid/criteria/modifiable.rb +8 -3
  90. data/lib/mongoid/criteria/options.rb +2 -2
  91. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  92. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +3 -3
  93. data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -1
  94. data/lib/mongoid/criteria/queryable/extensions/time.rb +1 -1
  95. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +12 -0
  96. data/lib/mongoid/criteria/queryable/key.rb +67 -8
  97. data/lib/mongoid/criteria/queryable/mergeable.rb +5 -4
  98. data/lib/mongoid/criteria/queryable/pipeline.rb +10 -5
  99. data/lib/mongoid/criteria/queryable/selectable.rb +5 -3
  100. data/lib/mongoid/criteria/queryable/selector.rb +9 -31
  101. data/lib/mongoid/criteria.rb +9 -3
  102. data/lib/mongoid/document.rb +14 -4
  103. data/lib/mongoid/errors/invalid_dependent_strategy.rb +32 -0
  104. data/lib/mongoid/errors/invalid_relation_option.rb +29 -0
  105. data/lib/mongoid/errors/unknown_model.rb +25 -0
  106. data/lib/mongoid/errors.rb +3 -0
  107. data/lib/mongoid/extensions/array.rb +5 -5
  108. data/lib/mongoid/extensions/hash.rb +9 -4
  109. data/lib/mongoid/extensions/object.rb +4 -4
  110. data/lib/mongoid/extensions/range.rb +1 -0
  111. data/lib/mongoid/extensions/regexp.rb +1 -1
  112. data/lib/mongoid/extensions/string.rb +2 -2
  113. data/lib/mongoid/extensions.rb +0 -4
  114. data/lib/mongoid/factory.rb +13 -3
  115. data/lib/mongoid/fields/foreign_key.rb +5 -5
  116. data/lib/mongoid/fields/standard.rb +2 -14
  117. data/lib/mongoid/fields/validators/macro.rb +1 -1
  118. data/lib/mongoid/fields.rb +5 -4
  119. data/lib/mongoid/indexable.rb +4 -1
  120. data/lib/mongoid/interceptable.rb +8 -6
  121. data/lib/mongoid/matchable/all.rb +4 -3
  122. data/lib/mongoid/matchable/and.rb +1 -1
  123. data/lib/mongoid/matchable/default.rb +71 -24
  124. data/lib/mongoid/matchable/elem_match.rb +9 -3
  125. data/lib/mongoid/matchable/eq.rb +22 -0
  126. data/lib/mongoid/matchable/ne.rb +1 -1
  127. data/lib/mongoid/matchable/regexp.rb +2 -2
  128. data/lib/mongoid/matchable.rb +17 -16
  129. data/lib/mongoid/persistable/deletable.rb +7 -6
  130. data/lib/mongoid/persistable/incrementable.rb +1 -1
  131. data/lib/mongoid/persistable/logical.rb +1 -1
  132. data/lib/mongoid/persistable/pushable.rb +11 -2
  133. data/lib/mongoid/persistable/settable.rb +57 -12
  134. data/lib/mongoid/persistable.rb +4 -5
  135. data/lib/mongoid/persistence_context.rb +26 -11
  136. data/lib/mongoid/positional.rb +1 -1
  137. data/lib/mongoid/query_cache.rb +4 -2
  138. data/lib/mongoid/serializable.rb +4 -4
  139. data/lib/mongoid/shardable.rb +1 -1
  140. data/lib/mongoid/touchable.rb +102 -0
  141. data/lib/mongoid/traversable.rb +3 -3
  142. data/lib/mongoid/validatable/macros.rb +1 -1
  143. data/lib/mongoid/validatable/presence.rb +2 -2
  144. data/lib/mongoid/validatable/uniqueness.rb +5 -5
  145. data/lib/mongoid/validatable.rb +8 -8
  146. data/lib/mongoid/version.rb +2 -1
  147. data/lib/mongoid.rb +1 -0
  148. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  149. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +3 -0
  150. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +1 -1
  151. data/spec/README.md +18 -0
  152. data/spec/app/models/animal.rb +2 -1
  153. data/spec/app/models/bomb.rb +1 -1
  154. data/spec/app/models/customer.rb +11 -0
  155. data/spec/app/models/customer_address.rb +12 -0
  156. data/spec/app/models/message.rb +1 -1
  157. data/spec/app/models/minim.rb +7 -0
  158. data/spec/app/models/other_owner_object.rb +2 -0
  159. data/spec/app/models/person.rb +5 -2
  160. data/spec/app/models/shipment_address.rb +1 -0
  161. data/spec/app/models/store_as_dup_test3.rb +7 -0
  162. data/spec/app/models/store_as_dup_test4.rb +7 -0
  163. data/spec/app/models/updatable.rb +7 -0
  164. data/spec/app/models/vertex.rb +6 -0
  165. data/spec/app/models/wiki_page.rb +1 -1
  166. data/spec/config/mongoid.yml +13 -3
  167. data/spec/integration/app_spec.rb +341 -0
  168. data/spec/integration/associations/belongs_to_spec.rb +13 -0
  169. data/spec/integration/associations/embedded_spec.rb +176 -0
  170. data/spec/integration/callbacks_models.rb +49 -0
  171. data/spec/integration/callbacks_spec.rb +216 -0
  172. data/spec/integration/criteria/date_field_spec.rb +41 -0
  173. data/spec/integration/criteria/time_with_zone_spec.rb +32 -0
  174. data/spec/integration/matchable_spec.rb +680 -0
  175. data/spec/lite_spec_helper.rb +71 -0
  176. data/spec/mongoid/{relations → association}/accessors_spec.rb +40 -1
  177. data/spec/mongoid/{relations → association}/auto_save_spec.rb +60 -12
  178. data/spec/mongoid/{relations → association}/builders_spec.rb +1 -1
  179. data/spec/mongoid/association/constrainable_spec.rb +115 -0
  180. data/spec/mongoid/{relations → association}/counter_cache_spec.rb +1 -1
  181. data/spec/mongoid/association/depending_spec.rb +866 -0
  182. data/spec/mongoid/{relations → association}/eager_spec.rb +12 -12
  183. data/spec/mongoid/{relations → association/embedded}/cyclic_spec.rb +1 -1
  184. data/spec/mongoid/{relations → association}/embedded/dirty_spec.rb +0 -0
  185. data/spec/mongoid/{relations/bindings/embedded/in_spec.rb → association/embedded/embedded_in/binding_spec.rb} +13 -13
  186. data/spec/mongoid/{relations/builders/embedded/in_spec.rb → association/embedded/embedded_in/buildable_spec.rb} +9 -9
  187. data/spec/mongoid/{relations/embedded/in_spec.rb → association/embedded/embedded_in/proxy_spec.rb} +55 -77
  188. data/spec/mongoid/association/embedded/embedded_in_spec.rb +901 -0
  189. data/spec/mongoid/{relations/bindings/embedded/many_spec.rb → association/embedded/embeds_many/binding_spec.rb} +3 -3
  190. data/spec/mongoid/{relations/builders/embedded/many_spec.rb → association/embedded/embeds_many/buildable_spec.rb} +17 -45
  191. data/spec/mongoid/{relations/embedded/many_spec.rb → association/embedded/embeds_many/proxy_spec.rb} +124 -182
  192. data/spec/mongoid/association/embedded/embeds_many_models.rb +53 -0
  193. data/spec/mongoid/association/embedded/embeds_many_spec.rb +862 -0
  194. data/spec/mongoid/{relations/bindings/embedded/one_spec.rb → association/embedded/embeds_one/binding_spec.rb} +4 -4
  195. data/spec/mongoid/{relations/builders/embedded/one_spec.rb → association/embedded/embeds_one/buildable_spec.rb} +14 -34
  196. data/spec/mongoid/{relations/embedded/one_spec.rb → association/embedded/embeds_one/proxy_spec.rb} +39 -84
  197. data/spec/mongoid/association/embedded/embeds_one_dnl_models.rb +6 -0
  198. data/spec/mongoid/association/embedded/embeds_one_models.rb +51 -0
  199. data/spec/mongoid/association/embedded/embeds_one_spec.rb +954 -0
  200. data/spec/mongoid/{relations → association}/macros_spec.rb +148 -73
  201. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/many_spec.rb +16 -19
  202. data/spec/mongoid/{relations/builders/nested_attributes → association/nested}/one_spec.rb +17 -20
  203. data/spec/mongoid/association/options_spec.rb +1321 -0
  204. data/spec/mongoid/{relations → association}/polymorphic_spec.rb +66 -34
  205. data/spec/mongoid/{relations/bindings/referenced/in_spec.rb → association/referenced/belongs_to/binding_spec.rb} +7 -7
  206. data/spec/mongoid/{relations/builders/referenced/in_spec.rb → association/referenced/belongs_to/buildable_spec.rb} +46 -79
  207. data/spec/mongoid/{relations/eager/belongs_to_spec.rb → association/referenced/belongs_to/eager_spec.rb} +33 -14
  208. data/spec/mongoid/{relations/referenced/in_spec.rb → association/referenced/belongs_to/proxy_spec.rb} +57 -91
  209. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2023 -0
  210. data/spec/mongoid/{relations/bindings/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/binding_spec.rb} +5 -5
  211. data/spec/mongoid/association/referenced/has_and_belongs_to_many/buildable_spec.rb +121 -0
  212. data/spec/mongoid/{relations/eager/has_and_belongs_to_many_spec.rb → association/referenced/has_and_belongs_to_many/eager_spec.rb} +26 -7
  213. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +56 -0
  214. data/spec/mongoid/{relations/referenced/many_to_many_spec.rb → association/referenced/has_and_belongs_to_many/proxy_spec.rb} +247 -99
  215. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +26 -0
  216. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +1027 -0
  217. data/spec/mongoid/{relations/bindings/referenced/many_spec.rb → association/referenced/has_many/binding_spec.rb} +5 -5
  218. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +119 -0
  219. data/spec/mongoid/{relations/eager/has_many_spec.rb → association/referenced/has_many/eager_spec.rb} +26 -11
  220. data/spec/mongoid/{relations/targets → association/referenced/has_many}/enumerable_spec.rb +227 -1
  221. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
  222. data/spec/mongoid/{relations/referenced/many_spec.rb → association/referenced/has_many/proxy_spec.rb} +30 -94
  223. data/spec/mongoid/association/referenced/has_many_models.rb +37 -0
  224. data/spec/mongoid/association/referenced/has_many_spec.rb +1225 -0
  225. data/spec/mongoid/{relations/bindings/referenced/one_spec.rb → association/referenced/has_one/binding_spec.rb} +4 -4
  226. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +113 -0
  227. data/spec/mongoid/{relations/eager/has_one_spec.rb → association/referenced/has_one/eager_spec.rb} +10 -10
  228. data/spec/mongoid/{relations/referenced/one_spec.rb → association/referenced/has_one/proxy_spec.rb} +9 -109
  229. data/spec/mongoid/association/referenced/has_one_models.rb +48 -0
  230. data/spec/mongoid/association/referenced/has_one_spec.rb +1360 -0
  231. data/spec/mongoid/{relations → association}/reflections_spec.rb +1 -12
  232. data/spec/mongoid/{relations/synchronization_spec.rb → association/syncable_spec.rb} +4 -2
  233. data/spec/mongoid/{relations_spec.rb → association_spec.rb} +1 -1
  234. data/spec/mongoid/atomic/modifiers_spec.rb +2 -2
  235. data/spec/mongoid/atomic/paths_spec.rb +41 -0
  236. data/spec/mongoid/atomic_spec.rb +4 -4
  237. data/spec/mongoid/attributes/dynamic_spec.rb +153 -0
  238. data/spec/mongoid/attributes/nested_spec.rb +29 -11
  239. data/spec/mongoid/attributes/readonly_spec.rb +80 -125
  240. data/spec/mongoid/attributes_spec.rb +298 -9
  241. data/spec/mongoid/clients/factory_spec.rb +20 -38
  242. data/spec/mongoid/clients/options_spec.rb +64 -50
  243. data/spec/mongoid/clients/sessions_spec.rb +9 -5
  244. data/spec/mongoid/clients/transactions_spec.rb +390 -0
  245. data/spec/mongoid/clients_spec.rb +70 -10
  246. data/spec/mongoid/config_spec.rb +27 -1
  247. data/spec/mongoid/contextual/atomic_spec.rb +37 -14
  248. data/spec/mongoid/contextual/geo_near_spec.rb +11 -2
  249. data/spec/mongoid/contextual/map_reduce_spec.rb +20 -5
  250. data/spec/mongoid/contextual/memory_spec.rb +19 -0
  251. data/spec/mongoid/contextual/mongo_spec.rb +107 -56
  252. data/spec/mongoid/copyable_spec.rb +90 -6
  253. data/spec/mongoid/copyable_spec_models.rb +17 -0
  254. data/spec/mongoid/criteria/modifiable_spec.rb +173 -1
  255. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +54 -0
  256. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +7 -7
  257. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +44 -1
  258. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +19 -7
  259. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +28 -1
  260. data/spec/mongoid/criteria/queryable/key_spec.rb +48 -6
  261. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +12 -0
  262. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +762 -0
  263. data/spec/mongoid/criteria/queryable/selectable_spec.rb +5 -224
  264. data/spec/mongoid/criteria/queryable/selector_spec.rb +37 -0
  265. data/spec/mongoid/criteria_spec.rb +36 -19
  266. data/spec/mongoid/document_fields_spec.rb +88 -0
  267. data/spec/mongoid/document_persistence_context_spec.rb +33 -0
  268. data/spec/mongoid/document_spec.rb +29 -4
  269. data/spec/mongoid/extensions/array_spec.rb +11 -15
  270. data/spec/mongoid/extensions/hash_spec.rb +18 -1
  271. data/spec/mongoid/extensions/object_spec.rb +7 -11
  272. data/spec/mongoid/extensions/range_spec.rb +7 -0
  273. data/spec/mongoid/factory_spec.rb +21 -3
  274. data/spec/mongoid/fields/foreign_key_spec.rb +24 -32
  275. data/spec/mongoid/fields_spec.rb +1 -1
  276. data/spec/mongoid/indexable_spec.rb +24 -12
  277. data/spec/mongoid/interceptable_spec.rb +22 -1
  278. data/spec/mongoid/matchable/default_spec.rb +10 -3
  279. data/spec/mongoid/matchable/elem_match_spec.rb +20 -0
  280. data/spec/mongoid/matchable/eq_spec.rb +48 -0
  281. data/spec/mongoid/matchable/regexp_spec.rb +2 -2
  282. data/spec/mongoid/matchable_spec.rb +2 -2
  283. data/spec/mongoid/persistable/pushable_spec.rb +55 -1
  284. data/spec/mongoid/persistable/savable_spec.rb +5 -5
  285. data/spec/mongoid/persistable/settable_spec.rb +125 -10
  286. data/spec/mongoid/persistable_spec.rb +21 -6
  287. data/spec/mongoid/persistence_context_spec.rb +1 -1
  288. data/spec/mongoid/query_cache_spec.rb +65 -27
  289. data/spec/mongoid/relations/proxy_spec.rb +124 -124
  290. data/spec/mongoid/scopable_spec.rb +2 -1
  291. data/spec/mongoid/shardable_spec.rb +32 -12
  292. data/spec/mongoid/tasks/database_rake_spec.rb +13 -13
  293. data/spec/mongoid/tasks/database_spec.rb +1 -1
  294. data/spec/mongoid/{relations/touchable_spec.rb → touchable_spec.rb} +40 -1
  295. data/spec/mongoid/validatable/associated_spec.rb +1 -1
  296. data/spec/mongoid/validatable/presence_spec.rb +7 -6
  297. data/spec/mongoid/validatable/uniqueness_spec.rb +33 -6
  298. data/spec/mongoid/validatable_spec.rb +1 -1
  299. data/spec/shared/LICENSE +20 -0
  300. data/spec/shared/bin/get-mongodb-download-url +17 -0
  301. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  302. data/spec/shared/lib/mrss/cluster_config.rb +221 -0
  303. data/spec/shared/lib/mrss/constraints.rb +354 -0
  304. data/spec/shared/lib/mrss/docker_runner.rb +265 -0
  305. data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
  306. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  307. data/spec/shared/lib/mrss/spec_organizer.rb +162 -0
  308. data/spec/shared/lib/mrss/utils.rb +15 -0
  309. data/spec/shared/share/Dockerfile.erb +231 -0
  310. data/spec/shared/shlib/distro.sh +73 -0
  311. data/spec/shared/shlib/server.sh +290 -0
  312. data/spec/shared/shlib/set_env.sh +128 -0
  313. data/spec/spec_helper.rb +34 -49
  314. data/spec/support/cluster_config.rb +3 -3
  315. data/spec/support/constraints.rb +21 -76
  316. data/spec/support/expectations.rb +17 -3
  317. data/spec/support/spec_config.rb +20 -7
  318. data.tar.gz.sig +0 -0
  319. metadata +646 -541
  320. metadata.gz.sig +1 -5
  321. data/lib/mongoid/relations/accessors.rb +0 -267
  322. data/lib/mongoid/relations/auto_save.rb +0 -94
  323. data/lib/mongoid/relations/bindings/embedded/in.rb +0 -59
  324. data/lib/mongoid/relations/bindings/referenced/in.rb +0 -65
  325. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +0 -70
  326. data/lib/mongoid/relations/bindings.rb +0 -9
  327. data/lib/mongoid/relations/builder.rb +0 -57
  328. data/lib/mongoid/relations/builders/nested_attributes/many.rb +0 -199
  329. data/lib/mongoid/relations/builders/referenced/in.rb +0 -26
  330. data/lib/mongoid/relations/builders/referenced/many.rb +0 -26
  331. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +0 -39
  332. data/lib/mongoid/relations/builders/referenced/one.rb +0 -26
  333. data/lib/mongoid/relations/builders.rb +0 -106
  334. data/lib/mongoid/relations/cascading/delete.rb +0 -44
  335. data/lib/mongoid/relations/cascading/destroy.rb +0 -43
  336. data/lib/mongoid/relations/cascading/nullify.rb +0 -35
  337. data/lib/mongoid/relations/cascading/restrict.rb +0 -39
  338. data/lib/mongoid/relations/cascading.rb +0 -56
  339. data/lib/mongoid/relations/conversions.rb +0 -34
  340. data/lib/mongoid/relations/counter_cache.rb +0 -160
  341. data/lib/mongoid/relations/cyclic.rb +0 -107
  342. data/lib/mongoid/relations/eager/base.rb +0 -153
  343. data/lib/mongoid/relations/eager/belongs_to.rb +0 -31
  344. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +0 -47
  345. data/lib/mongoid/relations/eager/has_many.rb +0 -38
  346. data/lib/mongoid/relations/eager/has_one.rb +0 -30
  347. data/lib/mongoid/relations/embedded/in.rb +0 -241
  348. data/lib/mongoid/relations/embedded/many.rb +0 -683
  349. data/lib/mongoid/relations/embedded/one.rb +0 -235
  350. data/lib/mongoid/relations/macros.rb +0 -367
  351. data/lib/mongoid/relations/metadata.rb +0 -1179
  352. data/lib/mongoid/relations/nested_builder.rb +0 -74
  353. data/lib/mongoid/relations/options.rb +0 -49
  354. data/lib/mongoid/relations/polymorphic.rb +0 -39
  355. data/lib/mongoid/relations/referenced/in.rb +0 -304
  356. data/lib/mongoid/relations/referenced/many.rb +0 -812
  357. data/lib/mongoid/relations/referenced/many_to_many.rb +0 -479
  358. data/lib/mongoid/relations/referenced/one.rb +0 -290
  359. data/lib/mongoid/relations/synchronization.rb +0 -169
  360. data/lib/mongoid/relations/targets/enumerable.rb +0 -493
  361. data/lib/mongoid/relations/targets.rb +0 -2
  362. data/lib/mongoid/relations/touchable.rb +0 -97
  363. data/spec/mongoid/fields/internal/foreign_keys/array_spec.rb +0 -184
  364. data/spec/mongoid/fields/internal/foreign_keys/object_spec.rb +0 -201
  365. data/spec/mongoid/relations/builders/referenced/many_spec.rb +0 -137
  366. data/spec/mongoid/relations/builders/referenced/many_to_many_spec.rb +0 -178
  367. data/spec/mongoid/relations/builders/referenced/one_spec.rb +0 -111
  368. data/spec/mongoid/relations/cascading/delete_spec.rb +0 -101
  369. data/spec/mongoid/relations/cascading/destroy_spec.rb +0 -47
  370. data/spec/mongoid/relations/cascading/nullify_spec.rb +0 -32
  371. data/spec/mongoid/relations/cascading/restrict_spec.rb +0 -68
  372. data/spec/mongoid/relations/cascading_spec.rb +0 -355
  373. data/spec/mongoid/relations/constraint_spec.rb +0 -75
  374. data/spec/mongoid/relations/conversions_spec.rb +0 -128
  375. data/spec/mongoid/relations/metadata_spec.rb +0 -1985
  376. data/spec/mongoid/relations/options_spec.rb +0 -35
@@ -0,0 +1,2023 @@
1
+ require "spec_helper"
2
+ require_relative './has_one_models'
3
+
4
+ describe Mongoid::Association::Referenced::BelongsTo do
5
+
6
+ before do
7
+ class OwnerObject; include Mongoid::Document; end
8
+ class BelongingObject; include Mongoid::Document; end
9
+ end
10
+
11
+ after do
12
+ Object.send(:remove_const, :BelongingObject)
13
+ Object.send(:remove_const, :OwnerObject)
14
+ end
15
+
16
+ let(:belonging_class) do
17
+ BelongingObject
18
+ end
19
+
20
+ let(:name) do
21
+ :owner_object
22
+ end
23
+
24
+ let(:association) do
25
+ belonging_class.belongs_to name, options
26
+ end
27
+
28
+ let(:options) do
29
+ { }
30
+ end
31
+
32
+ describe '#relation_complements' do
33
+
34
+ let(:expected_complements) do
35
+ [
36
+ Mongoid::Association::Referenced::HasMany,
37
+ Mongoid::Association::Referenced::HasOne
38
+ ]
39
+ end
40
+
41
+ it 'returns the relation complements' do
42
+ expect(association.relation_complements).to eq(expected_complements)
43
+ end
44
+ end
45
+
46
+ describe '#setup!' do
47
+
48
+ it 'sets up a getter for the relation' do
49
+ expect(Mongoid::Association::Accessors).to receive(:define_getter!).with(association)
50
+ association.setup!
51
+ end
52
+
53
+ it 'sets up a setter for the relation' do
54
+ expect(Mongoid::Association::Accessors).to receive(:define_setter!).with(association)
55
+ association.setup!
56
+ end
57
+
58
+ it 'sets up an existence check for the relation' do
59
+ expect(Mongoid::Association::Accessors).to receive(:define_existence_check!).with(association)
60
+ association.setup!
61
+ end
62
+
63
+ it 'sets up the builder for the relation' do
64
+ expect(Mongoid::Association::Builders).to receive(:define_builder!).with(association)
65
+ association.setup!
66
+ end
67
+
68
+ it 'sets up the creator for the relation' do
69
+ expect(Mongoid::Association::Builders).to receive(:define_creator!).with(association)
70
+ association.setup!
71
+ end
72
+
73
+ context 'autosave' do
74
+
75
+ context 'when the :autosave option is true' do
76
+
77
+ let(:options) do
78
+ {
79
+ autosave: true
80
+ }
81
+ end
82
+
83
+ let(:association) do
84
+ # Note that it is necessary to create the association directly, otherwise the
85
+ # setup!! method will be called by the :belongs_to macro
86
+ described_class.new(belonging_class, name, options)
87
+ end
88
+
89
+ it 'sets up autosave' do
90
+ expect(Mongoid::Association::Referenced::AutoSave).to receive(:define_autosave!).with(association)
91
+ association.setup!
92
+ end
93
+ end
94
+
95
+ context 'when the :autosave option is false' do
96
+
97
+ let(:options) do
98
+ {
99
+ autosave: false
100
+ }
101
+ end
102
+
103
+ it 'does not set up autosave' do
104
+ expect(Mongoid::Association::Referenced::AutoSave).not_to receive(:define_autosave!)
105
+ association.setup!
106
+ end
107
+ end
108
+
109
+ context 'when the :autosave option is not provided' do
110
+
111
+ let(:association) do
112
+ # Note that it is necessary to create the association directly, otherwise the
113
+ # setup!! method will be called by the :embeds_many macro
114
+ described_class.new(belonging_class, name, options)
115
+ end
116
+
117
+ it 'does not set up autosave' do
118
+ expect(Mongoid::Association::Referenced::AutoSave).not_to receive(:define_autosave!)
119
+ association.setup!
120
+ end
121
+ end
122
+ end
123
+
124
+ context 'counter cache callbacks' do
125
+
126
+ context 'when the :counter_cache option is true' do
127
+
128
+ let(:options) do
129
+ {
130
+ counter_cache: true
131
+ }
132
+ end
133
+
134
+ let(:association) do
135
+ # Note that it is necessary to create the association directly, otherwise the
136
+ # setup! method will be called by the :belongs_to macro
137
+ described_class.new(belonging_class, name, options)
138
+ end
139
+
140
+ it 'sets up counter cache callbacks' do
141
+ expect(Mongoid::Association::Referenced::CounterCache).to receive(:define_callbacks!).with(association)
142
+ association.setup!
143
+ end
144
+ end
145
+
146
+ context 'when the :counter_cache option is a String' do
147
+
148
+ let(:options) do
149
+ {
150
+ counter_cache: 'counts_field'
151
+ }
152
+ end
153
+
154
+ let(:association) do
155
+ # Note that it is necessary to create the association directly, otherwise the
156
+ # setup! method will be called by the :belongs_to macro
157
+ described_class.new(belonging_class, name, options)
158
+ end
159
+
160
+ it 'sets up counter cache callbacks' do
161
+ expect(Mongoid::Association::Referenced::CounterCache).to receive(:define_callbacks!).with(association)
162
+ association.setup!
163
+ end
164
+ end
165
+
166
+ context 'when the :counter_cache option is false' do
167
+
168
+ let(:options) do
169
+ {
170
+ counter_cache: false
171
+ }
172
+ end
173
+
174
+ it 'does not set up counter cache callbacks' do
175
+ expect(Mongoid::Association::Referenced::CounterCache).not_to receive(:define_callbacks!)
176
+ association.setup!
177
+ end
178
+ end
179
+
180
+ context 'when the :counter_cache option is not provided' do
181
+
182
+ let(:association) do
183
+ # Note that it is necessary to create the association directly, otherwise the
184
+ # setup! method will be called by the :embeds_many macro
185
+ described_class.new(belonging_class, name, options)
186
+ end
187
+
188
+ it 'does not set up counter cache callbacks' do
189
+ expect(Mongoid::Association::Referenced::CounterCache).not_to receive(:define_callbacks!)
190
+ association.setup!
191
+ end
192
+ end
193
+ end
194
+
195
+ context 'polymorphic' do
196
+
197
+ context 'when the polymorphic option is provided' do
198
+
199
+ context 'when the polymorphic option is true' do
200
+
201
+ let(:options) do
202
+ {
203
+ polymorphic: true
204
+ }
205
+ end
206
+
207
+ before do
208
+ association
209
+ end
210
+
211
+ it 'set the polymorphic attribute on the owner class' do
212
+ expect(belonging_class.polymorphic).to be(true)
213
+ end
214
+
215
+ it 'sets up a field for the inverse type' do
216
+ expect(belonging_class.fields.keys).to include(association.inverse_type)
217
+ end
218
+ end
219
+
220
+ context 'when the polymorphic option is false' do
221
+
222
+ let(:options) do
223
+ {
224
+ polymorphic: false
225
+ }
226
+ end
227
+
228
+ it 'does not set the polymorphic attribute on the owner class' do
229
+ expect(belonging_class.polymorphic).to be(false)
230
+ end
231
+
232
+ it 'does not set up a field for the inverse type' do
233
+ expect(belonging_class.fields.keys).not_to include(association.inverse_type)
234
+ end
235
+ end
236
+ end
237
+
238
+ context 'when the polymorphic option is not provided' do
239
+
240
+ it 'does not set the polymorphic attribute on the owner class' do
241
+ expect(belonging_class.polymorphic).to be(false)
242
+ end
243
+
244
+ it 'does not set up a field for the inverse type' do
245
+ expect(belonging_class.fields.keys).not_to include(association.inverse_type)
246
+ end
247
+ end
248
+ end
249
+
250
+ context 'dependent' do
251
+
252
+ context 'when the dependent option is provided' do
253
+
254
+ context 'when the dependent option is :delete_all' do
255
+
256
+ let(:options) do
257
+ {
258
+ dependent: :delete_all
259
+ }
260
+ end
261
+
262
+ let(:association) do
263
+ # Note that it is necessary to create the association directly, otherwise the
264
+ # setup! method will be called by the :belongs_to macro
265
+ described_class.new(belonging_class, name, options)
266
+ end
267
+
268
+ it 'sets up the dependency' do
269
+ expect(Mongoid::Association::Depending).to receive(:define_dependency!)
270
+ association.setup!
271
+ end
272
+ end
273
+
274
+ context 'when the dependent option is :destroy' do
275
+
276
+ let(:options) do
277
+ {
278
+ dependent: :destroy
279
+ }
280
+ end
281
+
282
+ let(:association) do
283
+ # Note that it is necessary to create the association directly, otherwise the
284
+ # setup! method will be called by the :belongs_to macro
285
+ described_class.new(belonging_class, name, options)
286
+ end
287
+
288
+ it 'sets up the dependency' do
289
+ expect(Mongoid::Association::Depending).to receive(:define_dependency!)
290
+ association.setup!
291
+ end
292
+ end
293
+
294
+ context 'when the dependent option is :nullify' do
295
+
296
+ let(:options) do
297
+ {
298
+ dependent: :nullify
299
+ }
300
+ end
301
+
302
+ let(:association) do
303
+ # Note that it is necessary to create the association directly, otherwise the
304
+ # setup! method will be called by the :belongs_to macro
305
+ described_class.new(belonging_class, name, options)
306
+ end
307
+
308
+ it 'sets up the dependency' do
309
+ expect(Mongoid::Association::Depending).to receive(:define_dependency!)
310
+ association.setup!
311
+ end
312
+ end
313
+
314
+ context 'when the dependent option is :restrict_with_exception' do
315
+
316
+ let(:options) do
317
+ {
318
+ dependent: :restrict_with_exception
319
+ }
320
+ end
321
+
322
+ let(:association) do
323
+ # Note that it is necessary to create the association directly, otherwise the
324
+ # setup! method will be called by the :belongs_to macro
325
+ described_class.new(belonging_class, name, options)
326
+ end
327
+
328
+ it 'sets up the dependency' do
329
+ expect(Mongoid::Association::Depending).to receive(:define_dependency!)
330
+ association.setup!
331
+ end
332
+ end
333
+
334
+ context 'when the dependent option is :restrict_with_error' do
335
+
336
+ let(:options) do
337
+ {
338
+ dependent: :restrict_with_error
339
+ }
340
+ end
341
+
342
+ let(:association) do
343
+ # Note that it is necessary to create the association directly, otherwise the
344
+ # setup! method will be called by the :belongs_to macro
345
+ described_class.new(belonging_class, name, options)
346
+ end
347
+
348
+ it 'sets up the dependency' do
349
+ expect(Mongoid::Association::Depending).to receive(:define_dependency!)
350
+ association.setup!
351
+ end
352
+ end
353
+ end
354
+
355
+ context 'when the dependent option is not provided' do
356
+
357
+ it 'does not set up the dependency' do
358
+ expect(Mongoid::Association::Depending).not_to receive(:define_dependency!)
359
+ association.setup!
360
+ end
361
+ end
362
+ end
363
+
364
+ context 'foreign key field' do
365
+
366
+ before do
367
+ association
368
+ end
369
+
370
+ it 'sets up the foreign key field' do
371
+ expect(belonging_class.fields.keys).to include(association.foreign_key)
372
+ end
373
+ end
374
+
375
+ context 'index' do
376
+
377
+ before do
378
+ association
379
+ end
380
+
381
+ context 'when index is true' do
382
+
383
+ context 'when polymorphic' do
384
+
385
+ let(:options) do
386
+ {
387
+ polymorphic: true,
388
+ index: true
389
+ }
390
+ end
391
+
392
+ it 'sets up the index with the key and inverse type' do
393
+ expect(belonging_class.index_specifications.first.fields).to match_array([ association.key.to_sym,
394
+ association.inverse_type.to_sym])
395
+ end
396
+ end
397
+
398
+ context 'when not polymorphic' do
399
+
400
+ let(:options) do
401
+ {
402
+ index: true
403
+ }
404
+ end
405
+
406
+ it 'sets up the index with the key' do
407
+ expect(belonging_class.index_specifications.first.fields).to match_array([ association.key.to_sym ])
408
+ end
409
+ end
410
+ end
411
+
412
+ context 'when index is false' do
413
+
414
+ context 'when polymorphic' do
415
+
416
+ let(:options) do
417
+ {
418
+ polymorphic: true
419
+ }
420
+ end
421
+
422
+ it 'does not set up an index' do
423
+ expect(belonging_class.index_specifications).to eq([ ])
424
+ end
425
+ end
426
+
427
+ context 'when not polymorphic' do
428
+
429
+ it 'does not set up an index' do
430
+ expect(belonging_class.index_specifications).to eq([ ])
431
+ end
432
+ end
433
+ end
434
+ end
435
+
436
+ context 'touchable' do
437
+
438
+ context 'when the :touch option is true' do
439
+
440
+ let(:options) do
441
+ {
442
+ touch: true
443
+ }
444
+ end
445
+
446
+ let(:association) do
447
+ # Note that it is necessary to create the association directly, otherwise the
448
+ # setup! method will be called by the :belongs_to macro
449
+ described_class.new(belonging_class, name, options)
450
+ end
451
+
452
+ it 'sets up touch' do
453
+ expect(Mongoid::Touchable).to receive(:define_touchable!).with(association)
454
+ association.setup!
455
+ end
456
+ end
457
+
458
+ context 'when the :touch option is false' do
459
+
460
+ let(:options) do
461
+ {
462
+ touch: false
463
+ }
464
+ end
465
+
466
+ it 'does not set up touch' do
467
+ expect(Mongoid::Touchable).not_to receive(:define_touchable!).with(association)
468
+ association.setup!
469
+ end
470
+ end
471
+
472
+ context 'when the :touch option is not provided' do
473
+
474
+ let(:association) do
475
+ # Note that it is necessary to create the association directly, otherwise the
476
+ # setup! method will be called by the :embeds_many macro
477
+ described_class.new(belonging_class, name, options)
478
+ end
479
+
480
+ it 'does not set up touch' do
481
+ expect(Mongoid::Touchable).not_to receive(:define_touchable!).with(association)
482
+ association.setup!
483
+ end
484
+ end
485
+ end
486
+
487
+ context 'validate' do
488
+
489
+ context 'when the :validate option is true' do
490
+
491
+ let(:options) do
492
+ {
493
+ validate: true
494
+ }
495
+ end
496
+
497
+ let(:association) do
498
+ # Note that it is necessary to create the association directly, otherwise the
499
+ # setup! method will be called by the :belongs_to macro
500
+ described_class.new(belonging_class, name, options)
501
+ end
502
+
503
+ it 'sets up validation' do
504
+ expect(belonging_class).to receive(:validates_associated).with(name).and_call_original
505
+ association.setup!
506
+ end
507
+ end
508
+
509
+ context 'when the :validate option is false' do
510
+
511
+ let(:options) do
512
+ {
513
+ validate: false
514
+ }
515
+ end
516
+
517
+ it 'does not set up validation' do
518
+ expect(belonging_class).not_to receive(:validates_associated)
519
+ association.setup!
520
+ end
521
+ end
522
+
523
+ context 'when the :validate option is not provided' do
524
+
525
+ let(:association) do
526
+ # Note that it is necessary to create the association directly, otherwise the
527
+ # setup! method will be called by the :belongs_to macro
528
+ described_class.new(belonging_class, name, options)
529
+ end
530
+
531
+ it 'does not set up the validation because it uses the validation default (false)' do
532
+ expect(belonging_class).not_to receive(:validates_associated)
533
+ association.setup!
534
+ end
535
+ end
536
+ end
537
+
538
+ context 'presence of validation' do
539
+
540
+ let(:association) do
541
+ # Note that it is necessary to create the association directly, otherwise the
542
+ # setup! method will be called by the :belongs_to macro
543
+ described_class.new(belonging_class, name, options)
544
+ end
545
+
546
+ context 'when the global config option is true' do
547
+
548
+ around(:example) do |example|
549
+ original_config = Mongoid.belongs_to_required_by_default
550
+ Mongoid.belongs_to_required_by_default = true
551
+ example.run
552
+ Mongoid.belongs_to_required_by_default = original_config
553
+ end
554
+
555
+ let!(:original_required_config) do
556
+ Mongoid.belongs_to_required_by_default
557
+ end
558
+
559
+ context 'when the required option is true' do
560
+
561
+ let(:options) do
562
+ {
563
+ required: true
564
+ }
565
+ end
566
+
567
+ it 'sets up the presence of validation' do
568
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
569
+ association.setup!
570
+ end
571
+
572
+ context 'when the optional option is true' do
573
+
574
+ let(:options) do
575
+ {
576
+ required: true,
577
+ optional: true
578
+ }
579
+ end
580
+
581
+ it 'sets up the presence of validation' do
582
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
583
+ association.setup!
584
+ end
585
+ end
586
+
587
+ context 'when the optional option is false' do
588
+
589
+ let(:options) do
590
+ {
591
+ required: true,
592
+ optional: false
593
+ }
594
+ end
595
+
596
+ it 'sets up the presence of validation' do
597
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
598
+ association.setup!
599
+ end
600
+ end
601
+ end
602
+
603
+ context 'when the required option is false' do
604
+
605
+ let(:options) do
606
+ {
607
+ required: false
608
+ }
609
+ end
610
+
611
+ it 'does not set up the presence of validation' do
612
+ expect(belonging_class).not_to receive(:validates)
613
+ association.setup!
614
+ end
615
+
616
+ context 'when the optional option is true' do
617
+
618
+ let(:options) do
619
+ {
620
+ required: false,
621
+ optional: true
622
+ }
623
+ end
624
+
625
+ it 'does not set up the presence of validation' do
626
+ expect(belonging_class).not_to receive(:validates)
627
+ association.setup!
628
+ end
629
+ end
630
+
631
+ context 'when the optional option is false' do
632
+
633
+ let(:options) do
634
+ {
635
+ required: false,
636
+ optional: false
637
+ }
638
+ end
639
+
640
+ it 'does not set up the presence of validation' do
641
+ expect(belonging_class).not_to receive(:validates)
642
+ association.setup!
643
+ end
644
+ end
645
+ end
646
+
647
+ context 'when the required option is not provided' do
648
+
649
+ it 'uses the default and sets up the presence of validation' do
650
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
651
+ association.setup!
652
+ end
653
+
654
+ context 'when the optional option is true' do
655
+
656
+ let(:options) do
657
+ {
658
+ optional: true
659
+ }
660
+ end
661
+
662
+ it 'does not set up the presence of validation' do
663
+ expect(belonging_class).not_to receive(:validates)
664
+ association.setup!
665
+ end
666
+ end
667
+
668
+ context 'when the optional option is false' do
669
+
670
+ let(:options) do
671
+ {
672
+ optional: false
673
+ }
674
+ end
675
+
676
+ it 'sets up the presence of validation' do
677
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
678
+ association.setup!
679
+ end
680
+ end
681
+ end
682
+ end
683
+
684
+ context 'when the global config option is false' do
685
+
686
+ around(:example) do |example|
687
+ original_config = Mongoid.belongs_to_required_by_default
688
+ Mongoid.belongs_to_required_by_default = false
689
+ example.run
690
+ Mongoid.belongs_to_required_by_default = original_config
691
+ end
692
+
693
+ context 'when the required option is true' do
694
+
695
+ let(:options) do
696
+ {
697
+ required: true
698
+ }
699
+ end
700
+
701
+ it 'sets up the presence of validation' do
702
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
703
+ association.setup!
704
+ end
705
+
706
+ context 'when the optional option is true' do
707
+
708
+ let(:options) do
709
+ {
710
+ required: true,
711
+ optional: true
712
+ }
713
+ end
714
+
715
+ it 'sets up the presence of validation' do
716
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
717
+ association.setup!
718
+ end
719
+ end
720
+
721
+ context 'when the optional option is false' do
722
+
723
+ let(:options) do
724
+ {
725
+ required: true,
726
+ optional: false
727
+ }
728
+ end
729
+
730
+ it 'sets up the presence of validation' do
731
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
732
+ association.setup!
733
+ end
734
+ end
735
+ end
736
+
737
+ context 'when the required option is false' do
738
+
739
+ let(:options) do
740
+ {
741
+ required: false
742
+ }
743
+ end
744
+
745
+ it 'does not set up the presence of validation' do
746
+ expect(belonging_class).not_to receive(:validates)
747
+ association.setup!
748
+ end
749
+
750
+ context 'when the optional option is true' do
751
+
752
+ let(:options) do
753
+ {
754
+ required: false,
755
+ optional: true
756
+ }
757
+ end
758
+
759
+ it 'does not set up the presence of validation' do
760
+ expect(belonging_class).not_to receive(:validates)
761
+ association.setup!
762
+ end
763
+ end
764
+
765
+ context 'when the optional option is false' do
766
+
767
+ let(:options) do
768
+ {
769
+ required: false,
770
+ optional: false
771
+ }
772
+ end
773
+
774
+ it 'does not set up the presence of validation' do
775
+ expect(belonging_class).not_to receive(:validates)
776
+ association.setup!
777
+ end
778
+ end
779
+ end
780
+
781
+ context 'when the required option is not provided' do
782
+
783
+ it 'uses the default and does not set up the presence of validation' do
784
+ expect(belonging_class).not_to receive(:validates)
785
+ association.setup!
786
+ end
787
+
788
+ context 'when the optional option is true' do
789
+
790
+ let(:options) do
791
+ {
792
+ optional: true
793
+ }
794
+ end
795
+
796
+ it 'does not set up the presence of validation' do
797
+ expect(belonging_class).not_to receive(:validates)
798
+ association.setup!
799
+ end
800
+ end
801
+
802
+ context 'when the optional option is false' do
803
+
804
+ let(:options) do
805
+ {
806
+ optional: false
807
+ }
808
+ end
809
+
810
+ it 'sets up the presence of validation' do
811
+ expect(belonging_class).to receive(:validates).with(name, { presence: true }).and_call_original
812
+ association.setup!
813
+ end
814
+ end
815
+ end
816
+ end
817
+ end
818
+ end
819
+
820
+ describe '#type' do
821
+
822
+ context 'when polymorphic' do
823
+
824
+ let(:options) do
825
+ { polymorphic: true }
826
+ end
827
+
828
+ it 'returns nil' do
829
+ expect(association.type).to be_nil
830
+ end
831
+ end
832
+
833
+ context 'when not polymorphic' do
834
+
835
+ it 'returns nil' do
836
+ expect(association.type).to be_nil
837
+ end
838
+ end
839
+ end
840
+
841
+ describe '#inverse_type' do
842
+
843
+ context 'when polymorphic' do
844
+
845
+ let(:options) do
846
+ { polymorphic: true }
847
+ end
848
+
849
+ it 'returns the name followed by "_type"' do
850
+ expect(association.inverse_type).to eq("#{name}_type")
851
+ end
852
+ end
853
+
854
+ context 'when not polymorphic' do
855
+
856
+ it 'returns nil' do
857
+ expect(association.inverse_type).to be_nil
858
+ end
859
+ end
860
+ end
861
+
862
+ describe '#inverse_type_setter' do
863
+
864
+ context 'when polymorphic' do
865
+
866
+ let(:options) do
867
+ { polymorphic: true }
868
+ end
869
+
870
+ it 'returns the inverse type setter' do
871
+ expect(association.inverse_type_setter).to eq("#{name}_type=")
872
+ end
873
+ end
874
+
875
+ context 'when not polymorphic' do
876
+
877
+ it 'returns nil' do
878
+ expect(association.inverse_type_setter).to be_nil
879
+ end
880
+ end
881
+ end
882
+
883
+ describe '#foreign_key' do
884
+
885
+ context 'when options has foreign_key specified' do
886
+
887
+ let(:options) do
888
+ { foreign_key: :other_object_id }
889
+ end
890
+
891
+ it 'returns the foreign key' do
892
+ expect(association.foreign_key).to eq(options[:foreign_key].to_s)
893
+ end
894
+ end
895
+
896
+ context 'when options does not have foreign_key specified' do
897
+
898
+ it 'returns the ame followed by "_id"' do
899
+ expect(association.foreign_key).to eq("#{name}_id")
900
+ end
901
+ end
902
+ end
903
+
904
+ describe '#embedded?' do
905
+
906
+ it 'returns false' do
907
+ expect(association.embedded?).to be(false)
908
+ end
909
+ end
910
+
911
+ describe '#primary_key' do
912
+
913
+ context 'when the :primary_key option is specified' do
914
+
915
+ context 'when the :primary_key option is true' do
916
+
917
+ let(:options) do
918
+ {
919
+ primary_key: :other_primary_key
920
+ }
921
+ end
922
+
923
+ it 'returns the primary key option as a String' do
924
+ expect(association.primary_key).to eq('other_primary_key')
925
+ end
926
+ end
927
+ end
928
+
929
+ context 'when the :primary_key option is not specified' do
930
+
931
+ it 'returns the default primary key' do
932
+ expect(association.primary_key).to eq(Mongoid::Association::Relatable::PRIMARY_KEY_DEFAULT)
933
+ end
934
+ end
935
+ end
936
+
937
+ describe '#indexed?' do
938
+
939
+ context 'when :index is specified in the options' do
940
+
941
+ context 'when :index is true' do
942
+
943
+ let(:options) do
944
+ {
945
+ index: true
946
+ }
947
+ end
948
+
949
+ it 'returns true' do
950
+ expect(association.indexed?).to be(true)
951
+ end
952
+ end
953
+
954
+ context 'when :index is false' do
955
+
956
+ let(:options) do
957
+ {
958
+ index: false
959
+ }
960
+ end
961
+
962
+ it 'returns false' do
963
+ expect(association.indexed?).to be(false)
964
+ end
965
+ end
966
+ end
967
+
968
+ context 'when :index is not specified in the options' do
969
+
970
+ it 'returns nil' do
971
+ expect(association.indexed?).to be(false)
972
+ end
973
+ end
974
+ end
975
+
976
+ describe '#relation' do
977
+
978
+ it 'returns Mongoid::Association::Referenced::BelongsTo::Proxy' do
979
+ expect(association.relation).to be(Mongoid::Association::Referenced::BelongsTo::Proxy)
980
+ end
981
+ end
982
+
983
+ describe '#validation_default' do
984
+
985
+ it 'returns false' do
986
+ expect(association.validation_default).to be(false)
987
+ end
988
+ end
989
+
990
+ describe '#name' do
991
+
992
+ it 'returns the name of the relation' do
993
+ expect(association.name).to be(name)
994
+ end
995
+ end
996
+
997
+ describe '#options' do
998
+
999
+ it 'returns the options' do
1000
+ expect(association.options).to be(options)
1001
+ end
1002
+ end
1003
+
1004
+ describe '#cyclic?' do
1005
+
1006
+ it 'returns false' do
1007
+ expect(association.cyclic?).to be(false)
1008
+ end
1009
+ end
1010
+
1011
+ describe '#merge!' do
1012
+
1013
+ end
1014
+
1015
+ describe '#store_as' do
1016
+
1017
+ it 'returns nil' do
1018
+ expect(association.store_as).to be_nil
1019
+ end
1020
+ end
1021
+
1022
+ describe '#touchable?' do
1023
+
1024
+ context 'when :touch is in the options' do
1025
+
1026
+ let(:options) do
1027
+ { touch: true}
1028
+ end
1029
+
1030
+ it 'returns true' do
1031
+ expect(association.send(:touchable?)).to be(true)
1032
+ end
1033
+ end
1034
+
1035
+ context 'when :touch is not in the options' do
1036
+
1037
+ it 'return false' do
1038
+ expect(association.send(:touchable?)).to be(false)
1039
+ end
1040
+ end
1041
+ end
1042
+
1043
+ describe '#order' do
1044
+
1045
+ it 'returns nil' do
1046
+ expect(association.order).to be_nil
1047
+ end
1048
+ end
1049
+
1050
+ describe '#as' do
1051
+
1052
+ it 'returns nil' do
1053
+ expect(association.as).to be_nil
1054
+ end
1055
+ end
1056
+
1057
+ describe '#polymorphic?' do
1058
+
1059
+ context 'when :polymorphic is specified in the options as true' do
1060
+
1061
+ let(:options) do
1062
+ { polymorphic: true }
1063
+ end
1064
+
1065
+ it 'returns true' do
1066
+ expect(association.polymorphic?).to be(true)
1067
+ end
1068
+ end
1069
+
1070
+ context 'when :polymorphic is specified in the options as false' do
1071
+
1072
+ let(:options) do
1073
+ { polymorphic: false }
1074
+ end
1075
+
1076
+ it 'returns false' do
1077
+ expect(association.polymorphic?).to be(false)
1078
+ end
1079
+ end
1080
+
1081
+ context 'when :polymorphic is not specified in the options' do
1082
+
1083
+ it 'returns false' do
1084
+ expect(association.polymorphic?).to be(false)
1085
+ end
1086
+ end
1087
+ end
1088
+
1089
+ describe '#dependent' do
1090
+
1091
+ context 'when the dependent option is provided' do
1092
+
1093
+ context 'when the dependent option is :delete_all' do
1094
+
1095
+ let(:options) do
1096
+ {
1097
+ dependent: :delete_all
1098
+ }
1099
+ end
1100
+
1101
+ it 'returns :delete_all' do
1102
+ expect(association.dependent).to eq(:delete_all)
1103
+ end
1104
+ end
1105
+
1106
+ context 'when the dependent option is :destroy' do
1107
+
1108
+ let(:options) do
1109
+ {
1110
+ dependent: :destroy
1111
+ }
1112
+ end
1113
+
1114
+ it 'returns :destroy' do
1115
+ expect(association.dependent).to eq(:destroy)
1116
+ end
1117
+ end
1118
+
1119
+ context 'when the dependent option is :nullify' do
1120
+
1121
+ let(:options) do
1122
+ {
1123
+ dependent: :nullify
1124
+ }
1125
+ end
1126
+
1127
+ it 'returns :nullify' do
1128
+ expect(association.dependent).to eq(:nullify)
1129
+ end
1130
+ end
1131
+
1132
+ context 'when the dependent option is :restrict_with_exception' do
1133
+
1134
+ let(:options) do
1135
+ {
1136
+ dependent: :restrict_with_exception
1137
+ }
1138
+ end
1139
+
1140
+ it 'returns :restrict_with_exception' do
1141
+ expect(association.dependent).to eq(:restrict_with_exception)
1142
+ end
1143
+ end
1144
+
1145
+ context 'when the dependent option is :restrict_with_error' do
1146
+
1147
+ let(:options) do
1148
+ {
1149
+ dependent: :restrict_with_error
1150
+ }
1151
+ end
1152
+
1153
+ it 'returns :restrict_with_error' do
1154
+ expect(association.dependent).to eq(:restrict_with_error)
1155
+ end
1156
+ end
1157
+ end
1158
+
1159
+ context 'when the dependent option is not provided' do
1160
+
1161
+ it 'returns nil' do
1162
+ expect(association.dependent).to be_nil
1163
+ end
1164
+ end
1165
+ end
1166
+
1167
+ describe '#bindable?' do
1168
+
1169
+ it 'returns false' do
1170
+ expect(association.bindable?(Person.new)).to be(false)
1171
+ end
1172
+ end
1173
+
1174
+ describe '#inverses' do
1175
+
1176
+ context 'when polymorphic' do
1177
+
1178
+ let(:options) do
1179
+ {
1180
+ polymorphic: true
1181
+ }
1182
+ end
1183
+
1184
+ let(:name) do
1185
+ :containable
1186
+ end
1187
+
1188
+ context 'when another object is passed to the method' do
1189
+
1190
+ let(:instance_of_other_class) do
1191
+ OwnerObject.new
1192
+ end
1193
+
1194
+ context 'when the relation class has only one relation whose class matches the owning class' do
1195
+
1196
+ before do
1197
+ OwnerObject.has_one :belonging_object, as: :containable
1198
+ end
1199
+
1200
+ context 'when :inverse_of is specified' do
1201
+
1202
+ before do
1203
+ options.merge!(inverse_of: :inverse_name)
1204
+ end
1205
+
1206
+ it 'returns the :inverse_of value' do
1207
+ expect(association.inverses(instance_of_other_class)).to eq([ :inverse_name ])
1208
+ end
1209
+ end
1210
+
1211
+ context 'when inverse_of is not specified' do
1212
+
1213
+ it 'returns the list of relations whose :as attribute matches the name of this association' do
1214
+ expect(association.inverses(instance_of_other_class)).to match_array([ :belonging_object ])
1215
+ end
1216
+ end
1217
+ end
1218
+
1219
+ context 'when the relation class has more than one relation whose class matches the owning class' do
1220
+
1221
+ before do
1222
+ OwnerObject.has_one :other_belonging_object, as: :containable, class_name: 'BelongingObject'
1223
+ OwnerObject.has_one :belonging_object, as: :containable
1224
+ end
1225
+
1226
+ context 'when :inverse_of is specified' do
1227
+
1228
+ before do
1229
+ options.merge!(inverse_of: :inverse_name)
1230
+ end
1231
+
1232
+ it 'returns the :inverse_of value' do
1233
+ expect(association.inverses(instance_of_other_class)).to eq([ :inverse_name ])
1234
+ end
1235
+ end
1236
+
1237
+ context 'when inverse_of is not specified' do
1238
+
1239
+ it 'returns the list of relations whose :as attribute matches the name of this association' do
1240
+ expect(association.inverses(instance_of_other_class)).to match_array([ :other_belonging_object,
1241
+ :belonging_object ])
1242
+ end
1243
+
1244
+ context 'when the relation class has two associations with the same name' do
1245
+
1246
+ before do
1247
+ OwnerObject.has_one :belonging_object, as: :containable
1248
+ OwnerObject.has_one :other_belonging_object, as: :containable
1249
+ end
1250
+
1251
+ it 'returns only the relations whose :as attribute and class match' do
1252
+ expect(association.inverses(instance_of_other_class)).to match_array([ :belonging_object ])
1253
+ end
1254
+ end
1255
+ end
1256
+ end
1257
+ end
1258
+
1259
+ context 'when another object is not passed to the method' do
1260
+
1261
+ context 'when inverse_of is specified' do
1262
+
1263
+ before do
1264
+ options.merge!(inverse_of: :inverse_name)
1265
+ end
1266
+
1267
+ it 'returns the :inverse_of value' do
1268
+ expect(association.inverses).to eq([ :inverse_name ])
1269
+ end
1270
+ end
1271
+
1272
+ context 'when inverse_of is not specified' do
1273
+
1274
+ it 'returns nil' do
1275
+ expect(association.inverses).to eq(nil)
1276
+ end
1277
+ end
1278
+ end
1279
+ end
1280
+
1281
+ context 'when not polymorphic' do
1282
+
1283
+ context 'when inverse_of is specified' do
1284
+
1285
+ before do
1286
+ options.merge!(inverse_of: :inverse_name)
1287
+ end
1288
+
1289
+ it 'returns the :inverse_of value' do
1290
+ expect(association.inverses).to eq([ :inverse_name ])
1291
+ end
1292
+ end
1293
+
1294
+ context 'when inverse_of is not specified' do
1295
+
1296
+ before do
1297
+ OwnerObject.has_many :belonging_objects
1298
+ end
1299
+
1300
+ it 'uses the inverse class to find the inverse name' do
1301
+ expect(association.inverses).to eq([ :belonging_objects ])
1302
+ end
1303
+ end
1304
+
1305
+ context 'when :cyclic is specified' do
1306
+
1307
+ it 'returns the cyclic inverse name' do
1308
+
1309
+ end
1310
+ end
1311
+
1312
+ context 'when the inverse class has more than one relation with objects of the owner class' do
1313
+
1314
+ before do
1315
+ OwnerObject.has_many :belonging_objects
1316
+ OwnerObject.has_one :other_belonging_object, class_name: 'BelongingObject'
1317
+ end
1318
+
1319
+ it 'raises a Mongoid::Errors::AmbiguousRelationship exception' do
1320
+ expect {
1321
+ association.inverses
1322
+ }.to raise_exception(Mongoid::Errors::AmbiguousRelationship)
1323
+ end
1324
+ end
1325
+
1326
+ context 'when the inverse class only has one relation with objects of the owner class' do
1327
+
1328
+ before do
1329
+ OwnerObject.has_many :belonging_objects
1330
+ end
1331
+
1332
+ it 'uses the inverse class to find the inverse name' do
1333
+ expect(association.inverses).to eq([ :belonging_objects ])
1334
+ end
1335
+ end
1336
+ end
1337
+ end
1338
+
1339
+ describe '#inverse' do
1340
+
1341
+ context 'when polymorphic' do
1342
+
1343
+ let(:options) do
1344
+ {
1345
+ polymorphic: true
1346
+ }
1347
+ end
1348
+
1349
+ let(:name) do
1350
+ :containable
1351
+ end
1352
+
1353
+ context 'when another object is passed to the method' do
1354
+
1355
+ let(:instance_of_other_class) do
1356
+ OwnerObject.new
1357
+ end
1358
+
1359
+ context 'when the relation class has only one relation whose class matches the owning class' do
1360
+
1361
+ before do
1362
+ OwnerObject.has_many :belonging_objects, as: :containable
1363
+ end
1364
+
1365
+ context 'when :inverse_of is specified' do
1366
+
1367
+ before do
1368
+ options.merge!(inverse_of: :inverse_name)
1369
+ end
1370
+
1371
+ it 'returns the :inverse_of value' do
1372
+ expect(association.inverse(instance_of_other_class)).to eq(:inverse_name)
1373
+ end
1374
+ end
1375
+
1376
+ context 'when inverse_of is not specified' do
1377
+
1378
+ it 'returns the list of relations whose :as attribute matches the name of this association' do
1379
+ expect(association.inverse(instance_of_other_class)).to eq(:belonging_objects)
1380
+ end
1381
+ end
1382
+ end
1383
+
1384
+ context 'when the relation class has more than one relation whose class matches the owning class' do
1385
+
1386
+ before do
1387
+ OwnerObject.has_one :other_belonging_object, as: :containable, class_name: 'BelongingObject'
1388
+ OwnerObject.has_one :belonging_object, as: :containable
1389
+ end
1390
+
1391
+ context 'when :inverse_of is specified' do
1392
+
1393
+ before do
1394
+ options.merge!(inverse_of: :inverse_name)
1395
+ end
1396
+
1397
+ it 'returns the :inverse_of value' do
1398
+ expect(association.inverse(instance_of_other_class)).to eq(:inverse_name)
1399
+ end
1400
+ end
1401
+
1402
+ context 'when inverse_of is not specified' do
1403
+
1404
+ it 'returns the first candidate whose :as attribute matches the name of this association' do
1405
+ expect(association.inverse(instance_of_other_class)).to eq(:other_belonging_object)
1406
+ end
1407
+ end
1408
+ end
1409
+ end
1410
+
1411
+ context 'when another object is not passed to the method' do
1412
+
1413
+ context 'when inverse_of is specified' do
1414
+
1415
+ before do
1416
+ options.merge!(inverse_of: :inverse_name)
1417
+ end
1418
+
1419
+ it 'returns the :inverse_of value' do
1420
+ expect(association.inverse).to eq(:inverse_name)
1421
+ end
1422
+ end
1423
+
1424
+ context 'when inverse_of is not specified' do
1425
+
1426
+ it 'returns nil' do
1427
+ expect(association.inverse).to eq(nil)
1428
+ end
1429
+ end
1430
+ end
1431
+ end
1432
+
1433
+ context 'when not polymorphic' do
1434
+
1435
+ context 'when inverse_of is specified' do
1436
+
1437
+ before do
1438
+ options.merge!(inverse_of: :inverse_name)
1439
+ end
1440
+
1441
+ it 'returns the :inverse_of value' do
1442
+ expect(association.inverse).to eq(:inverse_name)
1443
+ end
1444
+ end
1445
+
1446
+ context 'when inverse_of is not specified' do
1447
+
1448
+ before do
1449
+ OwnerObject.has_many :belonging_objects
1450
+ end
1451
+
1452
+ it 'uses the inverse class to find the inverse name' do
1453
+ expect(association.inverse).to eq(:belonging_objects)
1454
+ end
1455
+ end
1456
+
1457
+ context 'when :cyclic is specified' do
1458
+
1459
+ it 'returns the cyclic inverse name' do
1460
+
1461
+ end
1462
+ end
1463
+
1464
+ context 'when the inverse class has more than one relation with objects of the owner class' do
1465
+
1466
+ before do
1467
+ OwnerObject.has_many :belonging_objects
1468
+ OwnerObject.has_many :other_belonging_objects, class_name: 'BelongingObject'
1469
+ end
1470
+
1471
+ it 'raises a Mongoid::Errors::AmbiguousRelationship exception' do
1472
+ expect {
1473
+ association.inverse
1474
+ }.to raise_exception(Mongoid::Errors::AmbiguousRelationship)
1475
+ end
1476
+ end
1477
+
1478
+ context 'when the inverse class only has one relation with objects of the owner class' do
1479
+
1480
+ before do
1481
+ OwnerObject.has_many :belonging_objects
1482
+ end
1483
+
1484
+ it 'uses the inverse class to find the inverse name' do
1485
+ expect(association.inverse).to eq(:belonging_objects)
1486
+ end
1487
+ end
1488
+ end
1489
+ end
1490
+
1491
+ describe '#inverse_association' do
1492
+
1493
+ end
1494
+
1495
+ describe '#autosave' do
1496
+
1497
+ context 'when the :autosave option is specified' do
1498
+
1499
+ context 'when the :autosave option is true' do
1500
+
1501
+ let(:options) do
1502
+ {
1503
+ autosave: true
1504
+ }
1505
+ end
1506
+
1507
+ it 'returns true' do
1508
+ expect(association.autosave).to be(true)
1509
+ end
1510
+ end
1511
+
1512
+ context 'when the :autosave option is false' do
1513
+
1514
+ let(:options) do
1515
+ {
1516
+ autosave: false
1517
+ }
1518
+ end
1519
+
1520
+ it 'returns false' do
1521
+ expect(association.autosave).to be(false)
1522
+ end
1523
+ end
1524
+ end
1525
+
1526
+ context 'when the :autosave option is not specified' do
1527
+
1528
+ it 'returns nil' do
1529
+ expect(association.autosave).to be(false)
1530
+ end
1531
+ end
1532
+ end
1533
+
1534
+ describe '#counter_cached?' do
1535
+
1536
+ context 'when the :counter_cache option is true' do
1537
+
1538
+ let(:options) do
1539
+ {
1540
+ counter_cache: true
1541
+ }
1542
+ end
1543
+
1544
+ it 'returns true' do
1545
+ expect(association.counter_cached?).to be(true)
1546
+ end
1547
+ end
1548
+
1549
+ context 'when the :counter_cache option is a String' do
1550
+
1551
+ let(:options) do
1552
+ {
1553
+ counter_cache: 'counts_field'
1554
+ }
1555
+ end
1556
+
1557
+ it 'returns true' do
1558
+ expect(association.counter_cached?).to be(true)
1559
+ end
1560
+ end
1561
+
1562
+ context 'when the :counter_cache option is false' do
1563
+
1564
+ let(:options) do
1565
+ {
1566
+ counter_cache: false
1567
+ }
1568
+ end
1569
+
1570
+ it 'returns false' do
1571
+ expect(association.counter_cached?).to be(false)
1572
+ end
1573
+ end
1574
+
1575
+ context 'when the :counter_cache option is not provided' do
1576
+
1577
+ it 'returns false' do
1578
+ expect(association.counter_cached?).to be(false)
1579
+ end
1580
+ end
1581
+ end
1582
+
1583
+ describe '#counter_cache_column_name' do
1584
+
1585
+ context 'when the :counter_cache option is true' do
1586
+
1587
+ let(:options) do
1588
+ {
1589
+ counter_cache: true
1590
+ }
1591
+ end
1592
+
1593
+ it 'returns the inverse name followed by "_count"' do
1594
+ expect(association.counter_cache_column_name).to eq('belonging_objects_count')
1595
+ end
1596
+ end
1597
+
1598
+ context 'when the :counter_cache option is a String' do
1599
+
1600
+ let(:options) do
1601
+ {
1602
+ counter_cache: 'counts_field'
1603
+ }
1604
+ end
1605
+
1606
+ it 'returns the String' do
1607
+ expect(association.counter_cache_column_name).to eq('counts_field')
1608
+ end
1609
+ end
1610
+ end
1611
+
1612
+ describe '#relation_class_name' do
1613
+
1614
+ context 'when the :class_name option is specified' do
1615
+
1616
+ let(:options) do
1617
+ { class_name: 'OtherOwnerObject' }
1618
+ end
1619
+
1620
+ it 'returns the class name option' do
1621
+ expect(association.relation_class_name).to eq('OtherOwnerObject')
1622
+ end
1623
+ end
1624
+
1625
+ context 'when the :class_name option is scoped with ::' do
1626
+
1627
+ let(:options) do
1628
+ { class_name: '::OtherOwnerObject' }
1629
+ end
1630
+
1631
+ it 'returns the class name option' do
1632
+ expect(association.relation_class_name).to eq('::OtherOwnerObject')
1633
+ end
1634
+ end
1635
+
1636
+ context 'when the class_name option is not specified' do
1637
+
1638
+ it 'uses the name of the relation to deduce the class name' do
1639
+ expect(association.relation_class_name).to eq('OwnerObject')
1640
+ end
1641
+ end
1642
+
1643
+ context 'when the association is polymorphic' do
1644
+ let(:association) do
1645
+ HomPolymorphicChild.relations['p_parent']
1646
+ end
1647
+
1648
+ it 'is the computed class name that does not match any existing class' do
1649
+ expect(association.relation_class_name).to eq('PParent')
1650
+ end
1651
+ end
1652
+ end
1653
+
1654
+ describe '#relation_class' do
1655
+
1656
+ context 'when the :class_name option is specified' do
1657
+
1658
+ let(:options) do
1659
+ { class_name: 'OtherOwnerObject' }
1660
+ end
1661
+
1662
+ it 'returns the named class' do
1663
+ expect(association.relation_class).to eq(OtherOwnerObject)
1664
+ end
1665
+ end
1666
+
1667
+ context 'when the :class_name option is scoped with ::' do
1668
+
1669
+ let(:options) do
1670
+ { class_name: '::OtherOwnerObject' }
1671
+ end
1672
+
1673
+ it 'returns the named class' do
1674
+ expect(association.relation_class).to eq(OtherOwnerObject)
1675
+ end
1676
+ end
1677
+
1678
+ context 'when the class_name option is not specified' do
1679
+
1680
+ it 'uses the name of the relation to deduce the class name' do
1681
+ expect(association.relation_class).to eq(OwnerObject)
1682
+ end
1683
+ end
1684
+
1685
+ context 'when the association is polymorphic' do
1686
+ let(:association) do
1687
+ HomPolymorphicChild.relations['p_parent']
1688
+ end
1689
+
1690
+ it 'raises NameError' do
1691
+ expect do
1692
+ association.relation_class
1693
+ end.to raise_error(NameError, /uninitialized constant .*PParent/)
1694
+ end
1695
+ end
1696
+ end
1697
+
1698
+ describe '#inverse_class_name' do
1699
+
1700
+ it 'returns the name of the owner class' do
1701
+ expect(association.inverse_class_name).to eq(belonging_class.name)
1702
+ end
1703
+
1704
+ context 'polymorphic association' do
1705
+ let(:association) do
1706
+ belonging_class.belongs_to :poly_owner, polymorphic: true
1707
+ end
1708
+
1709
+ it 'returns the name of the owner class' do
1710
+ expect(association.inverse_class_name).to eq(belonging_class.name)
1711
+ end
1712
+ end
1713
+ end
1714
+
1715
+ describe '#inverse_class' do
1716
+
1717
+ it 'returns the owner class' do
1718
+ expect(association.inverse_class).to be(belonging_class)
1719
+ end
1720
+
1721
+ context 'polymorphic association' do
1722
+ let(:association) do
1723
+ belonging_class.belongs_to :poly_owner, polymorphic: true
1724
+ end
1725
+
1726
+ it 'returns the owner class' do
1727
+ expect(association.inverse_class).to be(belonging_class)
1728
+ end
1729
+ end
1730
+ end
1731
+
1732
+ describe '#inverse_of' do
1733
+
1734
+ context 'when :inverse_of is specified in the options' do
1735
+
1736
+ let(:options) do
1737
+ { inverse_of: :a_belonging_object }
1738
+ end
1739
+
1740
+ it 'returns the inverse_of value' do
1741
+ expect(association.inverse_of).to eq(options[:inverse_of])
1742
+ end
1743
+ end
1744
+
1745
+ context 'when :inverse_of is not specified in the options' do
1746
+
1747
+ it 'returns nil' do
1748
+ expect(association.inverse_of).to be_nil
1749
+ end
1750
+ end
1751
+ end
1752
+
1753
+ describe '#key' do
1754
+
1755
+ it 'returns the name of the foreign_key as a string' do
1756
+ expect(association.key).to eq(association.foreign_key.to_s)
1757
+ end
1758
+ end
1759
+
1760
+ describe '#setter' do
1761
+
1762
+ it 'returns a string of the name followed by =' do
1763
+ expect(association.setter).to eq("#{name}=")
1764
+ end
1765
+ end
1766
+
1767
+ describe '#validate?' do
1768
+
1769
+ context 'when :validate is specified in the options' do
1770
+
1771
+ context 'when validate is true' do
1772
+
1773
+ let(:options) do
1774
+ { validate: true }
1775
+ end
1776
+
1777
+ it 'returns true' do
1778
+ expect(association.send(:validate?)).to be(true)
1779
+ end
1780
+ end
1781
+
1782
+ context 'when validate is false' do
1783
+
1784
+ let(:options) do
1785
+ { validate: false }
1786
+ end
1787
+
1788
+ it 'returns false' do
1789
+ expect(association.send(:validate?)).to be(false)
1790
+ end
1791
+ end
1792
+ end
1793
+
1794
+ context 'when :validate is not specified in the options' do
1795
+
1796
+ it 'returns the validation_default' do
1797
+ expect(association.send(:validate?)).to eq(association.validation_default)
1798
+ end
1799
+ end
1800
+ end
1801
+
1802
+ describe '#autobuilding?' do
1803
+
1804
+ context 'when :autobuild is specified in the options' do
1805
+
1806
+ context 'when autobuild is true' do
1807
+
1808
+ let(:options) do
1809
+ { autobuild: true }
1810
+ end
1811
+
1812
+ it 'returns true' do
1813
+ expect(association.autobuilding?).to be(true)
1814
+ end
1815
+ end
1816
+
1817
+ context 'when autobuild is false' do
1818
+
1819
+ let(:options) do
1820
+ { autobuild: false }
1821
+ end
1822
+
1823
+ it 'returns true' do
1824
+ expect(association.autobuilding?).to be(false)
1825
+ end
1826
+ end
1827
+ end
1828
+
1829
+ context 'when :validate is not specified in the options' do
1830
+
1831
+ it 'returns false' do
1832
+ expect(association.autobuilding?).to be(false)
1833
+ end
1834
+ end
1835
+ end
1836
+
1837
+ describe '#forced_nil_inverse?' do
1838
+
1839
+ it 'returns false' do
1840
+ expect(association.forced_nil_inverse?).to be(false)
1841
+ end
1842
+ end
1843
+
1844
+ describe '#stores_foreign_key?' do
1845
+
1846
+ it 'returns true' do
1847
+ expect(association.stores_foreign_key?).to be(true)
1848
+ end
1849
+ end
1850
+
1851
+ describe '#inverse_setter' do
1852
+
1853
+ context 'when an inverse can be determined' do
1854
+
1855
+ before do
1856
+ OwnerObject.has_many :belonging_objects
1857
+ end
1858
+
1859
+ it 'returns the name of the inverse followed by =' do
1860
+ expect(association.inverse_setter).to eq('belonging_objects=')
1861
+ end
1862
+ end
1863
+
1864
+ context 'when an inverse cannot be determined' do
1865
+
1866
+ it 'returns nil' do
1867
+ expect(association.inverse_setter).to be_nil
1868
+ end
1869
+ end
1870
+ end
1871
+
1872
+ describe '#extension' do
1873
+
1874
+ context 'when a block is passed' do
1875
+
1876
+ let(:association) do
1877
+ belonging_class.belongs_to name, options do; end
1878
+ end
1879
+
1880
+ it 'defines an extension module' do
1881
+ expect(association.extension).to be_a(Module)
1882
+ end
1883
+
1884
+ it 'returns the extension' do
1885
+ expect(association.extension).to eq(
1886
+ "#{belonging_class.name}::#{belonging_class.name}#{name.to_s.camelize}RelationExtension".constantize)
1887
+ end
1888
+ end
1889
+
1890
+ context 'when an :extension is not specified in the options' do
1891
+
1892
+ it 'returns false' do
1893
+ expect(association.extension).to be_nil
1894
+ end
1895
+ end
1896
+ end
1897
+
1898
+ describe '#foreign_key_setter' do
1899
+
1900
+ it 'returns the foriegn key field followed by "="' do
1901
+ expect(association.foreign_key_setter).to eq("owner_object_id=")
1902
+ end
1903
+ end
1904
+
1905
+ describe '#destructive?' do
1906
+
1907
+ context 'when the dependent option is provided' do
1908
+
1909
+ context 'when the dependent option is :delete_all' do
1910
+
1911
+ let(:options) do
1912
+ {
1913
+ dependent: :delete_all
1914
+ }
1915
+ end
1916
+
1917
+ it 'returns true' do
1918
+ expect(association.destructive?).to be(true)
1919
+ end
1920
+ end
1921
+
1922
+ context 'when the dependent option is :destroy' do
1923
+
1924
+ let(:options) do
1925
+ {
1926
+ dependent: :destroy
1927
+ }
1928
+ end
1929
+
1930
+ it 'returns true' do
1931
+ expect(association.destructive?).to be(true)
1932
+ end
1933
+ end
1934
+
1935
+ context 'when the dependent option is :nullify' do
1936
+
1937
+ let(:options) do
1938
+ {
1939
+ dependent: :nullify
1940
+ }
1941
+ end
1942
+
1943
+ it 'returns false' do
1944
+ expect(association.destructive?).to be(false)
1945
+ end
1946
+ end
1947
+
1948
+ context 'when the dependent option is :restrict_with_exception' do
1949
+
1950
+ let(:options) do
1951
+ {
1952
+ dependent: :restrict_with_exception
1953
+ }
1954
+ end
1955
+
1956
+ it 'returns false' do
1957
+ expect(association.destructive?).to be(false)
1958
+ end
1959
+ end
1960
+
1961
+ context 'when the dependent option is :restrict_with_error' do
1962
+
1963
+ let(:options) do
1964
+ {
1965
+ dependent: :restrict_with_error
1966
+ }
1967
+ end
1968
+
1969
+ it 'returns false' do
1970
+ expect(association.destructive?).to be(false)
1971
+ end
1972
+ end
1973
+ end
1974
+
1975
+ context 'when the dependent option is not provided' do
1976
+
1977
+ it 'returns false' do
1978
+ expect(association.destructive?).to be(false)
1979
+ end
1980
+ end
1981
+ end
1982
+
1983
+ describe '#nested_builder' do
1984
+
1985
+ it 'returns an instance of Association::Nested::One' do
1986
+ expect(association.nested_builder({}, {})).to be_a(Mongoid::Association::Nested::One)
1987
+ end
1988
+ end
1989
+
1990
+ describe '#path' do
1991
+
1992
+ it 'returns an instance of Mongoid::Atomic::Paths::Root' do
1993
+ expect(association.path({})).to be_a(Mongoid::Atomic::Paths::Root)
1994
+ end
1995
+ end
1996
+
1997
+ describe '#foreign_key_check' do
1998
+
1999
+ it 'returns the foreign_key followed by "_changed?"' do
2000
+ expect(association.foreign_key_check).to eq('owner_object_id_changed?')
2001
+ end
2002
+ end
2003
+
2004
+ describe '#create_relation' do
2005
+
2006
+ let(:owner) do
2007
+ BelongingObject.new
2008
+ end
2009
+
2010
+ let(:target) do
2011
+ OwnerObject.new
2012
+ end
2013
+
2014
+ before do
2015
+ OwnerObject.has_one :belonging_object
2016
+ end
2017
+
2018
+ it 'returns an instance of Mongoid::Association::Referenced::BelongsTo::Proxy' do
2019
+ expect(Mongoid::Association::Referenced::BelongsTo::Proxy).to receive(:new).and_call_original
2020
+ expect(association.create_relation(owner, target)).to be_a(OwnerObject)
2021
+ end
2022
+ end
2023
+ end