mongoid 7.0.2 → 7.0.3

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 (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