mongoid 7.0.2 → 7.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (72) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/mongoid/association/referenced/eager.rb +4 -1
  4. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +3 -1
  5. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  6. data/lib/mongoid/association/relatable.rb +90 -10
  7. data/lib/mongoid/clients/options.rb +6 -4
  8. data/lib/mongoid/copyable.rb +2 -2
  9. data/lib/mongoid/criteria/options.rb +2 -2
  10. data/lib/mongoid/criteria/queryable/selectable.rb +33 -6
  11. data/lib/mongoid/document.rb +11 -4
  12. data/lib/mongoid/extensions/big_decimal.rb +1 -1
  13. data/lib/mongoid/extensions/regexp.rb +1 -0
  14. data/lib/mongoid/matchable.rb +3 -1
  15. data/lib/mongoid/matchable/eq.rb +22 -0
  16. data/lib/mongoid/matchable/ne.rb +1 -1
  17. data/lib/mongoid/persistence_context.rb +20 -5
  18. data/lib/mongoid/query_cache.rb +8 -4
  19. data/lib/mongoid/railtie.rb +17 -0
  20. data/lib/mongoid/railties/controller_runtime.rb +86 -0
  21. data/lib/mongoid/scopable.rb +3 -3
  22. data/lib/mongoid/threaded.rb +36 -0
  23. data/lib/mongoid/version.rb +1 -1
  24. data/spec/app/models/minim.rb +7 -0
  25. data/spec/app/models/store_as_dup_test3.rb +7 -0
  26. data/spec/app/models/store_as_dup_test4.rb +7 -0
  27. data/spec/config/mongoid.yml +12 -3
  28. data/spec/integration/associations/belongs_to_spec.rb +13 -0
  29. data/spec/lite_spec_helper.rb +56 -0
  30. data/spec/mongoid/association/referenced/belongs_to/eager_spec.rb +24 -5
  31. data/spec/mongoid/association/referenced/belongs_to_spec.rb +46 -3
  32. data/spec/mongoid/association/referenced/has_and_belongs_to_many/eager_spec.rb +21 -2
  33. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_persistence_spec.rb +56 -0
  34. data/spec/mongoid/association/referenced/has_and_belongs_to_many_models.rb +26 -0
  35. data/spec/mongoid/association/referenced/has_and_belongs_to_many_spec.rb +3 -3
  36. data/spec/mongoid/association/referenced/has_many/proxy_query_spec.rb +23 -0
  37. data/spec/mongoid/association/referenced/has_many_models.rb +37 -0
  38. data/spec/mongoid/association/referenced/has_many_spec.rb +3 -3
  39. data/spec/mongoid/association/referenced/has_one_models.rb +48 -0
  40. data/spec/mongoid/association/referenced/has_one_spec.rb +51 -4
  41. data/spec/mongoid/clients/factory_spec.rb +24 -18
  42. data/spec/mongoid/clients/options_spec.rb +40 -37
  43. data/spec/mongoid/clients_spec.rb +68 -8
  44. data/spec/mongoid/config_spec.rb +3 -1
  45. data/spec/mongoid/contextual/mongo_spec.rb +5 -2
  46. data/spec/mongoid/copyable_spec.rb +40 -6
  47. data/spec/mongoid/copyable_spec_models.rb +17 -0
  48. data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -3
  49. data/spec/mongoid/criteria/queryable/selectable_spec.rb +42 -3
  50. data/spec/mongoid/criteria/queryable/selector_spec.rb +2 -2
  51. data/spec/mongoid/criteria/scopable_spec.rb +81 -0
  52. data/spec/mongoid/criteria_spec.rb +18 -3
  53. data/spec/mongoid/document_spec.rb +81 -2
  54. data/spec/mongoid/extensions/big_decimal_spec.rb +9 -9
  55. data/spec/mongoid/extensions/regexp_spec.rb +23 -0
  56. data/spec/mongoid/fields_spec.rb +1 -1
  57. data/spec/mongoid/findable_spec.rb +1 -1
  58. data/spec/mongoid/matchable/eq_spec.rb +48 -0
  59. data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
  60. data/spec/mongoid/persistence_context_spec.rb +1 -1
  61. data/spec/mongoid/query_cache_spec.rb +59 -6
  62. data/spec/mongoid/scopable_spec.rb +13 -0
  63. data/spec/mongoid/threaded_spec.rb +68 -0
  64. data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
  65. data/spec/spec_helper.rb +35 -25
  66. data/spec/support/constraints.rb +101 -0
  67. data/spec/support/macros.rb +20 -0
  68. data/spec/support/spec_config.rb +39 -0
  69. metadata +471 -460
  70. checksums.yaml.gz.sig +0 -0
  71. data.tar.gz.sig +0 -2
  72. metadata.gz.sig +0 -0
@@ -2,15 +2,13 @@ require "spec_helper"
2
2
 
3
3
  describe Mongoid::Clients::Options do
4
4
 
5
- before(:all) do
6
- class TestModel
7
- include Mongoid::Document
8
- field :name
9
- end
10
- end
11
-
12
- after(:all) do
13
- Object.send(:remove_const, :TestModel)
5
+ before do
6
+ # This test asserts on numbers of open connections,
7
+ # to make these assertions work in jruby we cannot have connections
8
+ # bleeding from one test to another and this includes background SDAM
9
+ # threads in the driver
10
+ Mongoid.disconnect_clients
11
+ Mongoid::Clients.clients.clear
14
12
  end
15
13
 
16
14
  describe '#with', if: non_legacy_server? do
@@ -18,7 +16,7 @@ describe Mongoid::Clients::Options do
18
16
  context 'when passing some options' do
19
17
 
20
18
  let(:persistence_context) do
21
- TestModel.with(options) do |klass|
19
+ Minim.with(options) do |klass|
22
20
  klass.persistence_context
23
21
  end
24
22
  end
@@ -30,13 +28,13 @@ describe Mongoid::Clients::Options do
30
28
  end
31
29
 
32
30
  it 'does not set the options on class level' do
33
- expect(TestModel.persistence_context.client.options['database']).to eq('mongoid_test')
31
+ expect(Minim.persistence_context.client.options['database']).to eq('mongoid_test')
34
32
  end
35
33
 
36
34
  context 'when the options are not valid mongo client options' do
37
35
 
38
36
  let(:persistence_context) do
39
- TestModel.with(invalid_options) do |klass|
37
+ Minim.with(invalid_options) do |klass|
40
38
  klass.persistence_context
41
39
  end
42
40
  end
@@ -51,7 +49,7 @@ describe Mongoid::Clients::Options do
51
49
 
52
50
  it 'clears the persistence context' do
53
51
  begin; persistence_context; rescue Mongoid::Errors::InvalidPersistenceOption; end
54
- expect(TestModel.persistence_context).to eq(Mongoid::PersistenceContext.new(TestModel))
52
+ expect(Minim.persistence_context).to eq(Mongoid::PersistenceContext.new(Minim))
55
53
  end
56
54
  end
57
55
 
@@ -77,14 +75,14 @@ describe Mongoid::Clients::Options do
77
75
  context 'when passing a block', if: testing_locally? do
78
76
 
79
77
  let!(:connections_before) do
80
- TestModel.mongo_client.database.command(serverStatus: 1).first['connections']['current']
78
+ Minim.mongo_client.database.command(serverStatus: 1).first['connections']['current']
81
79
  end
82
80
 
83
81
  let!(:connections_and_cluster_during) do
84
82
  connections = nil
85
- cluster = TestModel.with(options) do |klass|
83
+ cluster = Minim.with(options) do |klass|
86
84
  klass.where(name: 'emily').to_a
87
- connections = TestModel.mongo_client.database.command(serverStatus: 1).first['connections']['current']
85
+ connections = Minim.mongo_client.database.command(serverStatus: 1).first['connections']['current']
88
86
  end
89
87
  [ connections, cluster ]
90
88
  end
@@ -98,15 +96,15 @@ describe Mongoid::Clients::Options do
98
96
  end
99
97
 
100
98
  let(:connections_after) do
101
- TestModel.mongo_client.database.command(serverStatus: 1).first['connections']['current']
99
+ Minim.mongo_client.database.command(serverStatus: 1).first['connections']['current']
102
100
  end
103
101
 
104
102
  let!(:cluster_before) do
105
- TestModel.persistence_context.cluster
103
+ Minim.persistence_context.cluster
106
104
  end
107
105
 
108
106
  let(:cluster_after) do
109
- TestModel.persistence_context.cluster
107
+ Minim.persistence_context.cluster
110
108
  end
111
109
 
112
110
  context 'when the options create a new cluster' do
@@ -145,8 +143,8 @@ describe Mongoid::Clients::Options do
145
143
 
146
144
  let(:config) do
147
145
  {
148
- default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
149
- secondary: { uri: "mongodb://127.0.0.1:27017/secondary-db?connectTimeoutMS=3000" }
146
+ default: { hosts: SpecConfig.instance.addresses, database: database_id },
147
+ secondary: { uri: "mongodb://#{SpecConfig.instance.addresses.first}/secondary-db?connectTimeoutMS=3000" }
150
148
  }
151
149
  end
152
150
 
@@ -159,7 +157,7 @@ describe Mongoid::Clients::Options do
159
157
  end
160
158
 
161
159
  let(:persistence_context) do
162
- TestModel.with(client: :secondary) do |klass|
160
+ Minim.with(client: :secondary) do |klass|
163
161
  klass.persistence_context
164
162
  end
165
163
  end
@@ -192,7 +190,7 @@ describe Mongoid::Clients::Options do
192
190
 
193
191
  let(:context_and_criteria) do
194
192
  collection = nil
195
- cxt = TestModel.with(read_secondary_option) do |klass|
193
+ cxt = Minim.with(read_secondary_option) do |klass|
196
194
  collection = klass.all.collection
197
195
  klass.persistence_context
198
196
  end
@@ -232,11 +230,11 @@ describe Mongoid::Clients::Options do
232
230
  100.times do |i|
233
231
  threads << Thread.new do
234
232
  if i % 2 == 0
235
- TestModel.with(collection: 'British') do |klass|
233
+ Minim.with(collection: 'British') do |klass|
236
234
  klass.create(name: 'realised')
237
235
  end
238
236
  else
239
- TestModel.with(collection: 'American') do |klass|
237
+ Minim.with(collection: 'American') do |klass|
240
238
  klass.create(name: 'realized')
241
239
  end
242
240
  end
@@ -246,13 +244,13 @@ describe Mongoid::Clients::Options do
246
244
  end
247
245
 
248
246
  let(:british_count) do
249
- TestModel.with(collection: 'British') do |klass|
247
+ Minim.with(collection: 'British') do |klass|
250
248
  klass.all.count
251
249
  end
252
250
  end
253
251
 
254
252
  let(:american_count) do
255
- TestModel.with(collection: 'American') do |klass|
253
+ Minim.with(collection: 'American') do |klass|
256
254
  klass.all.count
257
255
  end
258
256
  end
@@ -267,7 +265,7 @@ describe Mongoid::Clients::Options do
267
265
  context 'when passing a persistence context' do
268
266
 
269
267
  let(:instance) do
270
- TestModel.new
268
+ Minim.new
271
269
  end
272
270
 
273
271
  let(:persistence_context) do
@@ -279,7 +277,7 @@ describe Mongoid::Clients::Options do
279
277
  let(:options) { { database: 'other' } }
280
278
 
281
279
  it 'sets the persistence context on the object' do
282
- TestModel.new.with(persistence_context) do |model_instance|
280
+ Minim.new.with(persistence_context) do |model_instance|
283
281
  expect(model_instance.persistence_context.options).to eq(persistence_context.options)
284
282
  end
285
283
  end
@@ -295,7 +293,7 @@ describe Mongoid::Clients::Options do
295
293
  end
296
294
 
297
295
  let(:test_model) do
298
- TestModel.create
296
+ Minim.create
299
297
  end
300
298
 
301
299
  let(:persistence_context) do
@@ -338,8 +336,13 @@ describe Mongoid::Clients::Options do
338
336
 
339
337
  let(:config) do
340
338
  {
341
- default: { hosts: [ "127.0.0.1:27017" ], database: database_id },
342
- secondary: { uri: "mongodb://127.0.0.1:27017/secondary-db" }
339
+ default: { hosts: SpecConfig.instance.addresses, database: database_id },
340
+ secondary: {
341
+ uri: "mongodb://#{SpecConfig.instance.addresses.first}/secondary-db",
342
+ options: {
343
+ server_selection_timeout: 0.5,
344
+ },
345
+ }
343
346
  }
344
347
  end
345
348
 
@@ -442,7 +445,7 @@ describe Mongoid::Clients::Options do
442
445
  before do
443
446
  threads = []
444
447
  100.times do |i|
445
- test_model = TestModel.create
448
+ test_model = Minim.create
446
449
  threads << Thread.new do
447
450
  if i % 2 == 0
448
451
  test_model.with(collection: 'British') do |b|
@@ -461,13 +464,13 @@ describe Mongoid::Clients::Options do
461
464
  end
462
465
 
463
466
  let(:british_count) do
464
- TestModel.with(collection: 'British') do |klass|
467
+ Minim.with(collection: 'British') do |klass|
465
468
  klass.all.count
466
469
  end
467
470
  end
468
471
 
469
472
  let(:american_count) do
470
- TestModel.with(collection: 'British') do |klass|
473
+ Minim.with(collection: 'British') do |klass|
471
474
  klass.all.count
472
475
  end
473
476
  end
@@ -482,7 +485,7 @@ describe Mongoid::Clients::Options do
482
485
  context 'when passing a persistence context' do
483
486
 
484
487
  let(:persistence_context) do
485
- TestModel.with(options) do |klass|
488
+ Minim.with(options) do |klass|
486
489
  klass.persistence_context
487
490
  end
488
491
  end
@@ -490,7 +493,7 @@ describe Mongoid::Clients::Options do
490
493
  let(:options) { { database: 'other' } }
491
494
 
492
495
  it 'sets the persistence context on the object' do
493
- TestModel.with(persistence_context) do |test_model_class|
496
+ Minim.with(persistence_context) do |test_model_class|
494
497
  expect(test_model_class.persistence_context.options).to eq(persistence_context.options)
495
498
  end
496
499
  end
@@ -208,6 +208,72 @@ describe Mongoid::Clients do
208
208
  end
209
209
 
210
210
  it_behaves_like "an overridden collection name at the class level"
211
+
212
+ context 'when nesting #with calls' do
213
+ let(:instance_collection_name) do
214
+ Band.with(collection: "ignore") do |klass|
215
+ Band.with(collection: "artists") do |klass|
216
+ klass.new.collection_name
217
+ end
218
+ end
219
+ end
220
+
221
+ let(:class_collection_name) do
222
+ Band.with(collection: "ignore") do |klass|
223
+ Band.with(collection: "artists") do |klass|
224
+ klass.collection_name
225
+ end
226
+ end
227
+ end
228
+
229
+ it_behaves_like "an overridden collection name at the class level"
230
+ end
231
+
232
+ context 'when outer #with call specifies the collection' do
233
+ use_spec_mongoid_config
234
+
235
+ let(:instance_collection_name) do
236
+ Band.with(collection: "artists") do |klass|
237
+ Band.with(client: :reports) do |klass|
238
+ klass.new.collection_name
239
+ end
240
+ end
241
+ end
242
+
243
+ let(:class_collection_name) do
244
+ Band.with(collection: "artists") do |klass|
245
+ Band.with(client: :reports) do |klass|
246
+ klass.collection_name
247
+ end
248
+ end
249
+ end
250
+
251
+ it_behaves_like "an overridden collection name at the class level"
252
+ end
253
+
254
+ context 'restores outer context in outer block' do
255
+ use_spec_mongoid_config
256
+
257
+ let(:instance_collection_name) do
258
+ Band.with(collection: "artists") do |klass|
259
+ Band.with(collection: "scratch") do |klass|
260
+ # nothing
261
+ end
262
+ klass.new.collection_name
263
+ end
264
+ end
265
+
266
+ let(:class_collection_name) do
267
+ Band.with(collection: "artists") do |klass|
268
+ Band.with(collection: "scratch") do |klass|
269
+ # nothing
270
+ end
271
+ klass.collection_name
272
+ end
273
+ end
274
+
275
+ it_behaves_like "an overridden collection name at the class level"
276
+ end
211
277
  end
212
278
 
213
279
  context "when overriding store_in and persistence options" do
@@ -427,7 +493,7 @@ describe Mongoid::Clients do
427
493
  let(:client_name) { :alternative }
428
494
 
429
495
  before do
430
- Mongoid.clients[client_name] = { database: database_id_alt, hosts: [ "#{HOST}:#{PORT}" ] }
496
+ Mongoid.clients[client_name] = { database: database_id_alt, hosts: SpecConfig.instance.addresses }
431
497
  end
432
498
 
433
499
  after do
@@ -552,20 +618,14 @@ describe Mongoid::Clients do
552
618
  end
553
619
 
554
620
  context "when getting a client by name" do
555
-
556
- let(:file) do
557
- File.join(File.dirname(__FILE__), "..", "config", "mongoid.yml")
558
- end
621
+ use_spec_mongoid_config
559
622
 
560
623
  before do
561
- described_class.clear
562
- Mongoid.load!(file, :test)
563
624
  Band.store_in(client: :reports)
564
625
  end
565
626
 
566
627
  after do
567
628
  mongo_client.close
568
- Mongoid::Config.reset
569
629
  Band.reset_storage_options!
570
630
  end
571
631
 
@@ -370,7 +370,9 @@ describe Mongoid::Config do
370
370
  end
371
371
 
372
372
  it "sets the default hosts" do
373
- expect(default[:hosts]).to eq(["#{HOST}:#{PORT}"])
373
+ expect(default[:hosts]).to eq(SpecConfig.instance.addresses)
374
+ # and make sure the value is not empty
375
+ expect(default[:hosts].first).to include(':')
374
376
  end
375
377
 
376
378
  context "when the default has options" do
@@ -451,7 +451,7 @@ describe Mongoid::Contextual::Mongo do
451
451
  end
452
452
 
453
453
  it "returns the distinct field values" do
454
- expect(context.distinct(:years)).to eq([ 30, 25 ])
454
+ expect(context.distinct(:years).sort).to eq([ 25, 30 ])
455
455
  end
456
456
  end
457
457
 
@@ -1718,6 +1718,9 @@ describe Mongoid::Contextual::Mongo do
1718
1718
  end
1719
1719
 
1720
1720
  context "when limiting is provided" do
1721
+ # map/reduce with limit is not supported on sharded clusters:
1722
+ # https://jira.mongodb.org/browse/SERVER-2099
1723
+ require_topology :single, :replica_set
1721
1724
 
1722
1725
  let(:criteria) do
1723
1726
  Band.limit(1)
@@ -2388,7 +2391,7 @@ describe Mongoid::Contextual::Mongo do
2388
2391
  end
2389
2392
 
2390
2393
  it 'creates a pipeline with the selector as one of the $match criteria' do
2391
- expect(pipeline_match).to include({ :'$text' => { :'$search' => "New Order" } })
2394
+ expect(pipeline_match).to include({ '$text' => { '$search' => "New Order" } })
2392
2395
  end
2393
2396
 
2394
2397
  it 'creates a pipeline with the $exists operator as one of the $match criteria' do
@@ -1,6 +1,8 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require "spec_helper"
3
3
 
4
+ require_relative './copyable_spec_models'
5
+
4
6
  describe Mongoid::Copyable do
5
7
 
6
8
  [ :clone, :dup ].each do |method|
@@ -90,13 +92,45 @@ describe Mongoid::Copyable do
90
92
 
91
93
  context "and dynamic attributes are not set" do
92
94
 
93
- it "clones" do
94
- t = StoreAsDupTest1.new(:name => "hi")
95
- t.build_store_as_dup_test2(:name => "there")
96
- t.save
97
- copy = t.send(method)
98
- expect(copy.store_as_dup_test2.name).to eq(t.store_as_dup_test2.name)
95
+ context 'embeds_one' do
96
+
97
+ it "clones" do
98
+ t = StoreAsDupTest1.new(:name => "hi")
99
+ t.build_store_as_dup_test2(:name => "there")
100
+ t.save
101
+ copy = t.send(method)
102
+ expect(copy.object_id).not_to eq(t.object_id)
103
+ expect(copy.store_as_dup_test2.name).to eq(t.store_as_dup_test2.name)
104
+ end
99
105
  end
106
+
107
+ context 'embeds_many' do
108
+
109
+
110
+ it "clones" do
111
+ t = StoreAsDupTest3.new(:name => "hi")
112
+ t.store_as_dup_test4s << StoreAsDupTest4.new
113
+ t.save
114
+ copy = t.send(method)
115
+ expect(copy.object_id).not_to eq(t.object_id)
116
+ expect(copy.store_as_dup_test4s).not_to be_empty
117
+ expect(copy.store_as_dup_test4s.first.object_id).not_to eq(t.store_as_dup_test4s.first.object_id)
118
+ end
119
+ end
120
+ end
121
+ end
122
+
123
+ context 'nested embeds_many' do
124
+ it 'works' do
125
+ a = CopyableSpec::A.new
126
+ a.locations << CopyableSpec::Location.new
127
+ a.locations.first.buildings << CopyableSpec::Building.new
128
+ a.save!
129
+
130
+ new_a = a.send(method)
131
+
132
+ expect(new_a.locations.length).to be 1
133
+ expect(new_a.locations.first.buildings.length).to be 1
100
134
  end
101
135
  end
102
136
 
@@ -0,0 +1,17 @@
1
+ module CopyableSpec
2
+ class A
3
+ include Mongoid::Document
4
+
5
+ embeds_many :locations
6
+ end
7
+
8
+ class Location
9
+ include Mongoid::Document
10
+
11
+ embeds_many :buildings
12
+ end
13
+
14
+ class Building
15
+ include Mongoid::Document
16
+ end
17
+ end