mongoid 5.4.0 → 6.4.8

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 (301) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/README.md +3 -3
  4. data/Rakefile +26 -0
  5. data/lib/config/locales/en.yml +40 -0
  6. data/lib/mongoid/atomic/modifiers.rb +2 -2
  7. data/lib/mongoid/atomic.rb +5 -5
  8. data/lib/mongoid/attributes/readonly.rb +22 -0
  9. data/lib/mongoid/attributes.rb +22 -21
  10. data/lib/mongoid/cacheable.rb +36 -0
  11. data/lib/mongoid/changeable.rb +36 -0
  12. data/lib/mongoid/clients/options.rb +55 -250
  13. data/lib/mongoid/clients/sessions.rb +113 -0
  14. data/lib/mongoid/clients/storage_options.rb +2 -69
  15. data/lib/mongoid/clients.rb +10 -63
  16. data/lib/mongoid/composable.rb +29 -2
  17. data/lib/mongoid/config.rb +1 -0
  18. data/lib/mongoid/contextual/aggregable/mongo.rb +1 -1
  19. data/lib/mongoid/contextual/atomic.rb +4 -4
  20. data/lib/mongoid/contextual/map_reduce.rb +7 -3
  21. data/lib/mongoid/contextual/memory.rb +9 -4
  22. data/lib/mongoid/contextual/mongo.rb +65 -30
  23. data/lib/mongoid/contextual/none.rb +12 -0
  24. data/lib/mongoid/copyable.rb +13 -6
  25. data/lib/mongoid/criteria/marshalable.rb +2 -2
  26. data/lib/mongoid/criteria/modifiable.rb +29 -3
  27. data/lib/mongoid/criteria/options.rb +25 -0
  28. data/lib/mongoid/criteria/queryable/aggregable.rb +120 -0
  29. data/lib/mongoid/criteria/queryable/extensions/array.rb +185 -0
  30. data/lib/mongoid/criteria/queryable/extensions/big_decimal.rb +37 -0
  31. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +34 -0
  32. data/lib/mongoid/criteria/queryable/extensions/date.rb +63 -0
  33. data/lib/mongoid/criteria/queryable/extensions/date_time.rb +53 -0
  34. data/lib/mongoid/criteria/queryable/extensions/hash.rb +200 -0
  35. data/lib/mongoid/criteria/queryable/extensions/nil_class.rb +86 -0
  36. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +90 -0
  37. data/lib/mongoid/criteria/queryable/extensions/object.rb +206 -0
  38. data/lib/mongoid/criteria/queryable/extensions/range.rb +70 -0
  39. data/lib/mongoid/criteria/queryable/extensions/regexp.rb +79 -0
  40. data/lib/mongoid/criteria/queryable/extensions/set.rb +34 -0
  41. data/lib/mongoid/criteria/queryable/extensions/string.rb +137 -0
  42. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +79 -0
  43. data/lib/mongoid/criteria/queryable/extensions/time.rb +60 -0
  44. data/lib/mongoid/criteria/queryable/extensions/time_with_zone.rb +54 -0
  45. data/lib/mongoid/criteria/queryable/extensions.rb +28 -0
  46. data/lib/mongoid/criteria/queryable/forwardable.rb +65 -0
  47. data/lib/mongoid/criteria/queryable/key.rb +103 -0
  48. data/lib/mongoid/criteria/queryable/macroable.rb +27 -0
  49. data/lib/mongoid/criteria/queryable/mergeable.rb +273 -0
  50. data/lib/mongoid/criteria/queryable/optional.rb +429 -0
  51. data/lib/mongoid/criteria/queryable/options.rb +153 -0
  52. data/lib/mongoid/criteria/queryable/pipeline.rb +111 -0
  53. data/lib/mongoid/criteria/queryable/selectable.rb +689 -0
  54. data/lib/mongoid/criteria/queryable/selector.rb +212 -0
  55. data/lib/mongoid/criteria/queryable/smash.rb +104 -0
  56. data/lib/mongoid/criteria/queryable.rb +87 -0
  57. data/lib/mongoid/criteria.rb +6 -2
  58. data/lib/mongoid/document.rb +34 -41
  59. data/lib/mongoid/errors/ambiguous_relationship.rb +1 -1
  60. data/lib/mongoid/errors/in_memory_collation_not_supported.rb +1 -1
  61. data/lib/mongoid/errors/invalid_field.rb +2 -2
  62. data/lib/mongoid/errors/invalid_persistence_option.rb +29 -0
  63. data/lib/mongoid/errors/invalid_relation.rb +66 -0
  64. data/lib/mongoid/errors/invalid_session_use.rb +24 -0
  65. data/lib/mongoid/errors.rb +3 -0
  66. data/lib/mongoid/evolvable.rb +1 -1
  67. data/lib/mongoid/extensions/big_decimal.rb +17 -8
  68. data/lib/mongoid/extensions/date.rb +4 -1
  69. data/lib/mongoid/extensions/decimal128.rb +3 -3
  70. data/lib/mongoid/extensions/hash.rb +1 -0
  71. data/lib/mongoid/extensions/regexp.rb +1 -0
  72. data/lib/mongoid/extensions/string.rb +6 -3
  73. data/lib/mongoid/extensions/time.rb +4 -1
  74. data/lib/mongoid/extensions.rb +0 -4
  75. data/lib/mongoid/factory.rb +2 -1
  76. data/lib/mongoid/fields/validators/macro.rb +18 -0
  77. data/lib/mongoid/findable.rb +2 -2
  78. data/lib/mongoid/indexable.rb +16 -14
  79. data/lib/mongoid/interceptable.rb +9 -22
  80. data/lib/mongoid/matchable/all.rb +2 -2
  81. data/lib/mongoid/matchable/and.rb +3 -3
  82. data/lib/mongoid/matchable/default.rb +2 -2
  83. data/lib/mongoid/matchable/elem_match.rb +28 -0
  84. data/lib/mongoid/matchable/exists.rb +2 -2
  85. data/lib/mongoid/matchable/gt.rb +4 -2
  86. data/lib/mongoid/matchable/gte.rb +4 -2
  87. data/lib/mongoid/matchable/in.rb +2 -2
  88. data/lib/mongoid/matchable/lt.rb +4 -2
  89. data/lib/mongoid/matchable/lte.rb +4 -2
  90. data/lib/mongoid/matchable/ne.rb +2 -2
  91. data/lib/mongoid/matchable/nin.rb +2 -2
  92. data/lib/mongoid/matchable/nor.rb +37 -0
  93. data/lib/mongoid/matchable/or.rb +3 -3
  94. data/lib/mongoid/matchable/regexp.rb +3 -3
  95. data/lib/mongoid/matchable/size.rb +2 -2
  96. data/lib/mongoid/matchable.rb +16 -7
  97. data/lib/mongoid/persistable/creatable.rb +5 -3
  98. data/lib/mongoid/persistable/deletable.rb +5 -3
  99. data/lib/mongoid/persistable/destroyable.rb +1 -5
  100. data/lib/mongoid/persistable/settable.rb +5 -5
  101. data/lib/mongoid/persistable/updatable.rb +7 -14
  102. data/lib/mongoid/persistable/upsertable.rb +2 -1
  103. data/lib/mongoid/persistable.rb +4 -6
  104. data/lib/mongoid/persistence_context.rb +220 -0
  105. data/lib/mongoid/query_cache.rb +67 -23
  106. data/lib/mongoid/railtie.rb +17 -1
  107. data/lib/mongoid/railties/controller_runtime.rb +86 -0
  108. data/lib/mongoid/relations/accessors.rb +3 -0
  109. data/lib/mongoid/relations/auto_save.rb +12 -4
  110. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +4 -4
  111. data/lib/mongoid/relations/counter_cache.rb +15 -5
  112. data/lib/mongoid/relations/eager/base.rb +3 -3
  113. data/lib/mongoid/relations/eager/has_and_belongs_to_many.rb +2 -2
  114. data/lib/mongoid/relations/eager/has_many.rb +1 -1
  115. data/lib/mongoid/relations/eager.rb +6 -11
  116. data/lib/mongoid/relations/embedded/batchable.rb +20 -18
  117. data/lib/mongoid/relations/embedded/in.rb +13 -1
  118. data/lib/mongoid/relations/embedded/many.rb +51 -10
  119. data/lib/mongoid/relations/embedded/one.rb +14 -1
  120. data/lib/mongoid/relations/macros.rb +9 -1
  121. data/lib/mongoid/relations/many.rb +4 -0
  122. data/lib/mongoid/relations/metadata.rb +3 -3
  123. data/lib/mongoid/relations/options.rb +2 -2
  124. data/lib/mongoid/relations/proxy.rb +1 -31
  125. data/lib/mongoid/relations/referenced/in.rb +19 -10
  126. data/lib/mongoid/relations/referenced/many.rb +30 -26
  127. data/lib/mongoid/relations/referenced/many_to_many.rb +20 -13
  128. data/lib/mongoid/relations/referenced/one.rb +15 -1
  129. data/lib/mongoid/relations/synchronization.rb +12 -12
  130. data/lib/mongoid/relations/targets/enumerable.rb +24 -4
  131. data/lib/mongoid/relations/touchable.rb +7 -4
  132. data/lib/mongoid/reloadable.rb +2 -2
  133. data/lib/mongoid/scopable.rb +3 -3
  134. data/lib/mongoid/serializable.rb +1 -1
  135. data/lib/mongoid/stateful.rb +1 -0
  136. data/lib/mongoid/tasks/database.rb +3 -2
  137. data/lib/mongoid/threaded.rb +74 -0
  138. data/lib/mongoid/traversable.rb +1 -1
  139. data/lib/mongoid/validatable/uniqueness.rb +1 -2
  140. data/lib/mongoid/version.rb +1 -1
  141. data/lib/mongoid.rb +6 -6
  142. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +18 -3
  143. data/spec/app/models/agent.rb +2 -0
  144. data/spec/app/models/album.rb +5 -1
  145. data/spec/app/models/array_field.rb +7 -0
  146. data/spec/app/models/artist.rb +21 -0
  147. data/spec/app/models/band.rb +3 -0
  148. data/spec/app/models/book.rb +2 -1
  149. data/spec/app/models/delegating_patient.rb +16 -0
  150. data/spec/app/models/dokument.rb +1 -0
  151. data/spec/app/models/ordered_post.rb +5 -0
  152. data/spec/app/models/oscar.rb +1 -2
  153. data/spec/app/models/page.rb +1 -1
  154. data/spec/app/models/person.rb +3 -3
  155. data/spec/app/models/princess.rb +2 -0
  156. data/spec/app/models/record.rb +1 -0
  157. data/spec/app/models/subscription.rb +1 -0
  158. data/spec/app/models/thing.rb +1 -1
  159. data/spec/config/mongoid.yml +15 -0
  160. data/spec/integration/document_spec.rb +22 -0
  161. data/spec/mongoid/atomic/modifiers_spec.rb +3 -3
  162. data/spec/mongoid/atomic_spec.rb +5 -5
  163. data/spec/mongoid/attributes/nested_spec.rb +18 -14
  164. data/spec/mongoid/attributes/readonly_spec.rb +87 -44
  165. data/spec/mongoid/attributes_spec.rb +90 -5
  166. data/spec/mongoid/cacheable_spec.rb +112 -0
  167. data/spec/mongoid/changeable_spec.rb +58 -0
  168. data/spec/mongoid/clients/factory_spec.rb +80 -28
  169. data/spec/mongoid/clients/options_spec.rb +396 -95
  170. data/spec/mongoid/clients/sessions_spec.rb +334 -0
  171. data/spec/mongoid/clients_spec.rb +243 -101
  172. data/spec/mongoid/composable_spec.rb +7 -0
  173. data/spec/mongoid/config_spec.rb +67 -11
  174. data/spec/mongoid/contextual/atomic_spec.rb +3 -3
  175. data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
  176. data/spec/mongoid/contextual/mongo_spec.rb +275 -22
  177. data/spec/mongoid/contextual/none_spec.rb +15 -0
  178. data/spec/mongoid/copyable_spec.rb +13 -4
  179. data/spec/mongoid/criteria/modifiable_spec.rb +297 -16
  180. data/spec/mongoid/criteria/options_spec.rb +29 -0
  181. data/spec/mongoid/criteria/queryable/aggregable_spec.rb +370 -0
  182. data/spec/mongoid/criteria/queryable/extensions/array_spec.rb +523 -0
  183. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +59 -0
  184. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +58 -0
  185. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +213 -0
  186. data/spec/mongoid/criteria/queryable/extensions/date_spec.rb +330 -0
  187. data/spec/mongoid/criteria/queryable/extensions/date_time_spec.rb +405 -0
  188. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +58 -0
  189. data/spec/mongoid/criteria/queryable/extensions/float_spec.rb +65 -0
  190. data/spec/mongoid/criteria/queryable/extensions/hash_spec.rb +327 -0
  191. data/spec/mongoid/criteria/queryable/extensions/integer_spec.rb +65 -0
  192. data/spec/mongoid/criteria/queryable/extensions/nil_class_spec.rb +77 -0
  193. data/spec/mongoid/criteria/queryable/extensions/object_spec.rb +108 -0
  194. data/spec/mongoid/criteria/queryable/extensions/range_spec.rb +309 -0
  195. data/spec/mongoid/{extensions/origin → criteria/queryable/extensions}/regexp_raw_spec.rb +2 -2
  196. data/spec/mongoid/criteria/queryable/extensions/regexp_spec.rb +90 -0
  197. data/spec/mongoid/criteria/queryable/extensions/set_spec.rb +39 -0
  198. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +302 -0
  199. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +167 -0
  200. data/spec/mongoid/criteria/queryable/extensions/time_spec.rb +376 -0
  201. data/spec/mongoid/criteria/queryable/extensions/time_with_zone_spec.rb +347 -0
  202. data/spec/mongoid/criteria/queryable/forwardable_spec.rb +87 -0
  203. data/spec/mongoid/criteria/queryable/key_spec.rb +52 -0
  204. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +49 -0
  205. data/spec/mongoid/criteria/queryable/optional_spec.rb +1799 -0
  206. data/spec/mongoid/criteria/queryable/options_spec.rb +360 -0
  207. data/spec/mongoid/criteria/queryable/pipeline_spec.rb +200 -0
  208. data/spec/mongoid/criteria/queryable/queryable_spec.rb +137 -0
  209. data/spec/mongoid/criteria/queryable/selectable_spec.rb +4242 -0
  210. data/spec/mongoid/criteria/queryable/selector_spec.rb +844 -0
  211. data/spec/mongoid/criteria/queryable/smash_spec.rb +30 -0
  212. data/spec/mongoid/criteria/scopable_spec.rb +81 -0
  213. data/spec/mongoid/criteria_spec.rb +156 -22
  214. data/spec/mongoid/document_spec.rb +100 -90
  215. data/spec/mongoid/errors/invalid_relation_spec.rb +37 -0
  216. data/spec/mongoid/errors/mongoid_error_spec.rb +6 -3
  217. data/spec/mongoid/extensions/big_decimal_spec.rb +321 -19
  218. data/spec/mongoid/extensions/boolean_spec.rb +14 -0
  219. data/spec/mongoid/extensions/date_spec.rb +2 -6
  220. data/spec/mongoid/extensions/date_time_spec.rb +2 -6
  221. data/spec/mongoid/extensions/decimal128_spec.rb +1 -1
  222. data/spec/mongoid/extensions/float_spec.rb +8 -1
  223. data/spec/mongoid/extensions/hash_spec.rb +15 -0
  224. data/spec/mongoid/extensions/integer_spec.rb +8 -1
  225. data/spec/mongoid/extensions/object_spec.rb +11 -0
  226. data/spec/mongoid/extensions/regexp_spec.rb +23 -0
  227. data/spec/mongoid/extensions/string_spec.rb +53 -4
  228. data/spec/mongoid/extensions/time_spec.rb +2 -6
  229. data/spec/mongoid/extensions/time_with_zone_spec.rb +2 -6
  230. data/spec/mongoid/factory_spec.rb +11 -0
  231. data/spec/mongoid/fields_spec.rb +1 -1
  232. data/spec/mongoid/findable_spec.rb +47 -2
  233. data/spec/mongoid/indexable_spec.rb +15 -3
  234. data/spec/mongoid/interceptable_spec.rb +85 -19
  235. data/spec/mongoid/matchable/all_spec.rb +4 -4
  236. data/spec/mongoid/matchable/and_spec.rb +10 -10
  237. data/spec/mongoid/matchable/default_spec.rb +12 -12
  238. data/spec/mongoid/matchable/elem_match_spec.rb +86 -0
  239. data/spec/mongoid/matchable/exists_spec.rb +5 -5
  240. data/spec/mongoid/matchable/gt_spec.rb +18 -7
  241. data/spec/mongoid/matchable/gte_spec.rb +17 -7
  242. data/spec/mongoid/matchable/in_spec.rb +5 -5
  243. data/spec/mongoid/matchable/lt_spec.rb +18 -7
  244. data/spec/mongoid/matchable/lte_spec.rb +18 -7
  245. data/spec/mongoid/matchable/ne_spec.rb +5 -5
  246. data/spec/mongoid/matchable/nin_spec.rb +5 -5
  247. data/spec/mongoid/matchable/nor_spec.rb +209 -0
  248. data/spec/mongoid/matchable/or_spec.rb +7 -7
  249. data/spec/mongoid/matchable/regexp_spec.rb +5 -5
  250. data/spec/mongoid/matchable/size_spec.rb +3 -3
  251. data/spec/mongoid/matchable_spec.rb +199 -54
  252. data/spec/mongoid/persistable/creatable_spec.rb +7 -2
  253. data/spec/mongoid/persistable/deletable_spec.rb +35 -1
  254. data/spec/mongoid/persistable/destroyable_spec.rb +25 -2
  255. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  256. data/spec/mongoid/persistable/savable_spec.rb +34 -29
  257. data/spec/mongoid/persistable/settable_spec.rb +77 -27
  258. data/spec/mongoid/persistable/updatable_spec.rb +182 -3
  259. data/spec/mongoid/persistable_spec.rb +16 -16
  260. data/spec/mongoid/persistence_context_spec.rb +694 -0
  261. data/spec/mongoid/positional_spec.rb +1 -1
  262. data/spec/mongoid/query_cache_spec.rb +170 -12
  263. data/spec/mongoid/relations/accessors_spec.rb +1 -1
  264. data/spec/mongoid/relations/auto_save_spec.rb +39 -6
  265. data/spec/mongoid/relations/bindings/referenced/many_to_many_spec.rb +4 -4
  266. data/spec/mongoid/relations/builders_spec.rb +37 -10
  267. data/spec/mongoid/relations/counter_cache_spec.rb +64 -3
  268. data/spec/mongoid/relations/eager/has_and_belongs_to_many_spec.rb +16 -0
  269. data/spec/mongoid/relations/eager_spec.rb +40 -0
  270. data/spec/mongoid/relations/embedded/many_spec.rb +305 -59
  271. data/spec/mongoid/relations/embedded/one_spec.rb +2 -1
  272. data/spec/mongoid/relations/macros_spec.rb +415 -7
  273. data/spec/mongoid/relations/metadata_spec.rb +15 -1
  274. data/spec/mongoid/relations/proxy_spec.rb +27 -1
  275. data/spec/mongoid/relations/referenced/in_spec.rb +41 -1
  276. data/spec/mongoid/relations/referenced/many_spec.rb +35 -25
  277. data/spec/mongoid/relations/referenced/many_to_many_spec.rb +14 -26
  278. data/spec/mongoid/relations/synchronization_spec.rb +48 -2
  279. data/spec/mongoid/relations/targets/enumerable_spec.rb +108 -0
  280. data/spec/mongoid/relations/touchable_spec.rb +40 -0
  281. data/spec/mongoid/reloadable_spec.rb +51 -0
  282. data/spec/mongoid/scopable_spec.rb +13 -0
  283. data/spec/mongoid/serializable_spec.rb +0 -50
  284. data/spec/mongoid/threaded_spec.rb +68 -0
  285. data/spec/mongoid/validatable/presence_spec.rb +1 -1
  286. data/spec/mongoid/validatable/uniqueness_spec.rb +18 -9
  287. data/spec/mongoid/validatable_spec.rb +16 -0
  288. data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
  289. data/spec/spec_helper.rb +101 -8
  290. data/spec/support/cluster_config.rb +158 -0
  291. data/spec/support/constraints.rb +101 -0
  292. data/spec/support/macros.rb +20 -0
  293. data/spec/support/session_registry.rb +50 -0
  294. data/spec/support/spec_config.rb +42 -0
  295. data.tar.gz.sig +0 -0
  296. metadata +163 -61
  297. metadata.gz.sig +0 -0
  298. data/lib/mongoid/clients/thread_options.rb +0 -19
  299. data/lib/mongoid/extensions/origin/regexp_raw.rb +0 -43
  300. data/lib/mongoid/railties/document.rb +0 -12
  301. data/spec/mongoid/railties/document_spec.rb +0 -24
@@ -7,6 +7,111 @@ describe Mongoid::QueryCache do
7
7
  Mongoid::QueryCache.cache { spec.run }
8
8
  end
9
9
 
10
+ before(:all) do
11
+ # It is likely that there are other session leaks in the driver
12
+ # and/or Mongoid that are unrelated to the query cache. Clear the
13
+ # SessionRegistry at the start of these tests in order to detect leaks that
14
+ # occur only within the scope of these tests.
15
+ #
16
+ # Other session leaks will be detected and addressed as part of RUBY-2391.
17
+ SessionRegistry.instance.clear_registry
18
+ end
19
+
20
+ after do
21
+ SessionRegistry.instance.verify_sessions_ended!
22
+ end
23
+
24
+ context 'when iterating over objects sharing the same base' do
25
+
26
+ let(:server) do
27
+ relations.first.mongo_client.cluster.next_primary
28
+ end
29
+
30
+ before do
31
+ person = Person.create
32
+ 3.times do
33
+ person.send(relation).create
34
+ end
35
+ person.save
36
+ end
37
+
38
+ let!(:relations) do
39
+ Person.first.send(relation).to_a
40
+ end
41
+
42
+ context 'when the association is has-many' do
43
+
44
+ let(:relation) do
45
+ :posts
46
+ end
47
+
48
+ context 'when query cache is disabled' do
49
+
50
+ before do
51
+ Mongoid::QueryCache.enabled = false
52
+ end
53
+
54
+ it 'queries for each access to the base' do
55
+ expect_query(relations.size) do
56
+ relations.each do |object|
57
+ object.person
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ context 'when query cache is enabled' do
64
+
65
+ before do
66
+ Mongoid::QueryCache.enabled = true
67
+ end
68
+
69
+ it 'queries only once for the base' do
70
+ expect_query(1) do
71
+ relations.each do |object|
72
+ object.person
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+
79
+ context 'when the association is embeds-many' do
80
+
81
+ let(:relation) do
82
+ :symptoms
83
+ end
84
+
85
+ context 'when query cache is disabled' do
86
+
87
+ before do
88
+ Mongoid::QueryCache.enabled = false
89
+ end
90
+
91
+ it 'does not query for access to the base' do
92
+ expect(server).to receive(:context).exactly(0).times.and_call_original
93
+ relations.each do |object|
94
+ object.person
95
+ end
96
+ end
97
+ end
98
+
99
+ context 'when query cache is enabled' do
100
+
101
+ before do
102
+ Mongoid::QueryCache.enabled = true
103
+ end
104
+
105
+ it 'does not query for access to the base' do
106
+ expect(server).to receive(:context).exactly(0).times.and_call_original
107
+ relations.each do |object|
108
+ object.person
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+
10
115
  context "when querying for a single document" do
11
116
 
12
117
  [ :first, :one, :last ].each do |method|
@@ -116,6 +221,10 @@ describe Mongoid::QueryCache do
116
221
  end
117
222
 
118
223
  before do
224
+ 10.times do |i|
225
+ game.ratings << Rating.create!(value: i+1)
226
+ end
227
+
119
228
  game.ratings.where(:value.gt => 5).asc(:id).all.to_a
120
229
  end
121
230
 
@@ -123,7 +232,9 @@ describe Mongoid::QueryCache do
123
232
 
124
233
  it "uses the cache" do
125
234
  expect_no_queries do
126
- game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
235
+ result = game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
236
+ expect(result.length).to eq(2)
237
+ expect(result.map { |r| r['value'] }).to eq([6, 7])
127
238
  end
128
239
  end
129
240
  end
@@ -136,14 +247,23 @@ describe Mongoid::QueryCache do
136
247
  end
137
248
 
138
249
  before do
250
+ 10.times do |i|
251
+ game.ratings << Rating.create!(value: i+1)
252
+ end
253
+
139
254
  game.ratings.where(:value.gt => 5).limit(3).asc(:id).all.to_a
140
255
  end
141
256
 
142
257
  context "when the next query has a limit" do
258
+ # Server versions older than 3.2 also perform a killCursors operation,
259
+ # which causes this test to fail.
260
+ min_server_version '3.2'
143
261
 
144
262
  it "queries again" do
145
263
  expect_query(1) do
146
- game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
264
+ result = game.ratings.where(:value.gt => 5).limit(2).asc(:id).to_a
265
+ expect(result.length).to eq(2)
266
+ expect(result.map { |r| r['value'] }).to eq([6, 7])
147
267
  end
148
268
  end
149
269
  end
@@ -152,7 +272,9 @@ describe Mongoid::QueryCache do
152
272
 
153
273
  it "queries again" do
154
274
  expect_query(1) do
155
- game.ratings.where(:value.gt => 5).asc(:id).to_a
275
+ result = game.ratings.where(:value.gt => 5).asc(:id).to_a
276
+ expect(result.length).to eq(5)
277
+ expect(result.map { |r| r['value'] }).to eq([6, 7, 8, 9, 10])
156
278
  end
157
279
  end
158
280
  end
@@ -165,21 +287,34 @@ describe Mongoid::QueryCache do
165
287
  end
166
288
 
167
289
  before do
290
+ 10.times do |i|
291
+ game.ratings << Rating.create!(value: i+1)
292
+ end
293
+
168
294
  game.ratings.where(:value.gt => 5).asc(:id).all.to_a
169
295
  end
170
296
 
171
297
  it "does not query again" do
172
298
  expect_no_queries do
173
- game.ratings.where(:value.gt => 5).asc(:id).first
299
+ result = game.ratings.where(:value.gt => 5).asc(:id).first
300
+ expect(result['value']).to eq(6)
174
301
  end
175
302
  end
176
303
  end
177
304
 
178
305
  context "when limiting the result" do
306
+ before do
307
+ Band.destroy_all
308
+
309
+ 5.times { |i| Band.create!(name: "Band #{i}") }
310
+ Band.all.to_a
311
+ end
179
312
 
180
313
  it "does not query again" do
181
314
  expect_query(0) do
182
- Band.limit(2).all.to_a
315
+ result = Band.limit(2).all.to_a
316
+ expect(result.length).to eq(2)
317
+ expect(result.map { |r| r["name"] }).to eq(["Band 0", "Band 1"])
183
318
  end
184
319
  end
185
320
  end
@@ -187,12 +322,16 @@ describe Mongoid::QueryCache do
187
322
  context "when specifying a different skip value" do
188
323
 
189
324
  before do
190
- Band.limit(2).skip(1).all.to_a
325
+ Band.destroy_all
326
+
327
+ 5.times { |i| Band.create!(name: "Band #{i}") }
191
328
  end
192
329
 
193
330
  it "queries again" do
194
331
  expect_query(1) do
195
- Band.limit(2).skip(3).all.to_a
332
+ result = Band.limit(2).skip(3).all.to_a
333
+ expect(result.length).to eq(2)
334
+ expect(result.map { |r| r["name"] }).to eq(["Band 3", "Band 4"])
196
335
  end
197
336
  end
198
337
  end
@@ -228,6 +367,25 @@ describe Mongoid::QueryCache do
228
367
  end
229
368
  end
230
369
 
370
+ context 'when querying colleciton larger than the batch size' do
371
+ before do
372
+ Band.destroy_all
373
+ 101.times { |i| Band.create!(_id: i) }
374
+ end
375
+
376
+ it 'does not raise an exception when querying multiple times' do
377
+ expect do
378
+ results1 = Band.all.to_a
379
+ expect(results1.length).to eq(101)
380
+ expect(results1.map { |band| band["_id"] }).to eq([*0..100])
381
+
382
+ results2 = Band.all.to_a
383
+ expect(results2.length).to eq(101)
384
+ expect(results2.map { |band| band["_id"] }).to eq([*0..100])
385
+ end.not_to raise_error
386
+ end
387
+ end
388
+
231
389
  context "when query caching is enabled and the batch_size is set" do
232
390
 
233
391
  around(:each) do |example|
@@ -339,15 +497,15 @@ describe Mongoid::QueryCache do
339
497
  context "when querying a very large collection" do
340
498
 
341
499
  before do
342
- 123.times { Band.create! }
500
+ 100.times { Band.create! }
343
501
  end
344
502
 
345
503
  it "returns the right number of records" do
346
- expect(Band.all.to_a.length).to eq(123)
504
+ expect(Band.all.to_a.length).to eq(100)
347
505
  end
348
506
 
349
507
  it "#pluck returns the same count of objects" do
350
- expect(Band.pluck(:name).length).to eq(123)
508
+ expect(Band.pluck(:name).length).to eq(100)
351
509
  end
352
510
 
353
511
  context "when loading all the documents" do
@@ -358,12 +516,12 @@ describe Mongoid::QueryCache do
358
516
 
359
517
  it "caches the complete result of the query" do
360
518
  expect_no_queries do
361
- expect(Band.all.to_a.length).to eq(123)
519
+ expect(Band.all.to_a.length).to eq(100)
362
520
  end
363
521
  end
364
522
 
365
523
  it "returns the same count of objects when using #pluck" do
366
- expect(Band.pluck(:name).length).to eq(123)
524
+ expect(Band.pluck(:name).length).to eq(100)
367
525
  end
368
526
  end
369
527
  end
@@ -728,7 +728,7 @@ describe Mongoid::Relations::Accessors do
728
728
  game.save
729
729
  end
730
730
 
731
- it "keeps the the foreign key as ObjectID" do
731
+ it "keeps the foreign key as ObjectID" do
732
732
  expect(game.reload.person_id).to eq(person.id)
733
733
  end
734
734
  end
@@ -70,13 +70,44 @@ describe Mongoid::Relations::AutoSave do
70
70
 
71
71
  context "when saving a new parent document" do
72
72
 
73
- before do
74
- person.drugs << drug
75
- person.save
73
+ context 'when persistence options are not set on the parent' do
74
+ before do
75
+ person.drugs << drug
76
+ person.save
77
+ end
78
+
79
+ it "saves the relation" do
80
+ expect(drug).to be_persisted
81
+ end
76
82
  end
77
83
 
78
- it "saves the relation" do
79
- expect(drug).to be_persisted
84
+ context 'when persistence options are set on the parent' do
85
+
86
+ let(:other_database) do
87
+ :other
88
+ end
89
+
90
+ after do
91
+ Person.with(database: other_database) do |person_class|
92
+ person_class.delete_all
93
+ end
94
+ Drug.with(database: other_database) do |drug_class|
95
+ drug_class.delete_all
96
+ end
97
+ end
98
+
99
+ before do
100
+ person.with(database: other_database) do |per|
101
+ per.drugs << drug
102
+ per.save
103
+ end
104
+ end
105
+
106
+ it 'saves the relation with the persistence options' do
107
+ Drug.with(database: other_database) do |drug_class|
108
+ expect(drug_class.count).to eq(1)
109
+ end
110
+ end
80
111
  end
81
112
  end
82
113
 
@@ -160,7 +191,9 @@ describe Mongoid::Relations::AutoSave do
160
191
  it "sends one insert" do
161
192
  account.name = "account"
162
193
  expect_query(1) do
163
- person.with(write: {w:0}).save
194
+ person.with(write: {w:0}) do |_person|
195
+ _person.save
196
+ end
164
197
  end
165
198
  end
166
199
  end
@@ -43,11 +43,11 @@ describe Mongoid::Relations::Bindings::Referenced::ManyToMany do
43
43
  end
44
44
 
45
45
  it "syncs the base" do
46
- expect(person).to be_synced("preference_ids")
46
+ expect(person._synced?("preference_ids")).to be(true)
47
47
  end
48
48
 
49
49
  it "syncs the inverse" do
50
- expect(preference_two).to be_synced("person_ids")
50
+ expect(preference_two._synced?("person_ids")).to be(true)
51
51
  end
52
52
  end
53
53
 
@@ -98,11 +98,11 @@ describe Mongoid::Relations::Bindings::Referenced::ManyToMany do
98
98
  end
99
99
 
100
100
  it "syncs the base" do
101
- expect(person).to be_synced("preference_ids")
101
+ expect(person._synced?("preference_ids")).to be(true)
102
102
  end
103
103
 
104
104
  it "syncs the inverse" do
105
- expect(preference).to be_synced("person_ids")
105
+ expect(preference._synced?("person_ids")).to be(true)
106
106
  end
107
107
  end
108
108
 
@@ -185,20 +185,47 @@ describe Mongoid::Relations::Builders do
185
185
 
186
186
  context "when a document already exists" do
187
187
 
188
- let!(:game_two) do
189
- person.create_game(name: "Skyrim")
190
- end
188
+ context "when the relation belongs_to is already set" do
191
189
 
192
- it "replaces the existing document" do
193
- expect(person.game).to eq(game_two)
194
- end
190
+ let!(:game_one) do
191
+ game = person.create_game(name: "Starcraft")
192
+ game.person = person
193
+ end
194
+
195
+ let!(:game_two) do
196
+ person.create_game(name: "Skyrim")
197
+ end
198
+
199
+ it "replaces the existing document" do
200
+ expect(person.game).to eq(game_two)
201
+ end
202
+
203
+ it "persists the change" do
204
+ expect(person.game(true)).to eq(game_two)
205
+ end
195
206
 
196
- it "persists the change" do
197
- expect(person.game(true)).to eq(game_two)
207
+ it "removes the old document from the database" do
208
+ expect(Game.collection.find.count).to eq(1)
209
+ end
198
210
  end
199
211
 
200
- it "removes the old document from the database" do
201
- expect(Game.collection.find.count).to eq(1)
212
+ context 'when the relation belongs_to is not already set' do
213
+
214
+ let!(:game_two) do
215
+ person.create_game(name: "Skyrim")
216
+ end
217
+
218
+ it "replaces the existing document" do
219
+ expect(person.game).to eq(game_two)
220
+ end
221
+
222
+ it "persists the change" do
223
+ expect(person.game(true)).to eq(game_two)
224
+ end
225
+
226
+ it "removes the old document from the database" do
227
+ expect(Game.collection.find.count).to eq(1)
228
+ end
202
229
  end
203
230
  end
204
231
  end
@@ -34,7 +34,7 @@ describe Mongoid::Relations::CounterCache do
34
34
  it "expect to raise an error" do
35
35
  expect {
36
36
  person.reset_counters(:not_exist)
37
- }.to raise_error
37
+ }.to raise_error(NoMethodError)
38
38
  end
39
39
  end
40
40
 
@@ -85,6 +85,26 @@ describe Mongoid::Relations::CounterCache do
85
85
  expect(subscription.reload[:packs_count]).to eq(1)
86
86
  end
87
87
  end
88
+
89
+ context 'when there are persistence options set' do
90
+
91
+ let(:subscription) do
92
+ Subscription.new
93
+ end
94
+
95
+ before do
96
+ subscription.with(collection: 'other') do |sub|
97
+ sub.save
98
+ sub.packs.create
99
+ end
100
+ end
101
+
102
+ it 'applies the persistence options when resetting the counter' do
103
+ subscription.with(collection: 'other') do |sub|
104
+ expect(sub.reload[:packs_count]).to eq(1)
105
+ end
106
+ end
107
+ end
88
108
  end
89
109
 
90
110
  describe ".reset_counters" do
@@ -111,7 +131,7 @@ describe Mongoid::Relations::CounterCache do
111
131
  it "expect to raise an error" do
112
132
  expect {
113
133
  Person.reset_counters "1", :drugs
114
- }.to raise_error
134
+ }.to raise_error(Mongoid::Errors::DocumentNotFound)
115
135
  end
116
136
  end
117
137
 
@@ -124,7 +144,7 @@ describe Mongoid::Relations::CounterCache do
124
144
  it "expect to raise an error" do
125
145
  expect {
126
146
  Person.reset_counters person.id, :not_exist
127
- }.to raise_error
147
+ }.to raise_error(NoMethodError)
128
148
  end
129
149
  end
130
150
 
@@ -256,6 +276,26 @@ describe Mongoid::Relations::CounterCache do
256
276
  expect(person.reload.drugs_count).to eq(3)
257
277
  end
258
278
  end
279
+
280
+ context 'when there are persistence options set' do
281
+
282
+ let(:person) do
283
+ Person.new
284
+ end
285
+
286
+ before do
287
+ person.with(collection: 'other') do |per|
288
+ per.save
289
+ per.drugs.create
290
+ end
291
+ end
292
+
293
+ it 'applies the persistence options when resetting the counter' do
294
+ person.with(collection: 'other') do |per|
295
+ expect(per.drugs_count).to eq(1)
296
+ end
297
+ end
298
+ end
259
299
  end
260
300
 
261
301
  describe "#decrement_counter" do
@@ -286,6 +326,27 @@ describe Mongoid::Relations::CounterCache do
286
326
  expect(person.reload.drugs_count).to eq(0)
287
327
  end
288
328
  end
329
+
330
+ context 'when there are persistence options set' do
331
+
332
+ let(:person) do
333
+ Person.new
334
+ end
335
+
336
+ before do
337
+ person.with(collection: 'other') do |per|
338
+ per.save
339
+ drug = per.drugs.create
340
+ drug.destroy
341
+ end
342
+ end
343
+
344
+ it 'applies the persistence options when resetting the counter' do
345
+ person.with(collection: 'other') do |per|
346
+ expect(per.reload.drugs_count).to eq(0)
347
+ end
348
+ end
349
+ end
289
350
  end
290
351
 
291
352
  describe "#add_counter_cache_callbacks" do
@@ -113,5 +113,21 @@ describe Mongoid::Relations::Eager::HasAndBelongsToMany do
113
113
  end
114
114
  end
115
115
  end
116
+
117
+ context "when some related documents no longer exist" do
118
+ before do
119
+ # Deleting the first one to meet Builders::Referenced::ManyToMany#query?
120
+ House.collection.find(_id: Person.first.house_ids.first).delete_one
121
+ end
122
+
123
+ it "does not accidentally trigger an extra query" do
124
+ expect_query(2) do
125
+ Person.asc(:_id).includes(:houses).each do |person|
126
+ expect(person.houses).to_not be_nil
127
+ expect(person.houses.length).to be(2)
128
+ end
129
+ end
130
+ end
131
+ end
116
132
  end
117
133
  end
@@ -181,6 +181,46 @@ describe Mongoid::Relations::Eager do
181
181
  expect(Mongoid::Relations::Eager::HasAndBelongsToMany).to receive(:new).with([houses_metadata], docs).once.and_call_original
182
182
  context.eager_load(docs)
183
183
  end
184
+
185
+ context 'when one of the eager loading definitions is nested' do
186
+
187
+ before do
188
+ class User
189
+ include Mongoid::Document
190
+ end
191
+
192
+ class Unit
193
+ include Mongoid::Document
194
+ end
195
+
196
+ class Booking
197
+ include Mongoid::Document
198
+ belongs_to :unit
199
+ has_many :vouchers
200
+ end
201
+
202
+ class Voucher
203
+ include Mongoid::Document
204
+ belongs_to :booking
205
+ belongs_to :created_by, class_name: 'User'
206
+ end
207
+ end
208
+
209
+ it 'successfully loads all relations' do
210
+ user = User.create
211
+ unit = Unit.create
212
+ booking = Booking.create(unit: unit)
213
+ Voucher.create(booking: booking, created_by: user)
214
+
215
+ vouchers = Voucher.includes(:created_by, booking: [:unit])
216
+
217
+ vouchers.each do |voucher|
218
+ expect(voucher.created_by).to eql(user)
219
+ expect(voucher.booking).to eql(booking)
220
+ expect(voucher.booking.unit).to eql(unit)
221
+ end
222
+ end
223
+ end
184
224
  end
185
225
 
186
226
  context "when including two of the same relation type" do