mongoid 7.6.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 (313) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +2 -0
  3. data/README.md +3 -3
  4. data/Rakefile +21 -85
  5. data/lib/config/locales/en.yml +46 -30
  6. data/lib/mongoid/association/accessors.rb +32 -3
  7. data/lib/mongoid/association/bindable.rb +48 -0
  8. data/lib/mongoid/association/builders.rb +4 -2
  9. data/lib/mongoid/association/eager_loadable.rb +29 -7
  10. data/lib/mongoid/association/embedded/batchable.rb +28 -5
  11. data/lib/mongoid/association/embedded/embedded_in/binding.rb +24 -2
  12. data/lib/mongoid/association/embedded/embedded_in.rb +2 -1
  13. data/lib/mongoid/association/embedded/embeds_many/binding.rb +1 -0
  14. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +1 -1
  15. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +40 -18
  16. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +18 -4
  17. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +21 -2
  18. data/lib/mongoid/association/macros.rb +2 -1
  19. data/lib/mongoid/association/many.rb +5 -0
  20. data/lib/mongoid/association/nested/many.rb +2 -1
  21. data/lib/mongoid/association/proxy.rb +12 -0
  22. data/lib/mongoid/association/referenced/auto_save.rb +3 -2
  23. data/lib/mongoid/association/referenced/belongs_to/binding.rb +1 -0
  24. data/lib/mongoid/association/referenced/belongs_to/buildable.rb +1 -1
  25. data/lib/mongoid/association/referenced/belongs_to.rb +1 -1
  26. data/lib/mongoid/association/referenced/counter_cache.rb +8 -8
  27. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +64 -11
  28. data/lib/mongoid/association/referenced/has_and_belongs_to_many.rb +4 -1
  29. data/lib/mongoid/association/referenced/has_many/enumerable.rb +10 -18
  30. data/lib/mongoid/association/referenced/has_many/proxy.rb +12 -9
  31. data/lib/mongoid/association/referenced/has_one/buildable.rb +1 -1
  32. data/lib/mongoid/association/referenced/has_one/proxy.rb +8 -11
  33. data/lib/mongoid/association/referenced/syncable.rb +2 -2
  34. data/lib/mongoid/association/relatable.rb +38 -4
  35. data/lib/mongoid/attributes/processing.rb +9 -2
  36. data/lib/mongoid/attributes.rb +30 -27
  37. data/lib/mongoid/cacheable.rb +2 -2
  38. data/lib/mongoid/changeable.rb +37 -2
  39. data/lib/mongoid/clients/options.rb +4 -0
  40. data/lib/mongoid/clients/sessions.rb +2 -14
  41. data/lib/mongoid/config.rb +15 -11
  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 +55 -28
  46. data/lib/mongoid/contextual/mongo.rb +173 -287
  47. data/lib/mongoid/contextual/none.rb +33 -15
  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 -15
  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 -16
  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/optional.rb +3 -9
  65. data/lib/mongoid/criteria/queryable/options.rb +1 -1
  66. data/lib/mongoid/criteria/queryable/selectable.rb +2 -24
  67. data/lib/mongoid/criteria/queryable/selector.rb +90 -5
  68. data/lib/mongoid/criteria/queryable/smash.rb +39 -6
  69. data/lib/mongoid/criteria/queryable/storable.rb +1 -1
  70. data/lib/mongoid/criteria/queryable.rb +11 -6
  71. data/lib/mongoid/criteria.rb +1 -28
  72. data/lib/mongoid/deprecable.rb +36 -0
  73. data/lib/mongoid/deprecation.rb +25 -0
  74. data/lib/mongoid/document.rb +88 -33
  75. data/lib/mongoid/equality.rb +4 -4
  76. data/lib/mongoid/errors/document_not_found.rb +6 -2
  77. data/lib/mongoid/errors/invalid_dot_dollar_assignment.rb +23 -0
  78. data/lib/mongoid/errors/invalid_field.rb +5 -1
  79. data/lib/mongoid/errors/invalid_field_type.rb +26 -0
  80. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +1 -1
  81. data/lib/mongoid/errors.rb +2 -2
  82. data/lib/mongoid/extensions/array.rb +8 -6
  83. data/lib/mongoid/extensions/big_decimal.rb +29 -10
  84. data/lib/mongoid/extensions/binary.rb +42 -0
  85. data/lib/mongoid/extensions/boolean.rb +8 -2
  86. data/lib/mongoid/extensions/date.rb +26 -20
  87. data/lib/mongoid/extensions/date_time.rb +1 -1
  88. data/lib/mongoid/extensions/float.rb +4 -5
  89. data/lib/mongoid/extensions/hash.rb +12 -5
  90. data/lib/mongoid/extensions/integer.rb +4 -5
  91. data/lib/mongoid/extensions/object.rb +2 -0
  92. data/lib/mongoid/extensions/range.rb +41 -10
  93. data/lib/mongoid/extensions/regexp.rb +11 -4
  94. data/lib/mongoid/extensions/set.rb +11 -4
  95. data/lib/mongoid/extensions/string.rb +2 -13
  96. data/lib/mongoid/extensions/symbol.rb +3 -14
  97. data/lib/mongoid/extensions/time.rb +27 -16
  98. data/lib/mongoid/extensions/time_with_zone.rb +1 -2
  99. data/lib/mongoid/extensions.rb +1 -0
  100. data/lib/mongoid/factory.rb +42 -7
  101. data/lib/mongoid/fields/foreign_key.rb +7 -0
  102. data/lib/mongoid/fields/validators/macro.rb +3 -9
  103. data/lib/mongoid/fields.rb +49 -7
  104. data/lib/mongoid/findable.rb +21 -16
  105. data/lib/mongoid/indexable/specification.rb +1 -1
  106. data/lib/mongoid/indexable/validators/options.rb +4 -1
  107. data/lib/mongoid/interceptable.rb +69 -9
  108. data/lib/mongoid/persistable/creatable.rb +14 -5
  109. data/lib/mongoid/persistable/updatable.rb +12 -5
  110. data/lib/mongoid/persistence_context.rb +8 -42
  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/scopable.rb +9 -11
  115. data/lib/mongoid/selectable.rb +1 -2
  116. data/lib/mongoid/shardable.rb +11 -35
  117. data/lib/mongoid/stateful.rb +27 -1
  118. data/lib/mongoid/timestamps/created.rb +1 -1
  119. data/lib/mongoid/timestamps/updated.rb +1 -1
  120. data/lib/mongoid/touchable.rb +2 -3
  121. data/lib/mongoid/traversable.rb +1 -0
  122. data/lib/mongoid/validatable/uniqueness.rb +2 -1
  123. data/lib/mongoid/version.rb +1 -5
  124. data/lib/mongoid/warnings.rb +3 -4
  125. data/lib/mongoid.rb +1 -0
  126. data/spec/config/mongoid.yml +16 -0
  127. data/spec/integration/app_spec.rb +8 -12
  128. data/spec/integration/associations/belongs_to_spec.rb +18 -0
  129. data/spec/integration/associations/embedded_spec.rb +15 -0
  130. data/spec/integration/associations/embeds_many_spec.rb +15 -2
  131. data/spec/integration/associations/embeds_one_spec.rb +18 -0
  132. data/spec/integration/associations/foreign_key_spec.rb +9 -0
  133. data/spec/integration/associations/has_and_belongs_to_many_spec.rb +21 -0
  134. data/spec/integration/associations/has_one_spec.rb +97 -1
  135. data/spec/integration/associations/scope_option_spec.rb +1 -1
  136. data/spec/integration/callbacks_models.rb +95 -1
  137. data/spec/integration/callbacks_spec.rb +226 -4
  138. data/spec/integration/criteria/range_spec.rb +95 -1
  139. data/spec/integration/discriminator_key_spec.rb +115 -76
  140. data/spec/integration/dots_and_dollars_spec.rb +277 -0
  141. data/spec/integration/i18n_fallbacks_spec.rb +1 -15
  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/mongoid/association/counter_cache_spec.rb +1 -1
  147. data/spec/mongoid/association/depending_spec.rb +9 -9
  148. data/spec/mongoid/association/eager_spec.rb +2 -1
  149. data/spec/mongoid/association/embedded/embedded_in/binding_spec.rb +2 -1
  150. data/spec/mongoid/association/embedded/embedded_in/buildable_spec.rb +54 -0
  151. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +69 -9
  152. data/spec/mongoid/association/embedded/embeds_many/buildable_spec.rb +112 -0
  153. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +198 -8
  154. data/spec/mongoid/association/embedded/embeds_many_models.rb +36 -0
  155. data/spec/mongoid/association/embedded/embeds_many_query_spec.rb +12 -0
  156. data/spec/mongoid/association/embedded/embeds_many_spec.rb +68 -0
  157. data/spec/mongoid/association/embedded/embeds_one/buildable_spec.rb +25 -0
  158. data/spec/mongoid/association/embedded/embeds_one_models.rb +19 -0
  159. data/spec/mongoid/association/embedded/embeds_one_spec.rb +28 -0
  160. data/spec/mongoid/association/referenced/belongs_to/binding_spec.rb +2 -1
  161. data/spec/mongoid/association/referenced/belongs_to/buildable_spec.rb +54 -0
  162. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +15 -0
  163. data/spec/mongoid/association/referenced/belongs_to_models.rb +11 -0
  164. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -2
  165. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +38 -5
  166. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +25 -0
  167. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +35 -2
  168. data/spec/mongoid/association/referenced/has_many/buildable_spec.rb +109 -0
  169. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +2 -56
  170. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +62 -13
  171. data/spec/mongoid/association/referenced/has_many_models.rb +3 -1
  172. data/spec/mongoid/association/referenced/has_many_spec.rb +25 -0
  173. data/spec/mongoid/association/referenced/has_one/buildable_spec.rb +2 -2
  174. data/spec/mongoid/association/referenced/has_one/proxy_spec.rb +107 -1
  175. data/spec/mongoid/association/referenced/has_one_models.rb +16 -0
  176. data/spec/mongoid/association/syncable_spec.rb +14 -0
  177. data/spec/mongoid/atomic/paths_spec.rb +0 -14
  178. data/spec/mongoid/attributes/nested_spec.rb +80 -11
  179. data/spec/mongoid/attributes/nested_spec_models.rb +48 -0
  180. data/spec/mongoid/attributes/projector_spec.rb +1 -5
  181. data/spec/mongoid/attributes_spec.rb +480 -27
  182. data/spec/mongoid/cacheable_spec.rb +3 -3
  183. data/spec/mongoid/changeable_spec.rb +130 -13
  184. data/spec/mongoid/clients/factory_spec.rb +23 -30
  185. data/spec/mongoid/clients/sessions_spec.rb +0 -38
  186. data/spec/mongoid/clients_spec.rb +2 -2
  187. data/spec/mongoid/config_spec.rb +52 -15
  188. data/spec/mongoid/contextual/aggregable/memory_spec.rb +396 -158
  189. data/spec/mongoid/contextual/aggregable/memory_table.yml +88 -0
  190. data/spec/mongoid/contextual/aggregable/memory_table_spec.rb +62 -0
  191. data/spec/mongoid/contextual/map_reduce_spec.rb +2 -16
  192. data/spec/mongoid/contextual/memory_spec.rb +521 -14
  193. data/spec/mongoid/contextual/mongo_spec.rb +566 -426
  194. data/spec/mongoid/contextual/none_spec.rb +11 -19
  195. data/spec/mongoid/copyable_spec.rb +451 -2
  196. data/spec/mongoid/criteria/findable_spec.rb +86 -210
  197. data/spec/mongoid/criteria/includable_spec.rb +1492 -0
  198. data/spec/mongoid/criteria/includable_spec_models.rb +54 -0
  199. data/spec/mongoid/criteria/marshalable_spec.rb +18 -1
  200. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +7 -19
  201. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +134 -26
  202. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +1 -2
  203. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +11 -0
  204. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +11 -0
  205. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +1 -2
  206. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +0 -15
  207. data/spec/mongoid/criteria/queryable/extensions/numeric_spec.rb +73 -7
  208. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +11 -0
  209. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +11 -0
  210. data/spec/mongoid/criteria/queryable/optional_spec.rb +0 -484
  211. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +50 -0
  212. data/spec/mongoid/criteria/queryable/selectable_spec.rb +77 -85
  213. data/spec/mongoid/criteria/queryable/selector_spec.rb +16 -77
  214. data/spec/mongoid/criteria/queryable/storable_spec.rb +0 -72
  215. data/spec/mongoid/criteria_spec.rb +469 -1201
  216. data/spec/mongoid/document_fields_spec.rb +173 -24
  217. data/spec/mongoid/document_spec.rb +32 -41
  218. data/spec/mongoid/equality_spec.rb +12 -12
  219. data/spec/mongoid/errors/document_not_found_spec.rb +29 -2
  220. data/spec/mongoid/errors/invalid_field_spec.rb +1 -1
  221. data/spec/mongoid/errors/invalid_field_type_spec.rb +55 -0
  222. data/spec/mongoid/errors/mongoid_error_spec.rb +3 -1
  223. data/spec/mongoid/errors/no_environment_spec.rb +3 -3
  224. data/spec/mongoid/errors/too_many_nested_attribute_records_spec.rb +1 -1
  225. data/spec/mongoid/extensions/array_spec.rb +16 -2
  226. data/spec/mongoid/extensions/big_decimal_spec.rb +697 -212
  227. data/spec/mongoid/extensions/binary_spec.rb +44 -9
  228. data/spec/mongoid/extensions/boolean_spec.rb +68 -82
  229. data/spec/mongoid/extensions/date_class_mongoize_spec.rb +7 -3
  230. data/spec/mongoid/extensions/date_spec.rb +71 -1
  231. data/spec/mongoid/extensions/date_time_spec.rb +15 -9
  232. data/spec/mongoid/extensions/float_spec.rb +48 -76
  233. data/spec/mongoid/extensions/hash_spec.rb +30 -0
  234. data/spec/mongoid/extensions/integer_spec.rb +45 -66
  235. data/spec/mongoid/extensions/range_spec.rb +255 -54
  236. data/spec/mongoid/extensions/regexp_spec.rb +58 -33
  237. data/spec/mongoid/extensions/set_spec.rb +106 -0
  238. data/spec/mongoid/extensions/string_spec.rb +53 -25
  239. data/spec/mongoid/extensions/symbol_spec.rb +18 -25
  240. data/spec/mongoid/extensions/time_spec.rb +634 -66
  241. data/spec/mongoid/extensions/time_with_zone_spec.rb +17 -31
  242. data/spec/mongoid/factory_spec.rb +61 -1
  243. data/spec/mongoid/fields_spec.rb +321 -50
  244. data/spec/mongoid/findable_spec.rb +64 -29
  245. data/spec/mongoid/indexable/specification_spec.rb +2 -2
  246. data/spec/mongoid/indexable_spec.rb +16 -19
  247. data/spec/mongoid/interceptable_spec.rb +584 -5
  248. data/spec/mongoid/interceptable_spec_models.rb +235 -4
  249. data/spec/mongoid/matcher/extract_attribute_spec.rb +1 -5
  250. data/spec/mongoid/mongoizable_spec.rb +285 -0
  251. data/spec/mongoid/persistable/creatable_spec.rb +2 -2
  252. data/spec/mongoid/persistable/deletable_spec.rb +2 -2
  253. data/spec/mongoid/persistable/destroyable_spec.rb +2 -2
  254. data/spec/mongoid/persistable/upsertable_spec.rb +14 -0
  255. data/spec/mongoid/persistence_context_spec.rb +24 -0
  256. data/spec/mongoid/query_cache_middleware_spec.rb +0 -18
  257. data/spec/mongoid/query_cache_spec.rb +1 -156
  258. data/spec/mongoid/reloadable_spec.rb +35 -2
  259. data/spec/mongoid/scopable_spec.rb +36 -34
  260. data/spec/mongoid/serializable_spec.rb +14 -7
  261. data/spec/mongoid/shardable_models.rb +0 -14
  262. data/spec/mongoid/shardable_spec.rb +61 -153
  263. data/spec/mongoid/stateful_spec.rb +28 -0
  264. data/spec/mongoid/timestamps_spec.rb +390 -0
  265. data/spec/mongoid/timestamps_spec_models.rb +67 -0
  266. data/spec/mongoid/touchable_spec.rb +116 -0
  267. data/spec/mongoid/touchable_spec_models.rb +12 -8
  268. data/spec/mongoid/traversable_spec.rb +4 -11
  269. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  270. data/spec/mongoid/validatable/uniqueness_spec.rb +60 -31
  271. data/spec/mongoid/warnings_spec.rb +35 -0
  272. data/spec/mongoid_spec.rb +1 -7
  273. data/spec/rails/controller_extension/controller_runtime_spec.rb +2 -2
  274. data/spec/rails/mongoid_spec.rb +4 -16
  275. data/spec/shared/lib/mrss/docker_runner.rb +1 -8
  276. data/spec/shared/lib/mrss/event_subscriber.rb +5 -15
  277. data/spec/shared/lib/mrss/lite_constraints.rb +2 -10
  278. data/spec/shared/lib/mrss/server_version_registry.rb +24 -17
  279. data/spec/shared/lib/mrss/spec_organizer.rb +3 -32
  280. data/spec/shared/lib/mrss/utils.rb +6 -28
  281. data/spec/shared/share/Dockerfile.erb +107 -33
  282. data/spec/shared/shlib/distro.sh +0 -10
  283. data/spec/shared/shlib/server.sh +33 -64
  284. data/spec/shared/shlib/set_env.sh +71 -12
  285. data/spec/support/constraints.rb +24 -0
  286. data/spec/support/expectations.rb +17 -20
  287. data/spec/support/macros.rb +30 -0
  288. data/spec/support/models/augmentation.rb +12 -0
  289. data/spec/support/models/band.rb +3 -0
  290. data/spec/support/models/catalog.rb +24 -0
  291. data/spec/support/models/circus.rb +3 -0
  292. data/spec/support/models/fanatic.rb +8 -0
  293. data/spec/support/models/implant.rb +9 -0
  294. data/spec/support/models/label.rb +2 -0
  295. data/spec/support/models/passport.rb +9 -0
  296. data/spec/support/models/person.rb +1 -0
  297. data/spec/support/models/player.rb +2 -0
  298. data/spec/support/models/powerup.rb +12 -0
  299. data/spec/support/models/registry.rb +1 -0
  300. data/spec/support/models/school.rb +14 -0
  301. data/spec/support/models/shield.rb +18 -0
  302. data/spec/support/models/student.rb +14 -0
  303. data/spec/support/models/weapon.rb +12 -0
  304. data.tar.gz.sig +0 -0
  305. metadata +695 -641
  306. metadata.gz.sig +0 -0
  307. data/lib/mongoid/errors/eager_load.rb +0 -23
  308. data/lib/mongoid/errors/invalid_value.rb +0 -17
  309. data/spec/mongoid/errors/eager_load_spec.rb +0 -31
  310. data/spec/shared/CANDIDATE.md +0 -28
  311. data/spec/shared/lib/mrss/release/candidate.rb +0 -281
  312. data/spec/shared/lib/mrss/release/product_data.rb +0 -144
  313. data/spec/shared/lib/tasks/candidate.rake +0 -64
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
+ require_relative '../belongs_to_models.rb'
4
5
 
5
6
  describe Mongoid::Association::Referenced::BelongsTo::Proxy do
6
7
 
@@ -1368,6 +1369,20 @@ describe Mongoid::Association::Referenced::BelongsTo::Proxy do
1368
1369
  game.person.set_personal_data(ssn: '123', age: 25)
1369
1370
  end.not_to raise_error
1370
1371
  end
1372
+ end
1373
+
1374
+ # This is a very specific case, see MONGOID-5089 for more details.
1375
+ context "when required is false, child is an orphan, and parent has explicit _id" do
1376
+ let(:comment) { BTMComment.create! }
1377
+ let(:article) do
1378
+ BTMArticle.new(
1379
+ comment_ids: [comment.id],
1380
+ id: 1
1381
+ )
1382
+ end
1371
1383
 
1384
+ it "uses the correct explicit id" do
1385
+ expect(article.comments.first.article_id).to eq(1)
1386
+ end
1372
1387
  end
1373
1388
  end
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ class BTMArticle
4
+ include Mongoid::Document
5
+ has_many :comments, class_name: "BTMComment"
6
+ end
7
+
8
+ class BTMComment
9
+ include Mongoid::Document
10
+ belongs_to :article, class_name: "BTMArticle", required: false
11
+ end
@@ -2019,8 +2019,8 @@ describe Mongoid::Association::Referenced::BelongsTo do
2019
2019
 
2020
2020
  describe '#foreign_key_check' do
2021
2021
 
2022
- it 'returns the foreign_key followed by "_changed?"' do
2023
- expect(association.foreign_key_check).to eq('owner_object_id_changed?')
2022
+ it 'returns the foreign_key followed by "_previously_changed?"' do
2023
+ expect(association.foreign_key_check).to eq('owner_object_id_previously_changed?')
2024
2024
  end
2025
2025
  end
2026
2026
 
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
- require_relative "../has_and_belongs_to_many_models.rb"
4
+ require_relative "../has_and_belongs_to_many_models"
5
5
 
6
6
  describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
7
7
 
@@ -2395,6 +2395,10 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2395
2395
  it "removes the ids from the foreign key" do
2396
2396
  expect(person.preference_ids).to eq([ preference_two.id ])
2397
2397
  end
2398
+
2399
+ it "sets the association locally" do
2400
+ expect(person.preferences).to eq([preference_two])
2401
+ end
2398
2402
  end
2399
2403
 
2400
2404
  context "when conditions are not provided" do
@@ -2421,6 +2425,10 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2421
2425
  it "returns the number of documents deleted" do
2422
2426
  expect(deleted).to eq(2)
2423
2427
  end
2428
+
2429
+ it "sets the association locally" do
2430
+ expect(person.preferences).to eq([])
2431
+ end
2424
2432
  end
2425
2433
  end
2426
2434
  end
@@ -2508,7 +2516,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2508
2516
  it "raises an error" do
2509
2517
  expect {
2510
2518
  preference
2511
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2519
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2512
2520
  end
2513
2521
  end
2514
2522
 
@@ -2523,7 +2531,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2523
2531
  it "raises an error" do
2524
2532
  expect {
2525
2533
  person.preferences.find(BSON::ObjectId.new)
2526
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2534
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2527
2535
  end
2528
2536
  end
2529
2537
 
@@ -2572,7 +2580,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2572
2580
  it "raises an error" do
2573
2581
  expect {
2574
2582
  preferences
2575
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2583
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2576
2584
  end
2577
2585
  end
2578
2586
 
@@ -2587,7 +2595,7 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
2587
2595
  it "raises an error" do
2588
2596
  expect {
2589
2597
  person.preferences.find([ BSON::ObjectId.new ])
2590
- }.to raise_error(Mongoid::Errors::DocumentNotFound)
2598
+ }.to raise_error(Mongoid::Errors::DocumentNotFound, /Document\(s\) not found for class Preference with id\(s\)/)
2591
2599
  end
2592
2600
  end
2593
2601
 
@@ -3772,6 +3780,31 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany::Proxy do
3772
3780
  end
3773
3781
  end
3774
3782
 
3783
+ context "when accesing own _id from parent's foreign key in default" do
3784
+ let!(:contract) { HabtmmContract.create! }
3785
+ let!(:signature) { contract.signatures.create! }
3786
+
3787
+ it "is nil" do
3788
+ expect(signature.favorite_signature).to be nil
3789
+ end
3790
+ end
3791
+
3792
+ context "when setting an association on a model that uses the class_name option" do
3793
+ let!(:contract) { HabtmmContract.create! }
3794
+ let!(:signature) { HabtmmSignature.create!(contracts: [contract]) }
3795
+
3796
+ it "populates the inverse foreign key" do
3797
+ expect(signature.contracts.first.signature_ids).to eq([signature.id])
3798
+ end
3799
+ end
3800
+
3801
+ context "when there is a foreign key in the aliased associations" do
3802
+ it "has the correct aliases" do
3803
+ expect(Dog.aliased_associations["breed_ids"]).to eq("breeds")
3804
+ expect(Breed.aliased_associations["dog_ids"]).to eq("dogs")
3805
+ end
3806
+ end
3807
+
3775
3808
  # This test is for MONGOID-5344 which tests that the initial call to
3776
3809
  # signature_ids refers to the same array as subsequent calls to signature_ids.
3777
3810
  # Prior to the change in that ticket, this test broke because the array
@@ -32,6 +32,8 @@ end
32
32
  class HabtmmSignature
33
33
  include Mongoid::Document
34
34
 
35
+ field :favorite_signature, default: ->{ contracts.first.signature_ids.first if contracts.first }
36
+
35
37
  has_and_belongs_to_many :contracts, class_name: 'HabtmmContract'
36
38
 
37
39
  field :name, type: String
@@ -65,3 +67,26 @@ class HabtmmAnimal
65
67
 
66
68
  has_and_belongs_to_many :trainers, inverse_of: :animals, class_name: 'HabtmmTrainer', scope: -> { where(name: 'Dave') }
67
69
  end
70
+
71
+ class HabtmmSchool
72
+ include Mongoid::Document
73
+ include Mongoid::Timestamps
74
+
75
+ has_and_belongs_to_many :students, class_name: 'HabtmmStudent'
76
+
77
+ field :after_destroy_triggered, default: false
78
+
79
+ accepts_nested_attributes_for :students, allow_destroy: true
80
+ end
81
+
82
+ class HabtmmStudent
83
+ include Mongoid::Document
84
+ include Mongoid::Timestamps
85
+
86
+ has_and_belongs_to_many :schools, class_name: 'HabtmmSchool'
87
+
88
+ after_destroy do |doc|
89
+ schools.first.update_attributes!(after_destroy_triggered: true) unless schools.empty?
90
+ end
91
+ end
92
+
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require "spec_helper"
4
+ require_relative "./has_and_belongs_to_many_models"
4
5
 
5
6
  describe Mongoid::Association::Referenced::HasAndBelongsToMany do
6
7
 
@@ -1008,8 +1009,8 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
1008
1009
 
1009
1010
  describe '#foreign_key_check' do
1010
1011
 
1011
- it 'returns the foreign_key followed by "_changed?"' do
1012
- expect(association.foreign_key_check).to eq('has_many_right_object_ids_changed?')
1012
+ it 'returns the foreign_key followed by "_previously_changed?"' do
1013
+ expect(association.foreign_key_check).to eq('has_many_right_object_ids_previously_changed?')
1013
1014
  end
1014
1015
  end
1015
1016
 
@@ -1060,6 +1061,13 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
1060
1061
  expect(association.inverse_foreign_key).to eq('bar_ref')
1061
1062
  end
1062
1063
  end
1064
+
1065
+ context "when using a model that uses the class_name option" do
1066
+ let(:inverse_foreign_key) { HabtmmSchool.relations[:students].inverse_foreign_key }
1067
+ it "gets the correct inverse foreign key" do
1068
+ expect(inverse_foreign_key).to eq("school_ids")
1069
+ end
1070
+ end
1063
1071
  end
1064
1072
 
1065
1073
  describe '#inverse_foreign_key_setter' do
@@ -1068,4 +1076,29 @@ describe Mongoid::Association::Referenced::HasAndBelongsToMany do
1068
1076
  expect(association.inverse_foreign_key_setter).to eq('has_many_left_object_ids=')
1069
1077
  end
1070
1078
  end
1079
+
1080
+ context "when adding an object to the association" do
1081
+ let!(:start_time) { Timecop.freeze(Time.at(Time.now.to_i)) }
1082
+
1083
+ let(:update_time) do
1084
+ Timecop.freeze(Time.at(Time.now.to_i) + 2)
1085
+ end
1086
+
1087
+ after do
1088
+ Timecop.return
1089
+ end
1090
+
1091
+ let!(:school) { HabtmmSchool.create! }
1092
+ let!(:student) { HabtmmStudent.create! }
1093
+
1094
+ before do
1095
+ update_time
1096
+ school.update(students: [student])
1097
+ end
1098
+
1099
+ it "updates the updated at" do
1100
+ pending "MONGOID-4953"
1101
+ expect(school.updated_at).to eq(update_time)
1102
+ end
1103
+ end
1071
1104
  end
@@ -138,5 +138,114 @@ describe Mongoid::Association::Referenced::HasMany::Buildable do
138
138
  end
139
139
  end
140
140
  end
141
+
142
+ context 'when the object is already associated with another object' do
143
+
144
+ context "when using <<" do
145
+
146
+ let(:person1) do
147
+ Person.new
148
+ end
149
+
150
+ let(:person2) do
151
+ Person.new
152
+ end
153
+
154
+ let(:drug) do
155
+ Drug.new
156
+ end
157
+
158
+ before do
159
+ person1.drugs << drug
160
+ person2.drugs << drug
161
+ end
162
+
163
+ it 'clears the object of its previous association' do
164
+ expect(person1.drugs).to eq([])
165
+ expect(person1.drug_ids).to eq([])
166
+ expect(person2.drugs).to eq([drug])
167
+ expect(person2.drug_ids).to eq([drug._id])
168
+ end
169
+ end
170
+
171
+ context "when using concat" do
172
+
173
+ let(:person1) do
174
+ Person.new
175
+ end
176
+
177
+ let(:person2) do
178
+ Person.new
179
+ end
180
+
181
+ let(:drug) do
182
+ Drug.new
183
+ end
184
+
185
+ before do
186
+ person1.drugs.concat([drug])
187
+ person2.drugs.concat([drug])
188
+ end
189
+
190
+ it 'clears the object of its previous association' do
191
+ expect(person1.drugs).to eq([])
192
+ expect(person1.drug_ids).to eq([])
193
+ expect(person2.drugs).to eq([drug])
194
+ expect(person2.drug_ids).to eq([drug._id])
195
+ end
196
+ end
197
+
198
+ context "when using =" do
199
+
200
+ let(:person1) do
201
+ Person.new
202
+ end
203
+
204
+ let(:person2) do
205
+ Person.new
206
+ end
207
+
208
+ let(:drug) do
209
+ Drug.new
210
+ end
211
+
212
+ before do
213
+ person1.drugs = [drug]
214
+ person2.drugs = [drug]
215
+ end
216
+
217
+ it 'clears the object of its previous association' do
218
+ expect(person1.drugs).to eq([])
219
+ expect(person1.drug_ids).to eq([])
220
+ expect(person2.drugs).to eq([drug])
221
+ expect(person2.drug_ids).to eq([drug._id])
222
+ end
223
+ end
224
+
225
+ context "when using = on the same document twice" do
226
+
227
+ let(:person1) do
228
+ Person.new
229
+ end
230
+
231
+ let(:person2) do
232
+ Person.new
233
+ end
234
+
235
+ let(:drug) do
236
+ Drug.new
237
+ end
238
+
239
+ before do
240
+ person1.drugs = [drug]
241
+ person1.drugs = [drug]
242
+ end
243
+
244
+ it 'clears the object of its previous association' do
245
+ expect(person1.drugs).to eq([drug])
246
+ expect(person1.drug_ids).to eq([drug._id])
247
+ end
248
+ end
249
+ end
141
250
  end
142
251
  end
@@ -1237,33 +1237,6 @@ describe Mongoid::Association::Referenced::HasMany::Enumerable do
1237
1237
  end
1238
1238
  end
1239
1239
 
1240
- context 'when the id_sort option is none' do
1241
-
1242
- let(:person) do
1243
- Person.create!
1244
- end
1245
-
1246
- let(:criteria) do
1247
- Post.where(person_id: person.id)
1248
- end
1249
-
1250
- let(:enumerable) do
1251
- described_class.new(criteria)
1252
- end
1253
-
1254
- let!(:first_post) do
1255
- person.posts.create!(title: "One")
1256
- end
1257
-
1258
- let!(:second_post) do
1259
- person.posts.create!(title: "Two")
1260
- end
1261
-
1262
- it 'does not use the sort on id' do
1263
- expect(enumerable.first(id_sort: :none)).to eq(first_post)
1264
- end
1265
- end
1266
-
1267
1240
  context 'when including a limit' do
1268
1241
 
1269
1242
  let(:person) do
@@ -1291,7 +1264,7 @@ describe Mongoid::Association::Referenced::HasMany::Enumerable do
1291
1264
  end
1292
1265
  end
1293
1266
 
1294
- context 'when the id_sort option is not provided' do
1267
+ context 'when no parameters are provided' do
1295
1268
 
1296
1269
  let(:person) do
1297
1270
  Person.create!
@@ -1761,34 +1734,7 @@ describe Mongoid::Association::Referenced::HasMany::Enumerable do
1761
1734
  end
1762
1735
  end
1763
1736
 
1764
- context 'when the id_sort option is none' do
1765
-
1766
- let(:person) do
1767
- Person.create!
1768
- end
1769
-
1770
- let(:criteria) do
1771
- Post.where(person_id: person.id)
1772
- end
1773
-
1774
- let(:enumerable) do
1775
- described_class.new(criteria)
1776
- end
1777
-
1778
- let!(:first_post) do
1779
- person.posts.create!(title: "One")
1780
- end
1781
-
1782
- let!(:second_post) do
1783
- person.posts.create!(title: "Two")
1784
- end
1785
-
1786
- it 'does not use the sort on id' do
1787
- expect(enumerable.last(id_sort: :none)).to eq(first_post)
1788
- end
1789
- end
1790
-
1791
- context 'when the id_sort option is not provided' do
1737
+ context 'when no parameters are provided' do
1792
1738
 
1793
1739
  let(:person) do
1794
1740
  Person.create!
@@ -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
 
@@ -4090,6 +4106,39 @@ describe Mongoid::Association::Referenced::HasMany::Proxy do
4090
4106
  end
4091
4107
  end
4092
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
+
4093
4142
  context "when executing concat on foreign key array from the db" do
4094
4143
  config_override :legacy_attributes, false
4095
4144
 
@@ -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