mongoid 6.4.1 → 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.
- checksums.yaml +5 -5
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -3
- data/Rakefile +26 -0
- data/lib/mongoid.rb +1 -1
- data/lib/mongoid/contextual/map_reduce.rb +1 -1
- data/lib/mongoid/criteria/modifiable.rb +12 -2
- data/lib/mongoid/criteria/queryable/selectable.rb +34 -7
- data/lib/mongoid/document.rb +4 -4
- data/lib/mongoid/extensions/big_decimal.rb +1 -1
- data/lib/mongoid/extensions/regexp.rb +1 -0
- data/lib/mongoid/extensions/string.rb +3 -1
- data/lib/mongoid/matchable.rb +3 -0
- data/lib/mongoid/matchable/nor.rb +37 -0
- data/lib/mongoid/persistable/settable.rb +5 -5
- data/lib/mongoid/persistence_context.rb +4 -0
- data/lib/mongoid/query_cache.rb +64 -19
- data/lib/mongoid/railtie.rb +17 -0
- data/lib/mongoid/railties/controller_runtime.rb +86 -0
- data/lib/mongoid/scopable.rb +3 -3
- data/lib/mongoid/threaded.rb +36 -0
- data/lib/mongoid/version.rb +1 -1
- data/spec/app/models/array_field.rb +7 -0
- data/spec/app/models/delegating_patient.rb +16 -0
- data/spec/integration/document_spec.rb +22 -0
- data/spec/mongoid/clients/factory_spec.rb +52 -28
- data/spec/mongoid/clients/options_spec.rb +30 -15
- data/spec/mongoid/clients/sessions_spec.rb +12 -3
- data/spec/mongoid/contextual/geo_near_spec.rb +1 -0
- data/spec/mongoid/contextual/mongo_spec.rb +2 -2
- data/spec/mongoid/criteria/modifiable_spec.rb +59 -10
- data/spec/mongoid/criteria/queryable/extensions/big_decimal_spec.rb +3 -3
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +42 -3
- data/spec/mongoid/criteria/queryable/selector_spec.rb +2 -2
- data/spec/mongoid/criteria/scopable_spec.rb +81 -0
- data/spec/mongoid/criteria_spec.rb +4 -1
- data/spec/mongoid/document_spec.rb +54 -0
- data/spec/mongoid/extensions/big_decimal_spec.rb +9 -9
- data/spec/mongoid/extensions/regexp_spec.rb +23 -0
- data/spec/mongoid/extensions/string_spec.rb +35 -7
- data/spec/mongoid/fields_spec.rb +1 -1
- data/spec/mongoid/findable_spec.rb +1 -1
- data/spec/mongoid/matchable/nor_spec.rb +209 -0
- data/spec/mongoid/matchable_spec.rb +26 -1
- data/spec/mongoid/persistable/incrementable_spec.rb +6 -6
- data/spec/mongoid/persistable/settable_spec.rb +19 -0
- data/spec/mongoid/query_cache_spec.rb +87 -18
- data/spec/mongoid/scopable_spec.rb +13 -0
- data/spec/mongoid/threaded_spec.rb +68 -0
- data/spec/rails/controller_extension/controller_runtime_spec.rb +110 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/cluster_config.rb +158 -0
- data/spec/support/constraints.rb +101 -0
- data/spec/support/macros.rb +20 -0
- data/spec/support/session_registry.rb +50 -0
- data/spec/support/spec_config.rb +42 -0
- metadata +43 -23
- metadata.gz.sig +0 -0
@@ -66,15 +66,15 @@ describe Mongoid::Persistable::Incrementable do
|
|
66
66
|
context "when providing big decimal values" do
|
67
67
|
|
68
68
|
let(:five) do
|
69
|
-
BigDecimal
|
69
|
+
BigDecimal("5.0")
|
70
70
|
end
|
71
71
|
|
72
72
|
let(:neg_ten) do
|
73
|
-
BigDecimal
|
73
|
+
BigDecimal("-10.0")
|
74
74
|
end
|
75
75
|
|
76
76
|
let(:thirty) do
|
77
|
-
BigDecimal
|
77
|
+
BigDecimal("30.0")
|
78
78
|
end
|
79
79
|
|
80
80
|
let!(:inc) do
|
@@ -151,15 +151,15 @@ describe Mongoid::Persistable::Incrementable do
|
|
151
151
|
context "when providing big decimal values" do
|
152
152
|
|
153
153
|
let(:five) do
|
154
|
-
BigDecimal
|
154
|
+
BigDecimal("5.0")
|
155
155
|
end
|
156
156
|
|
157
157
|
let(:neg_ten) do
|
158
|
-
BigDecimal
|
158
|
+
BigDecimal("-10.0")
|
159
159
|
end
|
160
160
|
|
161
161
|
let(:thirty) do
|
162
|
-
BigDecimal
|
162
|
+
BigDecimal("30.0")
|
163
163
|
end
|
164
164
|
|
165
165
|
let!(:inc) do
|
@@ -315,6 +315,25 @@ describe Mongoid::Persistable::Settable do
|
|
315
315
|
end
|
316
316
|
end
|
317
317
|
|
318
|
+
context 'when a leaf value in the nested hash is updated to a number' do
|
319
|
+
|
320
|
+
let(:church) do
|
321
|
+
Church.new.tap do |a|
|
322
|
+
a.location = {'address' => {'city' => 'Berlin', 'street' => 'Yorckstr'}}
|
323
|
+
a.name = 'Church1'
|
324
|
+
a.save
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
before do
|
329
|
+
church.set('location.address.city' => 12345)
|
330
|
+
end
|
331
|
+
|
332
|
+
it 'updates the nested value to the correct value' do
|
333
|
+
expect(church.name).to eq('Church1')
|
334
|
+
expect(church.location).to eql({'address' => {'city' => 12345, 'street' => 'Yorckstr'}})
|
335
|
+
end
|
336
|
+
end
|
318
337
|
|
319
338
|
context 'when the nested hash is many levels deep' do
|
320
339
|
|
@@ -7,6 +7,20 @@ 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
|
+
|
10
24
|
context 'when iterating over objects sharing the same base' do
|
11
25
|
|
12
26
|
let(:server) do
|
@@ -38,9 +52,10 @@ describe Mongoid::QueryCache do
|
|
38
52
|
end
|
39
53
|
|
40
54
|
it 'queries for each access to the base' do
|
41
|
-
|
42
|
-
|
43
|
-
|
55
|
+
expect_query(relations.size) do
|
56
|
+
relations.each do |object|
|
57
|
+
object.person
|
58
|
+
end
|
44
59
|
end
|
45
60
|
end
|
46
61
|
end
|
@@ -52,9 +67,10 @@ describe Mongoid::QueryCache do
|
|
52
67
|
end
|
53
68
|
|
54
69
|
it 'queries only once for the base' do
|
55
|
-
|
56
|
-
|
57
|
-
|
70
|
+
expect_query(1) do
|
71
|
+
relations.each do |object|
|
72
|
+
object.person
|
73
|
+
end
|
58
74
|
end
|
59
75
|
end
|
60
76
|
end
|
@@ -205,6 +221,10 @@ describe Mongoid::QueryCache do
|
|
205
221
|
end
|
206
222
|
|
207
223
|
before do
|
224
|
+
10.times do |i|
|
225
|
+
game.ratings << Rating.create!(value: i+1)
|
226
|
+
end
|
227
|
+
|
208
228
|
game.ratings.where(:value.gt => 5).asc(:id).all.to_a
|
209
229
|
end
|
210
230
|
|
@@ -212,7 +232,9 @@ describe Mongoid::QueryCache do
|
|
212
232
|
|
213
233
|
it "uses the cache" do
|
214
234
|
expect_no_queries do
|
215
|
-
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])
|
216
238
|
end
|
217
239
|
end
|
218
240
|
end
|
@@ -225,14 +247,23 @@ describe Mongoid::QueryCache do
|
|
225
247
|
end
|
226
248
|
|
227
249
|
before do
|
250
|
+
10.times do |i|
|
251
|
+
game.ratings << Rating.create!(value: i+1)
|
252
|
+
end
|
253
|
+
|
228
254
|
game.ratings.where(:value.gt => 5).limit(3).asc(:id).all.to_a
|
229
255
|
end
|
230
256
|
|
231
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'
|
232
261
|
|
233
262
|
it "queries again" do
|
234
263
|
expect_query(1) do
|
235
|
-
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])
|
236
267
|
end
|
237
268
|
end
|
238
269
|
end
|
@@ -241,7 +272,9 @@ describe Mongoid::QueryCache do
|
|
241
272
|
|
242
273
|
it "queries again" do
|
243
274
|
expect_query(1) do
|
244
|
-
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])
|
245
278
|
end
|
246
279
|
end
|
247
280
|
end
|
@@ -254,21 +287,34 @@ describe Mongoid::QueryCache do
|
|
254
287
|
end
|
255
288
|
|
256
289
|
before do
|
290
|
+
10.times do |i|
|
291
|
+
game.ratings << Rating.create!(value: i+1)
|
292
|
+
end
|
293
|
+
|
257
294
|
game.ratings.where(:value.gt => 5).asc(:id).all.to_a
|
258
295
|
end
|
259
296
|
|
260
297
|
it "does not query again" do
|
261
298
|
expect_no_queries do
|
262
|
-
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)
|
263
301
|
end
|
264
302
|
end
|
265
303
|
end
|
266
304
|
|
267
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
|
268
312
|
|
269
313
|
it "does not query again" do
|
270
314
|
expect_query(0) do
|
271
|
-
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"])
|
272
318
|
end
|
273
319
|
end
|
274
320
|
end
|
@@ -276,12 +322,16 @@ describe Mongoid::QueryCache do
|
|
276
322
|
context "when specifying a different skip value" do
|
277
323
|
|
278
324
|
before do
|
279
|
-
Band.
|
325
|
+
Band.destroy_all
|
326
|
+
|
327
|
+
5.times { |i| Band.create!(name: "Band #{i}") }
|
280
328
|
end
|
281
329
|
|
282
330
|
it "queries again" do
|
283
331
|
expect_query(1) do
|
284
|
-
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"])
|
285
335
|
end
|
286
336
|
end
|
287
337
|
end
|
@@ -317,6 +367,25 @@ describe Mongoid::QueryCache do
|
|
317
367
|
end
|
318
368
|
end
|
319
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
|
+
|
320
389
|
context "when query caching is enabled and the batch_size is set" do
|
321
390
|
|
322
391
|
around(:each) do |example|
|
@@ -428,15 +497,15 @@ describe Mongoid::QueryCache do
|
|
428
497
|
context "when querying a very large collection" do
|
429
498
|
|
430
499
|
before do
|
431
|
-
|
500
|
+
100.times { Band.create! }
|
432
501
|
end
|
433
502
|
|
434
503
|
it "returns the right number of records" do
|
435
|
-
expect(Band.all.to_a.length).to eq(
|
504
|
+
expect(Band.all.to_a.length).to eq(100)
|
436
505
|
end
|
437
506
|
|
438
507
|
it "#pluck returns the same count of objects" do
|
439
|
-
expect(Band.pluck(:name).length).to eq(
|
508
|
+
expect(Band.pluck(:name).length).to eq(100)
|
440
509
|
end
|
441
510
|
|
442
511
|
context "when loading all the documents" do
|
@@ -447,12 +516,12 @@ describe Mongoid::QueryCache do
|
|
447
516
|
|
448
517
|
it "caches the complete result of the query" do
|
449
518
|
expect_no_queries do
|
450
|
-
expect(Band.all.to_a.length).to eq(
|
519
|
+
expect(Band.all.to_a.length).to eq(100)
|
451
520
|
end
|
452
521
|
end
|
453
522
|
|
454
523
|
it "returns the same count of objects when using #pluck" do
|
455
|
-
expect(Band.pluck(:name).length).to eq(
|
524
|
+
expect(Band.pluck(:name).length).to eq(100)
|
456
525
|
end
|
457
526
|
end
|
458
527
|
end
|
@@ -1130,6 +1130,19 @@ describe Mongoid::Scopable do
|
|
1130
1130
|
it "sets the threading options" do
|
1131
1131
|
Band.without_default_scope do
|
1132
1132
|
expect(Mongoid::Threaded).to be_executing(:without_default_scope)
|
1133
|
+
expect(Mongoid::Threaded.without_default_scope?(Band)).to be(true)
|
1134
|
+
end
|
1135
|
+
end
|
1136
|
+
|
1137
|
+
it "suppresses default scope on the given model within the given block" do
|
1138
|
+
Appointment.without_default_scope do
|
1139
|
+
expect(Appointment.all.selector).to be_empty
|
1140
|
+
end
|
1141
|
+
end
|
1142
|
+
|
1143
|
+
it "does not affect other models' default scopes within the given block" do
|
1144
|
+
Appointment.without_default_scope do
|
1145
|
+
expect(Audio.all.selector).not_to be_empty
|
1133
1146
|
end
|
1134
1147
|
end
|
1135
1148
|
end
|
@@ -233,4 +233,72 @@ describe Mongoid::Threaded do
|
|
233
233
|
end
|
234
234
|
end
|
235
235
|
end
|
236
|
+
|
237
|
+
describe "#begin_without_default_scope" do
|
238
|
+
|
239
|
+
let(:klass) do
|
240
|
+
Appointment
|
241
|
+
end
|
242
|
+
|
243
|
+
after do
|
244
|
+
described_class.exit_without_default_scope(klass)
|
245
|
+
end
|
246
|
+
|
247
|
+
it "adds the given class to the without_default_scope stack" do
|
248
|
+
described_class.begin_without_default_scope(klass)
|
249
|
+
|
250
|
+
expect(described_class.stack(:without_default_scope)).to include(klass)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
describe "#exit_without_default_scope" do
|
255
|
+
|
256
|
+
let(:klass) do
|
257
|
+
Appointment
|
258
|
+
end
|
259
|
+
|
260
|
+
before do
|
261
|
+
described_class.begin_without_default_scope(klass)
|
262
|
+
end
|
263
|
+
|
264
|
+
it "removes the given class from the without_default_scope stack" do
|
265
|
+
described_class.exit_without_default_scope(klass)
|
266
|
+
|
267
|
+
expect(described_class.stack(:without_default_scope)).not_to include(klass)
|
268
|
+
end
|
269
|
+
end
|
270
|
+
|
271
|
+
describe "#without_default_scope?" do
|
272
|
+
|
273
|
+
let(:klass) do
|
274
|
+
Appointment
|
275
|
+
end
|
276
|
+
|
277
|
+
context "when klass has begun without_default_scope" do
|
278
|
+
|
279
|
+
before do
|
280
|
+
described_class.begin_without_default_scope(klass)
|
281
|
+
end
|
282
|
+
|
283
|
+
after do
|
284
|
+
described_class.exit_without_default_scope(klass)
|
285
|
+
end
|
286
|
+
|
287
|
+
it "returns true" do
|
288
|
+
expect(described_class.without_default_scope?(klass)).to be(true)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
context "when klass has exited without_default_scope" do
|
293
|
+
|
294
|
+
before do
|
295
|
+
described_class.begin_without_default_scope(klass)
|
296
|
+
described_class.exit_without_default_scope(klass)
|
297
|
+
end
|
298
|
+
|
299
|
+
it "returns false" do
|
300
|
+
expect(described_class.without_default_scope?(klass)).to be(false)
|
301
|
+
end
|
302
|
+
end
|
303
|
+
end
|
236
304
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
require "mongoid/railties/controller_runtime"
|
3
|
+
|
4
|
+
describe "Mongoid::Railties::ControllerRuntime" do
|
5
|
+
controller_runtime = Mongoid::Railties::ControllerRuntime
|
6
|
+
collector = controller_runtime::Collector
|
7
|
+
|
8
|
+
def set_metric value
|
9
|
+
Thread.current["Mongoid.controller_runtime"] = value
|
10
|
+
end
|
11
|
+
|
12
|
+
def clear_metric!
|
13
|
+
set_metric 0
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "Collector" do
|
17
|
+
|
18
|
+
it "stores the metric in thread-safe manner" do
|
19
|
+
clear_metric!
|
20
|
+
expect(collector.runtime).to eq(0)
|
21
|
+
set_metric 42
|
22
|
+
expect(collector.runtime).to eq(42)
|
23
|
+
end
|
24
|
+
|
25
|
+
it "sets metric on both succeeded and failed" do
|
26
|
+
instance = collector.new
|
27
|
+
event_payload = OpenStruct.new duration: 42
|
28
|
+
|
29
|
+
clear_metric!
|
30
|
+
instance.succeeded event_payload
|
31
|
+
expect(collector.runtime).to eq(42)
|
32
|
+
|
33
|
+
clear_metric!
|
34
|
+
instance.failed event_payload
|
35
|
+
expect(collector.runtime).to eq(42)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "resets the metric and returns the value" do
|
39
|
+
clear_metric!
|
40
|
+
expect(collector.reset_runtime).to eq(0)
|
41
|
+
set_metric 42
|
42
|
+
expect(collector.reset_runtime).to eq(42)
|
43
|
+
expect(collector.runtime).to eq(0)
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
reference_controller_class = Class.new do
|
49
|
+
def process_action *_
|
50
|
+
@process_action = true
|
51
|
+
end
|
52
|
+
|
53
|
+
def cleanup_view_runtime *_
|
54
|
+
@cleanup_view_runtime.call
|
55
|
+
end
|
56
|
+
|
57
|
+
def append_info_to_payload *_
|
58
|
+
@append_info_to_payload = true
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.log_process_action *_
|
62
|
+
@log_process_action.call
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
controller_class = Class.new reference_controller_class do
|
67
|
+
include controller_runtime::ControllerExtension
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:controller){ controller_class.new }
|
71
|
+
|
72
|
+
it "resets the metric before each action" do
|
73
|
+
set_metric 42
|
74
|
+
controller.send(:process_action, 'foo')
|
75
|
+
expect(collector.runtime).to be(0)
|
76
|
+
expect(controller.instance_variable_get "@process_action").to be(true)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "strips the metric of other sources of the runtime" do
|
80
|
+
set_metric 1
|
81
|
+
controller.instance_variable_set "@cleanup_view_runtime", ->{
|
82
|
+
controller.instance_variable_set "@cleanup_view_runtime", true
|
83
|
+
set_metric 13
|
84
|
+
42
|
85
|
+
}
|
86
|
+
returned = controller.send :cleanup_view_runtime
|
87
|
+
expect(controller.instance_variable_get "@cleanup_view_runtime").to be(true)
|
88
|
+
expect(controller.mongoid_runtime).to eq(14)
|
89
|
+
expect(returned).to be(29)
|
90
|
+
end
|
91
|
+
|
92
|
+
it "appends the metric to payload" do
|
93
|
+
payload = {}
|
94
|
+
set_metric 42
|
95
|
+
controller.send :append_info_to_payload, payload
|
96
|
+
expect(controller.instance_variable_get "@append_info_to_payload").to be(true)
|
97
|
+
expect(payload[:mongoid_runtime]).to eq(42)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "adds metric to log message" do
|
101
|
+
controller_class.instance_variable_set "@log_process_action", ->{
|
102
|
+
controller_class.instance_variable_set "@log_process_action", true
|
103
|
+
[]
|
104
|
+
}
|
105
|
+
messages = controller_class.log_process_action mongoid_runtime: 42.101
|
106
|
+
expect(controller_class.instance_variable_get "@log_process_action").to be(true)
|
107
|
+
expect(messages).to eq(["MongoDB: 42.1ms"])
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|