mongoid 6.4.1 → 6.4.8
Sign up to get free protection for your applications and to get access to all the features.
- 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
|