mongoid 7.4.0 → 8.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (315) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/lib/config/locales/en.yml +51 -28
  5. data/lib/mongoid/association/accessors.rb +32 -3
  6. data/lib/mongoid/association/bindable.rb +48 -0
  7. data/lib/mongoid/association/builders.rb +4 -2
  8. data/lib/mongoid/association/eager_loadable.rb +29 -7
  9. data/lib/mongoid/association/embedded/batchable.rb +48 -8
  10. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  11. data/lib/mongoid/association/embedded/embedded_in.rb +2 -1
  12. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  13. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  14. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +40 -18
  15. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  16. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +21 -2
  17. data/lib/mongoid/association/macros.rb +22 -1
  18. data/lib/mongoid/association/many.rb +5 -0
  19. data/lib/mongoid/association/nested/many.rb +2 -1
  20. data/lib/mongoid/association/proxy.rb +12 -0
  21. data/lib/mongoid/association/referenced/auto_save.rb +3 -2
  22. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  23. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  24. data/lib/mongoid/association/referenced/belongs_to.rb +1 -1
  25. data/lib/mongoid/association/referenced/counter_cache.rb +8 -8
  26. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +64 -11
  27. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +4 -1
  28. data/lib/mongoid/association/referenced/has_many/enumerable.rb +10 -14
  29. data/lib/mongoid/association/referenced/has_many/proxy.rb +12 -9
  30. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  31. data/lib/mongoid/association/referenced/has_one/proxy.rb +8 -11
  32. data/lib/mongoid/association/referenced/syncable.rb +2 -2
  33. data/lib/mongoid/association/relatable.rb +38 -4
  34. data/lib/mongoid/atomic/paths/embedded/many.rb +19 -0
  35. data/lib/mongoid/attributes/processing.rb +9 -2
  36. data/lib/mongoid/attributes.rb +30 -27
  37. data/lib/mongoid/changeable.rb +37 -2
  38. data/lib/mongoid/clients/options.rb +4 -0
  39. data/lib/mongoid/clients/sessions.rb +2 -14
  40. data/lib/mongoid/config/environment.rb +20 -4
  41. data/lib/mongoid/config.rb +25 -10
  42. data/lib/mongoid/contextual/aggregable/memory.rb +23 -15
  43. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  44. data/lib/mongoid/contextual/map_reduce.rb +2 -2
  45. data/lib/mongoid/contextual/memory.rb +176 -17
  46. data/lib/mongoid/contextual/mongo.rb +226 -206
  47. data/lib/mongoid/contextual/none.rb +66 -4
  48. data/lib/mongoid/copyable.rb +32 -8
  49. data/lib/mongoid/criteria/includable.rb +24 -20
  50. data/lib/mongoid/criteria/marshalable.rb +10 -2
  51. data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -13
  52. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +25 -4
  53. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  54. data/lib/mongoid/criteria/queryable/extensions/date.rb +6 -1
  55. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +6 -1
  56. data/lib/mongoid/criteria/queryable/extensions/hash.rb +0 -14
  57. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +1 -1
  58. data/lib/mongoid/criteria/queryable/extensions/object.rb +2 -1
  59. data/lib/mongoid/criteria/queryable/extensions/range.rb +13 -5
  60. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +1 -1
  61. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +3 -1
  62. data/lib/mongoid/criteria/queryable/extensions/time.rb +6 -1
  63. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +6 -1
  64. data/lib/mongoid/criteria/queryable/mergeable.rb +21 -0
  65. data/lib/mongoid/criteria/queryable/optional.rb +3 -9
  66. data/lib/mongoid/criteria/queryable/options.rb +1 -1
  67. data/lib/mongoid/criteria/queryable/selectable.rb +28 -34
  68. data/lib/mongoid/criteria/queryable/selector.rb +89 -4
  69. data/lib/mongoid/criteria/queryable/smash.rb +39 -6
  70. data/lib/mongoid/criteria/queryable.rb +11 -6
  71. data/lib/mongoid/criteria.rb +1 -26
  72. data/lib/mongoid/deprecable.rb +36 -0
  73. data/lib/mongoid/deprecation.rb +25 -0
  74. data/lib/mongoid/document.rb +96 -32
  75. data/lib/mongoid/errors/document_not_found.rb +29 -8
  76. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  77. data/lib/mongoid/errors/invalid_field.rb +5 -1
  78. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  79. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  80. data/lib/mongoid/errors.rb +2 -2
  81. data/lib/mongoid/extensions/array.rb +8 -6
  82. data/lib/mongoid/extensions/big_decimal.rb +29 -10
  83. data/lib/mongoid/extensions/binary.rb +42 -0
  84. data/lib/mongoid/extensions/boolean.rb +8 -2
  85. data/lib/mongoid/extensions/date.rb +26 -20
  86. data/lib/mongoid/extensions/date_time.rb +1 -1
  87. data/lib/mongoid/extensions/float.rb +4 -5
  88. data/lib/mongoid/extensions/hash.rb +12 -5
  89. data/lib/mongoid/extensions/integer.rb +4 -5
  90. data/lib/mongoid/extensions/object.rb +2 -0
  91. data/lib/mongoid/extensions/range.rb +41 -10
  92. data/lib/mongoid/extensions/regexp.rb +11 -4
  93. data/lib/mongoid/extensions/set.rb +11 -4
  94. data/lib/mongoid/extensions/string.rb +2 -13
  95. data/lib/mongoid/extensions/symbol.rb +3 -14
  96. data/lib/mongoid/extensions/time.rb +27 -16
  97. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  98. data/lib/mongoid/extensions.rb +1 -0
  99. data/lib/mongoid/factory.rb +42 -7
  100. data/lib/mongoid/fields/foreign_key.rb +7 -0
  101. data/lib/mongoid/fields/validators/macro.rb +3 -9
  102. data/lib/mongoid/fields.rb +194 -28
  103. data/lib/mongoid/findable.rb +27 -7
  104. data/lib/mongoid/indexable/specification.rb +1 -1
  105. data/lib/mongoid/indexable/validators/options.rb +4 -1
  106. data/lib/mongoid/interceptable.rb +69 -9
  107. data/lib/mongoid/persistable/creatable.rb +14 -5
  108. data/lib/mongoid/persistable/updatable.rb +12 -5
  109. data/lib/mongoid/persistable/upsertable.rb +1 -1
  110. data/lib/mongoid/persistence_context.rb +19 -2
  111. data/lib/mongoid/query_cache.rb +6 -258
  112. data/lib/mongoid/railties/controller_runtime.rb +1 -1
  113. data/lib/mongoid/reloadable.rb +7 -3
  114. data/lib/mongoid/selectable.rb +1 -2
  115. data/lib/mongoid/stateful.rb +27 -1
  116. data/lib/mongoid/timestamps/created.rb +1 -1
  117. data/lib/mongoid/timestamps/updated.rb +1 -1
  118. data/lib/mongoid/touchable.rb +2 -3
  119. data/lib/mongoid/traversable.rb +5 -1
  120. data/lib/mongoid/validatable/uniqueness.rb +2 -1
  121. data/lib/mongoid/version.rb +1 -1
  122. data/lib/mongoid/warnings.rb +28 -0
  123. data/lib/mongoid.rb +2 -0
  124. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +11 -5
  125. data/spec/config/mongoid.yml +16 -0
  126. data/spec/config/mongoid_with_schema_map_uuid.yml +27 -0
  127. data/spec/integration/app_spec.rb +28 -26
  128. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  129. data/spec/integration/associations/embedded_dirty_spec.rb +28 -0
  130. data/spec/integration/associations/embedded_spec.rb +15 -0
  131. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  132. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  133. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  134. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  135. data/spec/integration/associations/has_one_spec.rb +97 -1
  136. data/spec/integration/associations/scope_option_spec.rb +1 -1
  137. data/spec/integration/callbacks_models.rb +95 -1
  138. data/spec/integration/callbacks_spec.rb +226 -4
  139. data/spec/integration/criteria/range_spec.rb +95 -1
  140. data/spec/integration/discriminator_key_spec.rb +115 -76
  141. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  142. data/spec/integration/matcher_examples_spec.rb +20 -13
  143. data/spec/integration/matcher_operator_data/type_decimal.yml +3 -2
  144. data/spec/integration/matcher_operator_spec.rb +3 -5
  145. data/spec/integration/persistence/range_field_spec.rb +350 -0
  146. data/spec/lite_spec_helper.rb +1 -1
  147. data/spec/mongoid/association/counter_cache_spec.rb +1 -1
  148. data/spec/mongoid/association/depending_spec.rb +9 -9
  149. data/spec/mongoid/association/eager_spec.rb +2 -1
  150. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  151. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  152. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  153. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  154. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +219 -8
  155. data/spec/mongoid/association/embedded/embeds_many_models.rb +157 -0
  156. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  157. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  158. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  159. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  160. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  161. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  162. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  163. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  164. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  165. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  166. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +67 -4
  167. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  168. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  169. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  170. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +8 -8
  171. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +82 -13
  172. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  173. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  174. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  175. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  176. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  177. data/spec/mongoid/association/syncable_spec.rb +14 -0
  178. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  179. data/spec/mongoid/atomic_spec.rb +22 -0
  180. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  181. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  182. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  183. data/spec/mongoid/attributes_spec.rb +524 -27
  184. data/spec/mongoid/changeable_spec.rb +130 -13
  185. data/spec/mongoid/clients/factory_spec.rb +34 -42
  186. data/spec/mongoid/clients/options_spec.rb +1 -0
  187. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  188. data/spec/mongoid/clients_spec.rb +32 -2
  189. data/spec/mongoid/config/environment_spec.rb +39 -1
  190. data/spec/mongoid/config_spec.rb +104 -13
  191. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  192. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  193. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  194. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  195. data/spec/mongoid/contextual/memory_spec.rb +1337 -69
  196. data/spec/mongoid/contextual/mongo_spec.rb +1105 -172
  197. data/spec/mongoid/contextual/none_spec.rb +38 -0
  198. data/spec/mongoid/copyable_spec.rb +451 -1
  199. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  200. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  201. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  202. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  203. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  204. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  205. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  206. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  207. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  208. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  209. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  210. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  211. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  212. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  213. data/spec/mongoid/criteria/queryable/selectable_spec.rb +289 -124
  214. data/spec/mongoid/criteria/queryable/selector_spec.rb +14 -2
  215. data/spec/mongoid/criteria_spec.rb +474 -1198
  216. data/spec/mongoid/document_fields_spec.rb +173 -24
  217. data/spec/mongoid/document_spec.rb +32 -41
  218. data/spec/mongoid/errors/document_not_found_spec.rb +76 -0
  219. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  220. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  221. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  222. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  223. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  224. data/spec/mongoid/extensions/array_spec.rb +16 -2
  225. data/spec/mongoid/extensions/big_decimal_spec.rb +697 -212
  226. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  227. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  228. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  229. data/spec/mongoid/extensions/date_spec.rb +71 -1
  230. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  231. data/spec/mongoid/extensions/float_spec.rb +48 -76
  232. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  233. data/spec/mongoid/extensions/integer_spec.rb +45 -66
  234. data/spec/mongoid/extensions/range_spec.rb +255 -54
  235. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  236. data/spec/mongoid/extensions/set_spec.rb +106 -0
  237. data/spec/mongoid/extensions/string_spec.rb +53 -25
  238. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  239. data/spec/mongoid/extensions/time_spec.rb +634 -66
  240. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  241. data/spec/mongoid/factory_spec.rb +61 -1
  242. data/spec/mongoid/fields_spec.rb +321 -50
  243. data/spec/mongoid/findable_spec.rb +80 -15
  244. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  245. data/spec/mongoid/indexable_spec.rb +16 -19
  246. data/spec/mongoid/interceptable_spec.rb +584 -5
  247. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  248. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  249. data/spec/mongoid/mongoizable_spec.rb +285 -0
  250. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  251. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  252. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  253. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  254. data/spec/mongoid/persistence_context_spec.rb +50 -1
  255. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  256. data/spec/mongoid/query_cache_spec.rb +0 -154
  257. data/spec/mongoid/reloadable_spec.rb +35 -2
  258. data/spec/mongoid/scopable_spec.rb +21 -1
  259. data/spec/mongoid/shardable_spec.rb +14 -0
  260. data/spec/mongoid/stateful_spec.rb +28 -0
  261. data/spec/mongoid/timestamps_spec.rb +390 -0
  262. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  263. data/spec/mongoid/touchable_spec.rb +116 -0
  264. data/spec/mongoid/touchable_spec_models.rb +12 -8
  265. data/spec/mongoid/traversable_spec.rb +4 -11
  266. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  267. data/spec/mongoid/validatable/uniqueness_spec.rb +60 -31
  268. data/spec/mongoid/warnings_spec.rb +35 -0
  269. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  270. data/spec/rails/mongoid_spec.rb +4 -16
  271. data/spec/shared/lib/mrss/constraints.rb +8 -16
  272. data/spec/shared/lib/mrss/docker_runner.rb +23 -3
  273. data/spec/shared/lib/mrss/eg_config_utils.rb +51 -0
  274. data/spec/shared/lib/mrss/lite_constraints.rb +32 -1
  275. data/spec/shared/share/Dockerfile.erb +34 -48
  276. data/spec/shared/shlib/config.sh +27 -0
  277. data/spec/shared/shlib/server.sh +32 -19
  278. data/spec/shared/shlib/set_env.sh +37 -0
  279. data/spec/support/constraints.rb +24 -0
  280. data/spec/support/macros.rb +39 -0
  281. data/spec/support/models/augmentation.rb +12 -0
  282. data/spec/support/models/band.rb +3 -0
  283. data/spec/support/models/catalog.rb +24 -0
  284. data/spec/support/models/circus.rb +3 -0
  285. data/spec/support/models/code.rb +2 -0
  286. data/spec/support/models/fanatic.rb +8 -0
  287. data/spec/support/models/implant.rb +9 -0
  288. data/spec/support/models/label.rb +2 -0
  289. data/spec/support/models/membership.rb +1 -0
  290. data/spec/support/models/passport.rb +9 -0
  291. data/spec/support/models/person.rb +1 -0
  292. data/spec/support/models/player.rb +2 -0
  293. data/spec/support/models/powerup.rb +12 -0
  294. data/spec/support/models/registry.rb +1 -0
  295. data/spec/support/models/school.rb +14 -0
  296. data/spec/support/models/shield.rb +18 -0
  297. data/spec/support/models/student.rb +14 -0
  298. data/spec/support/models/weapon.rb +12 -0
  299. data/spec/support/schema_maps/schema_map_aws.json +17 -0
  300. data/spec/support/schema_maps/schema_map_aws_key_alt_names.json +12 -0
  301. data/spec/support/schema_maps/schema_map_azure.json +17 -0
  302. data/spec/support/schema_maps/schema_map_azure_key_alt_names.json +12 -0
  303. data/spec/support/schema_maps/schema_map_gcp.json +17 -0
  304. data/spec/support/schema_maps/schema_map_gcp_key_alt_names.json +12 -0
  305. data/spec/support/schema_maps/schema_map_kmip.json +17 -0
  306. data/spec/support/schema_maps/schema_map_kmip_key_alt_names.json +12 -0
  307. data/spec/support/schema_maps/schema_map_local.json +18 -0
  308. data/spec/support/schema_maps/schema_map_local_key_alt_names.json +12 -0
  309. data/spec/support/spec_config.rb +4 -0
  310. data.tar.gz.sig +0 -0
  311. metadata +76 -13
  312. metadata.gz.sig +0 -0
  313. data/lib/mongoid/errors/eager_load.rb +0 -23
  314. data/lib/mongoid/errors/invalid_value.rb +0 -17
  315. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
@@ -2239,10 +2239,8 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2239
2239
  Person.create!(username: 'durran')
2240
2240
  end
2241
2241
 
2242
- before do
2243
- person.posts.create!(title: "Testing")
2244
- person.posts.create!(title: "Test")
2245
- end
2242
+ let!(:post1) { person.posts.create!(title: "Testing") }
2243
+ let!(:post2) { person.posts.create!(title: "Test") }
2246
2244
 
2247
2245
  it "removes the correct posts" do
2248
2246
  person.posts.send(method, { title: "Testing" })
@@ -2258,6 +2256,11 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2258
2256
  it "returns the number of documents deleted" do
2259
2257
  expect(person.posts.send(method, { title: "Testing" })).to eq(1)
2260
2258
  end
2259
+
2260
+ it "sets the association locally" do
2261
+ person.posts.send(method, { title: "Testing" })
2262
+ expect(person.posts).to eq([post2])
2263
+ end
2261
2264
  end
2262
2265
 
2263
2266
  context "when conditions are not provided" do
@@ -2284,6 +2287,11 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2284
2287
  it "returns the number of documents deleted" do
2285
2288
  expect(person.posts.send(method)).to eq(2)
2286
2289
  end
2290
+
2291
+ it "sets the association locally" do
2292
+ person.posts.send(method)
2293
+ expect(person.posts).to eq([])
2294
+ end
2287
2295
  end
2288
2296
  end
2289
2297
 
@@ -2295,10 +2303,8 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2295
2303
  Movie.create!(title: "Bladerunner")
2296
2304
  end
2297
2305
 
2298
- before do
2299
- movie.ratings.create!(value: 1)
2300
- movie.ratings.create!(value: 2)
2301
- end
2306
+ let!(:rating1) { movie.ratings.create!(value: 1) }
2307
+ let!(:rating2) { movie.ratings.create!(value: 2) }
2302
2308
 
2303
2309
  it "removes the correct ratings" do
2304
2310
  movie.ratings.send(method, { value: 1 })
@@ -2313,6 +2319,11 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2313
2319
  it "returns the number of documents deleted" do
2314
2320
  expect(movie.ratings.send(method, { value: 1 })).to eq(1)
2315
2321
  end
2322
+
2323
+ it "sets the association locally" do
2324
+ movie.ratings.send(method, { value: 1 })
2325
+ expect(movie.ratings).to eq([rating2])
2326
+ end
2316
2327
  end
2317
2328
 
2318
2329
  context "when conditions are not provided" do
@@ -2339,6 +2350,11 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2339
2350
  it "returns the number of documents deleted" do
2340
2351
  expect(movie.ratings.send(method)).to eq(2)
2341
2352
  end
2353
+
2354
+ it "sets the association locally" do
2355
+ movie.ratings.send(method)
2356
+ expect(movie.ratings).to eq([])
2357
+ end
2342
2358
  end
2343
2359
  end
2344
2360
  end
@@ -2524,7 +2540,7 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2524
2540
  it "raises an error" do
2525
2541
  expect {
2526
2542
  person.posts.find(post.id)
2527
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2543
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Post with id\(s\)/)
2528
2544
  end
2529
2545
  end
2530
2546
 
@@ -2539,7 +2555,7 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2539
2555
  it "raises an error" do
2540
2556
  expect {
2541
2557
  person.posts.find(BSON::ObjectId.new)
2542
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2558
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Post with id\(s\)/)
2543
2559
  end
2544
2560
  end
2545
2561
 
@@ -2588,7 +2604,7 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2588
2604
  it "raises an error" do
2589
2605
  expect {
2590
2606
  person.posts.find([ BSON::ObjectId.new ])
2591
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2607
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Post with id\(s\)/)
2592
2608
  end
2593
2609
  end
2594
2610
 
@@ -2652,7 +2668,7 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2652
2668
  it "raises an error" do
2653
2669
  expect {
2654
2670
  movie.ratings.find(BSON::ObjectId.new)
2655
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2671
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Rating with id\(s\)/)
2656
2672
  end
2657
2673
  end
2658
2674
 
@@ -2709,7 +2725,7 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
2709
2725
  it "raises an error" do
2710
2726
  expect {
2711
2727
  movie.ratings.find([ BSON::ObjectId.new ])
2712
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2728
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Rating with id\(s\)/)
2713
2729
  end
2714
2730
  end
2715
2731
 
@@ -4089,4 +4105,57 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
4089
4105
  expect(band.same_name).to eq([agent])
4090
4106
  end
4091
4107
  end
4108
+
4109
+ context "when removing a document with counter_cache on" do
4110
+ let(:post) { Post.create! }
4111
+ let(:person1) { Person.create! }
4112
+ let(:person2) { Person.create! }
4113
+
4114
+ before do
4115
+ post.update_attribute(:person, person1)
4116
+ expect(person1.posts_count).to eq 1
4117
+
4118
+ person2
4119
+ post.update_attribute(:person, person2)
4120
+ person1.reload
4121
+ expect(person1.posts_count).to eq 0
4122
+ expect(person2.posts_count).to eq 1
4123
+
4124
+ post.update_attribute(:person, nil)
4125
+ person1.reload
4126
+ person2.reload
4127
+ end
4128
+
4129
+ it "the count field is updated" do
4130
+ expect(person2.posts_count).to eq 0
4131
+ end
4132
+ end
4133
+
4134
+ context "when there is a foreign key in the aliased associations" do
4135
+ it "has the correct aliases" do
4136
+ expect(Band.aliased_associations["artist_ids"]).to eq("artists")
4137
+ expect(Artist.aliased_associations.key?("band_id")).to be false
4138
+ expect(Artist.aliased_fields["band"]).to eq("band_id")
4139
+ end
4140
+ end
4141
+
4142
+ context "when executing concat on foreign key array from the db" do
4143
+ config_override :legacy_attributes, false
4144
+
4145
+ before do
4146
+ Agent.create!
4147
+ Basic.create!
4148
+ end
4149
+
4150
+ let!(:agent) { Agent.first }
4151
+ let!(:basic) { Basic.first }
4152
+
4153
+ before do
4154
+ agent.basic_ids.concat([basic.id])
4155
+ end
4156
+
4157
+ it "works on the first attempt" do
4158
+ expect(agent.basic_ids).to eq([basic.id])
4159
+ end
4160
+ end
4092
4161
  end
@@ -42,6 +42,7 @@ end
42
42
 
43
43
  class HmmSchool
44
44
  include Mongoid::Document
45
+ include Mongoid::Timestamps
45
46
 
46
47
  has_many :students, class_name: 'HmmStudent'
47
48
 
@@ -51,8 +52,9 @@ end
51
52
 
52
53
  class HmmStudent
53
54
  include Mongoid::Document
55
+ include Mongoid::Timestamps
54
56
 
55
- belongs_to :school, class_name: 'HmmSchool'
57
+ belongs_to :school, class_name: 'HmmSchool', touch: true
56
58
 
57
59
  field :name, type: String
58
60
  field :grade, type: Integer, default: 3
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
+ require_relative './has_many_models'
4
5
 
5
6
  describe Mongoid::Association::Referenced::HasMany do
6
7
 
@@ -1245,4 +1246,28 @@ describe Mongoid::Association::Referenced::HasMany do
1245
1246
  expect(association.create_relation(owner, target)).to be_a(Array)
1246
1247
  end
1247
1248
  end
1249
+
1250
+ context "when adding an object to the association" do
1251
+ let!(:start_time) { Timecop.freeze(Time.at(Time.now.to_i)) }
1252
+
1253
+ let(:update_time) do
1254
+ Timecop.freeze(Time.at(Time.now.to_i) + 2)
1255
+ end
1256
+
1257
+ after do
1258
+ Timecop.return
1259
+ end
1260
+
1261
+ let!(:school) { HmmSchool.create! }
1262
+ let!(:student) { HmmStudent.create! }
1263
+
1264
+ before do
1265
+ update_time
1266
+ student.update(school: school)
1267
+ end
1268
+
1269
+ it "updates the updated_at" do
1270
+ expect(student.updated_at).to eq(update_time)
1271
+ end
1272
+ end
1248
1273
  end
@@ -91,7 +91,7 @@ describe Mongoid::Association::Referenced::HasOne::Buildable do
91
91
  expect(document).to eq(object)
92
92
  end
93
93
 
94
- context 'when the object is already related to another object' do
94
+ context 'when the object is already associated with another object' do
95
95
 
96
96
  let(:original_person) do
97
97
  Person.new
@@ -105,7 +105,7 @@ describe Mongoid::Association::Referenced::HasOne::Buildable do
105
105
  association.build(Person.new, object)
106
106
  end
107
107
 
108
- it 'clears the object of its previous relation' do
108
+ it 'clears the object of its previous association' do
109
109
  expect(original_person.account).to be_nil
110
110
  end
111
111
 
@@ -133,7 +133,7 @@ describe Mongoid::Association::Referenced::HasOne::Proxy do
133
133
  it "detaches the previous relation" do
134
134
  expect {
135
135
  game.reload
136
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
136
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Game with id\(s\)/)
137
137
  end
138
138
  end
139
139
  end
@@ -1139,4 +1139,110 @@ describe Mongoid::Association::Referenced::HasOne::Proxy do
1139
1139
  end
1140
1140
  end
1141
1141
  end
1142
+
1143
+ context "when there is a foreign key in the aliased associations" do
1144
+ it "has the correct aliases" do
1145
+ # Instances of Driver do not respond to vehicle_id.
1146
+ expect(Driver.aliased_associations.key?("vehicle_id")).to be false
1147
+ expect(Vehicle.aliased_associations.key?("driver_id")).to be false
1148
+ expect(Vehicle.aliased_fields["driver"]).to eq("driver_id")
1149
+ end
1150
+ end
1151
+
1152
+ context "when the document is not persisted and the association is invalid" do
1153
+
1154
+ before do
1155
+ class HomParent
1156
+ include Mongoid::Document
1157
+ has_one :child, class_name: "HomChild"
1158
+ field :name
1159
+ validates :name, presence: true
1160
+ end
1161
+
1162
+ class HomChild; include Mongoid::Document; end
1163
+
1164
+ belongs_to
1165
+ child.parent = parent
1166
+ child.save
1167
+ end
1168
+
1169
+ after do
1170
+ Object.send(:remove_const, :HomParent)
1171
+ Object.send(:remove_const, :HomChild)
1172
+ end
1173
+
1174
+ let(:belongs_to) do
1175
+ HomChild.belongs_to :parent, autosave: true, validate: false, optional: optional
1176
+ end
1177
+
1178
+ let(:child) { HomChild.new }
1179
+ let(:parent) { HomParent.new }
1180
+
1181
+
1182
+ context "when belongs_to_required_by_default is true" do
1183
+ config_override :belongs_to_required_by_default, true
1184
+
1185
+ context "when optional is true" do
1186
+ let(:optional) { true }
1187
+
1188
+ it "persists the child with the parent_id" do
1189
+ expect(HomChild.first.parent_id).to eq(parent._id)
1190
+ expect(HomParent.count).to eq(0)
1191
+ end
1192
+ end
1193
+
1194
+ context "when optional is false" do
1195
+ let(:optional) { false }
1196
+
1197
+ it "doesn't persist the parent or the child" do
1198
+ expect(HomChild.count).to eq(0)
1199
+ expect(HomParent.count).to eq(0)
1200
+ end
1201
+ end
1202
+
1203
+ context "when optional is not set" do
1204
+ let(:belongs_to) do
1205
+ HomChild.belongs_to :parent, autosave: true, validate: false
1206
+ end
1207
+
1208
+ it "doesn't persist the parent or the child" do
1209
+ expect(HomChild.count).to eq(0)
1210
+ expect(HomParent.count).to eq(0)
1211
+ end
1212
+ end
1213
+ end
1214
+
1215
+ context "when belongs_to_required_by_default is false" do
1216
+ config_override :belongs_to_required_by_default, false
1217
+
1218
+ context "when optional is true" do
1219
+ let(:optional) { true }
1220
+
1221
+ it "persists the child with the parent_id" do
1222
+ expect(HomChild.first.parent_id).to eq(parent._id)
1223
+ expect(HomParent.count).to eq(0)
1224
+ end
1225
+ end
1226
+
1227
+ context "when optional is false" do
1228
+ let(:optional) { false }
1229
+
1230
+ it "doesn't persist the parent or the child" do
1231
+ expect(HomChild.count).to eq(0)
1232
+ expect(HomParent.count).to eq(0)
1233
+ end
1234
+ end
1235
+
1236
+ context "when optional is not set" do
1237
+ let(:belongs_to) do
1238
+ HomChild.belongs_to :parent, autosave: true, validate: false
1239
+ end
1240
+
1241
+ it "persists the child with the parent_id" do
1242
+ expect(HomChild.first.parent_id).to eq(parent._id)
1243
+ expect(HomParent.count).to eq(0)
1244
+ end
1245
+ end
1246
+ end
1247
+ end
1142
1248
  end
@@ -95,3 +95,19 @@ class HomAnimal
95
95
 
96
96
  belongs_to :trainer, class_name: 'HomTrainer', scope: -> { where(name: 'Dave') }
97
97
  end
98
+
99
+ class HomPost
100
+ include Mongoid::Document
101
+
102
+ field :title, type: String
103
+
104
+ has_one :comment, inverse_of: :post, class_name: 'HomComment'
105
+ end
106
+
107
+ class HomComment
108
+ include Mongoid::Document
109
+
110
+ field :content, type: String
111
+
112
+ belongs_to :post, inverse_of: :comment, optional: true, class_name: 'HomPost'
113
+ end
@@ -496,4 +496,18 @@ describe "Syncable Association" do
496
496
  expect(dog.reload.breed_ids).to eq([ breed.id ])
497
497
  end
498
498
  end
499
+
500
+ context "when setting one document on unpersisted HABTM association" do
501
+ let!(:dog) { Dog.create! }
502
+ let!(:breed) { Breed.new }
503
+
504
+ before do
505
+ breed.dogs = Dog.all
506
+ breed.save!
507
+ end
508
+
509
+ it "sets the foreign key on the other side" do
510
+ expect(dog.reload.breed_ids).to eq([breed._id])
511
+ end
512
+ end
499
513
  end
@@ -329,7 +329,6 @@ describe Mongoid::Atomic::Paths do
329
329
  context "assignment after saving" do
330
330
 
331
331
  it "correctly sets the association for the embedded class" do
332
- pending 'MONGOID-5039'
333
332
 
334
333
  customer.home_address = CustomerAddress.new
335
334
  customer.work_address = CustomerAddress.new
@@ -346,19 +345,6 @@ describe Mongoid::Atomic::Paths do
346
345
  expect(customer.work_address.atomic_path).to eq("work_address")
347
346
  end
348
347
  end
349
-
350
- context "inverse assignment" do
351
-
352
- it "correctly returns the path for each embedded class" do
353
- pending 'MONGOID-5039'
354
-
355
- customer.work_address = CustomerAddress.new
356
- customer.work_address.addressable = customer
357
-
358
- expect(customer.home_address.atomic_path).to eq("home_address")
359
- expect(customer.work_address.atomic_path).to eq("work_address")
360
- end
361
- end
362
348
  end
363
349
  end
364
350
  end
@@ -386,5 +386,27 @@ describe Mongoid::Atomic do
386
386
  end
387
387
  end
388
388
  end
389
+
390
+ context "when adding embedded documents with nil ids" do
391
+ let(:account) { Account.create!(name: "acc") }
392
+
393
+ before do
394
+ account.memberships.build(id: nil, name: "m1")
395
+ account.memberships.build(id: nil, name: "m2")
396
+ end
397
+
398
+ it "has the correct updates" do
399
+ account.atomic_updates.should == {
400
+ "$push" => {
401
+ "memberships" => {
402
+ "$each" => [
403
+ { "_id" => nil, "name" => "m1" },
404
+ { "_id" => nil, "name" => "m2" }
405
+ ]
406
+ }
407
+ }
408
+ }
409
+ end
410
+ end
389
411
  end
390
412
  end
@@ -1,6 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
+ require_relative '../association/referenced/has_many_models'
5
+ require_relative '../association/referenced/has_and_belongs_to_many_models'
6
+ require_relative './nested_spec_models'
4
7
 
5
8
  describe Mongoid::Attributes::Nested do
6
9
 
@@ -1353,7 +1356,7 @@ describe Mongoid::Attributes::Nested do
1353
1356
  expect {
1354
1357
  person.addresses_attributes =
1355
1358
  { "foo" => { "id" => "test", "street" => "Test" } }
1356
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
1359
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Address with id\(s\)/)
1357
1360
  end
1358
1361
  end
1359
1362
  end
@@ -3012,7 +3015,7 @@ describe Mongoid::Attributes::Nested do
3012
3015
  { "0" =>
3013
3016
  { "id" => BSON::ObjectId.new.to_s, "title" => "Rogue" }
3014
3017
  }
3015
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
3018
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Post with id\(s\)/)
3016
3019
  end
3017
3020
  end
3018
3021
  end
@@ -3046,7 +3049,7 @@ describe Mongoid::Attributes::Nested do
3046
3049
  expect {
3047
3050
  person.posts_attributes =
3048
3051
  { "foo" => { "id" => "test", "title" => "Test" } }
3049
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
3052
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Post with id\(s\)/)
3050
3053
  end
3051
3054
  end
3052
3055
  end
@@ -3763,7 +3766,7 @@ describe Mongoid::Attributes::Nested do
3763
3766
  expect {
3764
3767
  person.preferences_attributes =
3765
3768
  { "foo" => { "id" => "test", "name" => "Test" } }
3766
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
3769
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
3767
3770
  end
3768
3771
  end
3769
3772
  end
@@ -4395,13 +4398,6 @@ describe Mongoid::Attributes::Nested do
4395
4398
 
4396
4399
  context "when nesting multiple levels and parent is timestamped" do
4397
4400
 
4398
- around do |example|
4399
- original_relations = Location.relations
4400
- Location.embedded_in :address, touch: true
4401
- example.run
4402
- Location.relations = original_relations
4403
- end
4404
-
4405
4401
  after do
4406
4402
  Address.reset_callbacks(:save)
4407
4403
  end
@@ -4928,4 +4924,77 @@ describe Mongoid::Attributes::Nested do
4928
4924
  end
4929
4925
  end
4930
4926
  end
4927
+
4928
+ context "when destroying has_many child using nested attributes" do
4929
+ let(:school) do
4930
+ School.create
4931
+ end
4932
+
4933
+ let!(:student) do
4934
+ school.students.create
4935
+ end
4936
+
4937
+ before do
4938
+ school.attributes = {
4939
+ '_id': school.id,
4940
+ 'students_attributes': [{
4941
+ '_id': student.id,
4942
+ '_destroy': 1
4943
+ }]
4944
+ }
4945
+ end
4946
+
4947
+ it "is able to access the parent in the after_destroy callback" do
4948
+ expect(school.after_destroy_triggered).to eq(true)
4949
+ end
4950
+ end
4951
+
4952
+ context "when destroying has_many child using nested attributes" do
4953
+ let(:school) do
4954
+ HabtmmSchool.create!(students: [student])
4955
+ end
4956
+
4957
+ let(:student) do
4958
+ HabtmmStudent.create!
4959
+ end
4960
+
4961
+ before do
4962
+ student.schools << school
4963
+ school.attributes = {
4964
+ '_id': school.id,
4965
+ 'students_attributes': [{
4966
+ '_id': student.id,
4967
+ '_destroy': 1
4968
+ }]
4969
+ }
4970
+ end
4971
+
4972
+ it "is able to access the parent in the after_destroy callback" do
4973
+ expect(school.reload.after_destroy_triggered).to eq(true)
4974
+ end
4975
+ end
4976
+
4977
+ context "when using a multi-leveled nested attribute on a referenced association" do
4978
+ let(:author) { NestedAuthor.create }
4979
+ let(:one_level_params) { { post_attributes: { title: 'test' } } }
4980
+ let(:two_levels_params) { { post_attributes: { comments_attributes: [ { body: 'test' } ] } } }
4981
+
4982
+ it "creates a 1st-depth child model" do
4983
+ author.update_attributes(one_level_params)
4984
+ expect(author.post.persisted?).to be true
4985
+ end
4986
+
4987
+ it "creates a 1st-depth child model, and a 2nd-depth child model" do
4988
+ author.update_attributes(two_levels_params)
4989
+ expect(author.post.comments.count).to eq 1
4990
+ end
4991
+
4992
+ context "the 1st-depth child model already exists" do
4993
+ it "creates a 2nd-depth child model" do
4994
+ author.create_post(title: 'test')
4995
+ author.update_attributes(two_levels_params)
4996
+ expect(author.post.comments.count).to eq 1
4997
+ end
4998
+ end
4999
+ end
4931
5000
  end
@@ -0,0 +1,48 @@
1
+ # frozen_string_literal: true
2
+
3
+ class NestedAuthor
4
+ include Mongoid::Document
5
+
6
+ field :name, type: String
7
+ has_one :post, class_name: "NestedPost"
8
+ accepts_nested_attributes_for :post
9
+ end
10
+
11
+ class NestedComment
12
+ include Mongoid::Document
13
+
14
+ field :body, type: String
15
+ belongs_to :post, class_name: "NestedPost"
16
+ end
17
+
18
+ class NestedPost
19
+ include Mongoid::Document
20
+
21
+ field :title, type: String
22
+ belongs_to :author, class_name: "NestedAuthor"
23
+ has_many :comments, class_name: "NestedComment"
24
+ accepts_nested_attributes_for :comments
25
+ end
26
+
27
+ class NestedBook
28
+ include Mongoid::Document
29
+
30
+ embeds_one :cover, class_name: "NestedCover"
31
+ embeds_many :pages, class_name: "NestedPage"
32
+
33
+ accepts_nested_attributes_for :cover, :pages
34
+ end
35
+
36
+ class NestedCover
37
+ include Mongoid::Document
38
+
39
+ field :title, type: String
40
+ embedded_in :book, class_name: "NestedBook"
41
+ end
42
+
43
+ class NestedPage
44
+ include Mongoid::Document
45
+
46
+ field :number, type: Integer
47
+ embedded_in :book, class_name: "NestedBook"
48
+ end
@@ -5,11 +5,7 @@ require "spec_helper"
5
5
  describe Mongoid::Attributes::Projector do
6
6
  Dir[File.join(File.dirname(__FILE__), 'projector_data', '*.yml')].sort.each do |path|
7
7
  context File.basename(path) do
8
- specs = if RUBY_VERSION.start_with?("2.5")
9
- YAML.safe_load(File.read(path), [], [], true)
10
- else
11
- YAML.safe_load(File.read(path), aliases: true)
12
- end
8
+ specs = YAML.safe_load(File.read(path), aliases: true)
13
9
 
14
10
  specs.each do |spec|
15
11
  context spec['name'] do