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
@@ -2,185 +2,486 @@ require "spec_helper"
2
2
 
3
3
  describe Mongoid::Clients::Options do
4
4
 
5
- describe "#with", if: non_legacy_server? do
5
+ describe '#with', if: non_legacy_server? do
6
6
 
7
- context "when passing some options" do
7
+ context 'when passing some options' do
8
8
 
9
- let(:options) { { database: 'test' } }
10
-
11
- let!(:cluster) do
12
- Band.mongo_client.cluster
9
+ let(:persistence_context) do
10
+ Band.with(options) do |klass|
11
+ klass.persistence_context
12
+ end
13
13
  end
14
14
 
15
- let!(:klass) do
16
- Band.with(options)
15
+ let(:options) { { database: 'other' } }
16
+
17
+ it 'sets the options on the client' do
18
+ expect(persistence_context.client.options['database']).to eq(options[:database])
17
19
  end
18
20
 
19
- it "sets the options into the class" do
20
- expect(klass.persistence_options).to eq(options)
21
+ it 'does not set the options on class level' do
22
+ expect(Band.persistence_context.client.options['database']).to eq('mongoid_test')
21
23
  end
22
24
 
23
- it "sets the options into the instance" do
24
- expect(klass.new.persistence_options).to eq(options)
25
+ context 'when the options are not valid mongo client options' do
26
+
27
+ let(:persistence_context) do
28
+ Band.with(invalid_options) do |klass|
29
+ klass.persistence_context
30
+ end
31
+ end
32
+
33
+ let(:invalid_options) { { bad: 'option' } }
34
+
35
+ it 'raises an error' do
36
+ expect {
37
+ persistence_context
38
+ }.to raise_exception(Mongoid::Errors::InvalidPersistenceOption)
39
+ end
40
+
41
+ it 'clears the persistence context' do
42
+ begin; persistence_context; rescue Mongoid::Errors::InvalidPersistenceOption; end
43
+ expect(Band.persistence_context).to eq(Mongoid::PersistenceContext.new(Band))
44
+ end
25
45
  end
26
46
 
27
- it "doesnt set the options on class level" do
28
- expect(Band.new.persistence_options).to be_nil
47
+ context 'when the options include a collection' do
48
+
49
+ let(:options) { { collection: 'another-collection' } }
50
+
51
+ it 'uses the collection' do
52
+ expect(persistence_context.collection_name).to eq(options[:collection].to_sym)
53
+ expect(persistence_context.collection.name).to eq(options[:collection])
54
+ end
55
+
56
+ it 'does not raise an error' do
57
+ expect(persistence_context.client).to be_a(Mongo::Client)
58
+ end
59
+
60
+ it 'does not include the collection option in the client options' do
61
+ expect(persistence_context.client.options[:collection]).to be_nil
62
+ expect(persistence_context.client.options['collection']).to be_nil
63
+ end
29
64
  end
30
65
 
31
- context 'when passed a block', if: testing_locally? do
66
+ context 'when passing a block', if: testing_locally? do
32
67
 
33
68
  let!(:connections_before) do
34
69
  Band.mongo_client.database.command(serverStatus: 1).first['connections']['current']
35
70
  end
36
71
 
37
- it "can return results" do
38
- Band.create(name: 'emily')
39
- result = Band.with(:read => {:mode => :secondary_preferred}) do |klass|
72
+ let!(:connections_and_cluster_during) do
73
+ connections = nil
74
+ cluster = Band.with(options) do |klass|
40
75
  klass.where(name: 'emily').to_a
76
+ connections = Band.mongo_client.database.command(serverStatus: 1).first['connections']['current']
41
77
  end
42
- expect(result.length).to eq(1)
43
- expect(result.first.name).to eq('emily')
78
+ [ connections, cluster ]
44
79
  end
45
80
 
46
- before do
47
- Band.with(options) do |klass|
48
- klass.where(name: 'emily').to_a
49
- end
81
+ let(:connections_during) do
82
+ connections_and_cluster_during[0]
83
+ end
84
+
85
+ let(:cluster_during) do
86
+ connections_and_cluster_during[1]
50
87
  end
51
88
 
52
89
  let(:connections_after) do
53
90
  Band.mongo_client.database.command(serverStatus: 1).first['connections']['current']
54
91
  end
55
92
 
56
- context 'when a new cluster is created by the driver' do
93
+ let!(:cluster_before) do
94
+ Band.persistence_context.cluster
95
+ end
96
+
97
+ let(:cluster_after) do
98
+ Band.persistence_context.cluster
99
+ end
57
100
 
58
- let(:options) { { connect_timeout: 2 } }
101
+ context 'when the options create a new cluster' do
59
102
 
60
- it 'disconnects the new cluster' do
61
- expect(connections_after).to eq(connections_before)
103
+ let(:options) do
104
+ { connect_timeout: 2 }
105
+ end
106
+
107
+ it 'creates a new cluster' do
108
+ expect(connections_before).to be <(connections_during)
109
+ expect(cluster_before).not_to be(cluster_during)
110
+ end
111
+
112
+ it 'disconnects the new cluster when the block exits' do
113
+ expect(connections_before).to eq(connections_after)
62
114
  end
63
115
  end
64
116
 
65
- context 'when the same cluster is used by the new client' do
117
+ context 'when the options do not create a new cluster' do
66
118
 
67
- let(:options) { { database: 'same-cluster' } }
119
+ let(:options) do
120
+ { database: 'same-cluster' }
121
+ end
122
+
123
+ it 'does not create a new cluster' do
124
+ expect(connections_during).to eq(connections_before)
125
+ end
68
126
 
69
127
  it 'does not disconnect the original cluster' do
70
128
  expect(connections_after).to eq(connections_before)
129
+ expect(cluster_before).to be(cluster_after)
130
+ end
131
+ end
132
+
133
+ context 'when the client options were configured using a uri' do
134
+
135
+ let(:config) do
136
+ {
137
+ default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
138
+ secondary: { uri: "mongodb://127.0.0.1:27017/secondary-db?connectTimeoutMS=3000" }
139
+ }
140
+ end
141
+
142
+ before do
143
+ Mongoid::Config.send(:clients=, config)
144
+ end
145
+
146
+ after do
147
+ persistence_context.client.close
148
+ end
149
+
150
+ let(:persistence_context) do
151
+ Band.with(client: :secondary) do |klass|
152
+ klass.persistence_context
153
+ end
154
+ end
155
+
156
+ it 'uses the database specified in the uri' do
157
+ expect(persistence_context.database_name).to eq('secondary-db')
158
+ expect(persistence_context.client.database.name).to eq('secondary-db')
159
+ end
160
+
161
+ it 'uses the options specified in the uri' do
162
+ expect(persistence_context.client.options[:connect_timeout]).to eq(3)
71
163
  end
72
164
  end
73
165
  end
74
166
 
75
- context "when calling .collection method" do
167
+ context 'when changing the collection' do
76
168
 
77
- before do
78
- klass.collection
169
+ let(:options) do
170
+ { collection: 'other' }
79
171
  end
80
172
 
81
- it "keeps the options" do
82
- expect(klass.persistence_options).to eq(options)
173
+ it 'uses that collection' do
174
+ expect(persistence_context.collection.name).to eq(options[:collection])
83
175
  end
176
+ end
84
177
 
85
- context 'when changing the collection' do
178
+ context 'when returning a criteria' do
86
179
 
87
- let(:options) do
88
- { collection: 'other' }
180
+ shared_context 'applies secondary read preference' do
181
+
182
+ let(:context_and_criteria) do
183
+ collection = nil
184
+ cxt = Band.with(read_secondary_option) do |klass|
185
+ collection = klass.all.collection
186
+ klass.persistence_context
187
+ end
188
+ [ cxt, collection ]
189
+ end
190
+
191
+ let(:persistence_context) do
192
+ context_and_criteria[0]
193
+ end
194
+
195
+ let(:client) do
196
+ context_and_criteria[1].client
89
197
  end
90
198
 
91
- it 'uses that collection' do
92
- expect(klass.collection.name).to eq(options[:collection])
199
+ it 'applies the options to the criteria client' do
200
+ expect(client.options['read']).to eq('mode' => :secondary)
93
201
  end
94
202
  end
203
+
204
+ context 'read: :secondary shorthand' do
205
+ let(:read_secondary_option) { {read: :secondary} }
206
+
207
+ it_behaves_like 'applies secondary read preference'
208
+ end
209
+
210
+ context 'read: {mode: :secondary}' do
211
+ let(:read_secondary_option) { {read: {mode: :secondary}} }
212
+
213
+ it_behaves_like 'applies secondary read preference'
214
+ end
95
215
  end
96
216
 
97
- context "when returning a criteria" do
217
+ context 'when the object is shared between threads' do
98
218
 
99
- let(:criteria) do
100
- klass.all
219
+ before do
220
+ threads = []
221
+ 100.times do |i|
222
+ threads << Thread.new do
223
+ if i % 2 == 0
224
+ Band.with(collection: 'British') do |klass|
225
+ klass.create(name: 'realised')
226
+ end
227
+ else
228
+ Band.with(collection: 'American') do |klass|
229
+ klass.create(name: 'realized')
230
+ end
231
+ end
232
+ end
233
+ end
234
+ threads.collect { |t| t.value }
101
235
  end
102
236
 
103
- it "sets the options into the criteria object" do
104
- expect(criteria.persistence_options).to eq(options)
237
+ let(:british_count) do
238
+ Band.with(collection: 'British') do |klass|
239
+ klass.all.count
240
+ end
105
241
  end
106
242
 
107
- it "doesnt set the options on class level" do
108
- expect(Band.new.persistence_options).to be_nil
243
+ let(:american_count) do
244
+ Band.with(collection: 'American') do |klass|
245
+ klass.all.count
246
+ end
247
+ end
248
+
249
+ it "does not share the persistence options" do
250
+ expect(british_count).to eq(50)
251
+ expect(american_count).to eq(50)
109
252
  end
110
253
  end
111
254
  end
112
- end
113
255
 
114
- describe ".with", if: non_legacy_server? do
256
+ context 'when passing a persistence context' do
115
257
 
116
- let(:options) { { database: 'test' } }
258
+ let(:instance) do
259
+ Band.new
260
+ end
117
261
 
118
- let(:instance) do
119
- Band.new.with(options)
120
- end
262
+ let(:persistence_context) do
263
+ instance.with(options) do |inst|
264
+ inst.persistence_context
265
+ end
266
+ end
121
267
 
122
- it "sets the options into" do
123
- expect(instance.persistence_options).to eq(options)
124
- end
268
+ let(:options) { { database: 'other' } }
125
269
 
126
- it "passes down the options to collection" do
127
- expect(instance.collection.database.name).to eq('test')
270
+ it 'sets the persistence context on the object' do
271
+ Band.new.with(persistence_context) do |band_instance|
272
+ expect(band_instance.persistence_context.options).to eq(persistence_context.options)
273
+ end
274
+ end
128
275
  end
276
+ end
129
277
 
130
- context "when the object is shared between threads" do
131
-
132
- before do
133
- threads = []
134
- doc = Band.create(name: "Beatles")
135
- 100.times do |i|
136
- threads << Thread.new do
137
- if i % 2 == 0
138
- doc.with(nil).set(name: "Rolling Stones")
139
- else
140
- doc.with(options).set(name: "Beatles")
141
- end
278
+ describe '.with', if: non_legacy_server? do
279
+
280
+ context 'when passing some options' do
281
+
282
+ let(:options) do
283
+ { database: 'other' }
284
+ end
285
+
286
+ let(:band) do
287
+ Band.create
288
+ end
289
+
290
+ let(:persistence_context) do
291
+ band.with(options) do |object|
292
+ object.persistence_context
293
+ end
294
+ end
295
+
296
+ it 'sets the options on the client' do
297
+ expect(persistence_context.client.options['database']).to eq(options[:database])
298
+ end
299
+
300
+ it 'does not set the options on instance level' do
301
+ expect(band.persistence_context.client.database.name).to eq('mongoid_test')
302
+ end
303
+
304
+ context 'when the options are not valid mongo client options' do
305
+
306
+ let(:persistence_context) do
307
+ band.with(invalid_options) do |object|
308
+ object.persistence_context
142
309
  end
143
310
  end
144
- threads.join
311
+
312
+ let(:invalid_options) { { bad: 'option' } }
313
+
314
+ it 'raises an error' do
315
+ expect {
316
+ persistence_context
317
+ }.to raise_exception(Mongoid::Errors::InvalidPersistenceOption)
318
+ end
319
+
320
+ it 'clears the persistence context' do
321
+ begin; persistence_context; rescue Mongoid::Errors::InvalidPersistenceOption; end
322
+ expect(band.persistence_context).to eq(Mongoid::PersistenceContext.new(band))
323
+ end
145
324
  end
146
325
 
147
- it "does not share the persistence options" do
148
- expect(Band.persistence_options).to eq(nil)
326
+ context 'when the client options were configured using a uri' do
327
+
328
+ let(:config) do
329
+ {
330
+ default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
331
+ secondary: { uri: "mongodb://127.0.0.1:27017/secondary-db" }
332
+ }
333
+ end
334
+
335
+ before do
336
+ Mongoid::Config.send(:clients=, config)
337
+ end
338
+
339
+ let(:persistence_context) do
340
+ band.with(client: :secondary) do |object|
341
+ object.persistence_context
342
+ end
343
+ end
344
+
345
+ it 'uses the database specified in the uri' do
346
+ expect(persistence_context.database_name).to eq('secondary-db')
347
+ expect(persistence_context.client.database.name).to eq('secondary-db')
348
+ end
149
349
  end
150
- end
151
- end
152
350
 
153
- describe "#persistence_options" do
351
+ context 'when passing a block', if: testing_locally? do
154
352
 
155
- it "touches the thread local" do
156
- expect(Thread.current).to receive(:[]).with("[mongoid][Band]:persistence-options").and_return({foo: :bar})
157
- expect(Band.persistence_options).to eq({foo: :bar})
158
- end
353
+ let!(:connections_before) do
354
+ band.mongo_client.database.command(serverStatus: 1).first['connections']['current']
355
+ end
159
356
 
160
- it "cannot force a value on thread local" do
161
- expect {
162
- Band.set_persistence_options(Band, {})
163
- }.to raise_error(NoMethodError)
164
- end
165
- end
357
+ let(:connections_and_cluster_during) do
358
+ connections = nil
359
+ cluster = band.with(options) do |b|
360
+ b.reload
361
+ connections = band.mongo_client.database.command(serverStatus: 1).first['connections']['current']
362
+ b.persistence_context.cluster
363
+ end
364
+ [ connections, cluster ]
365
+ end
366
+
367
+ let(:connections_during) do
368
+ connections_and_cluster_during[0]
369
+ end
370
+
371
+ let(:cluster_during) do
372
+ connections_and_cluster_during[1]
373
+ end
374
+
375
+ let(:connections_after) do
376
+ band.mongo_client.database.command(serverStatus: 1).first['connections']['current']
377
+ end
378
+
379
+ let!(:cluster_before) do
380
+ band.persistence_context.cluster
381
+ end
382
+
383
+ let(:cluster_after) do
384
+ band.persistence_context.cluster
385
+ end
386
+
387
+ context 'when the options create a new cluster' do
388
+
389
+ let(:options) do
390
+ { connect_timeout: 2 }
391
+ end
392
+
393
+ it 'creates a new cluster' do
394
+ expect(connections_before).to be <(connections_during)
395
+ expect(cluster_before).not_to be(cluster_during)
396
+ end
397
+
398
+ it 'disconnects the new cluster when the block exits' do
399
+ expect(connections_after).to eq(connections_before)
400
+ end
401
+ end
402
+
403
+ context 'when the options do not create a new cluster' do
166
404
 
167
- describe ".persistence_options" do
405
+ let(:options) { { read: :secondary } }
168
406
 
169
- context "when options exist on the current thread" do
407
+ it 'does not create a new cluster' do
408
+ expect(connections_during).to eq(connections_before)
409
+ end
170
410
 
171
- let(:klass) do
172
- Band.with(write: { w: 2 })
411
+ it 'does not disconnect the original cluster' do
412
+ expect(connections_after).to eq(connections_before)
413
+ expect(cluster_before).to be(cluster_after)
414
+ end
415
+ end
173
416
  end
174
417
 
175
- it "returns the options" do
176
- expect(klass.persistence_options).to eq(write: { w: 2 })
418
+ context 'when changing the collection' do
419
+
420
+ let(:options) do
421
+ { collection: 'other' }
422
+ end
423
+
424
+ it 'uses that collection' do
425
+ expect(persistence_context.collection.name).to eq(options[:collection])
426
+ end
427
+ end
428
+
429
+ context 'when the object is shared between threads' do
430
+
431
+ before do
432
+ threads = []
433
+ 100.times do |i|
434
+ band = Band.create
435
+ threads << Thread.new do
436
+ if i % 2 == 0
437
+ band.with(collection: 'British') do |b|
438
+ b.name = 'realised'
439
+ b.upsert
440
+ end
441
+ else
442
+ band.with(collection: 'American') do |b|
443
+ b.name = 'realized'
444
+ b.upsert
445
+ end
446
+ end
447
+ end
448
+ end
449
+ threads.collect { |t| t.value }
450
+ end
451
+
452
+ let(:british_count) do
453
+ Band.with(collection: 'British') do |klass|
454
+ klass.all.count
455
+ end
456
+ end
457
+
458
+ let(:american_count) do
459
+ Band.with(collection: 'British') do |klass|
460
+ klass.all.count
461
+ end
462
+ end
463
+
464
+ it 'does not share the persistence options' do
465
+ expect(british_count).to eq(50)
466
+ expect(american_count).to eq(50)
467
+ end
177
468
  end
178
469
  end
179
470
 
180
- context "when there are no options on the current thread" do
471
+ context 'when passing a persistence context' do
181
472
 
182
- it "returns nil" do
183
- expect(Band.persistence_options).to be_nil
473
+ let(:persistence_context) do
474
+ Band.with(options) do |klass|
475
+ klass.persistence_context
476
+ end
477
+ end
478
+
479
+ let(:options) { { database: 'other' } }
480
+
481
+ it 'sets the persistence context on the object' do
482
+ Band.with(persistence_context) do |band_class|
483
+ expect(band_class.persistence_context.options).to eq(persistence_context.options)
484
+ end
184
485
  end
185
486
  end
186
487
  end