mongoid 5.1.5 → 5.2.0
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 +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/lib/config/locales/en.yml +15 -0
- data/lib/mongoid.rb +5 -0
- data/lib/mongoid/attributes/dynamic.rb +3 -3
- data/lib/mongoid/clients/factory.rb +2 -0
- data/lib/mongoid/config.rb +1 -0
- data/lib/mongoid/config/options.rb +1 -1
- data/lib/mongoid/contextual/aggregable/mongo.rb +0 -1
- data/lib/mongoid/contextual/map_reduce.rb +20 -97
- data/lib/mongoid/contextual/memory.rb +1 -0
- data/lib/mongoid/contextual/mongo.rb +20 -15
- data/lib/mongoid/criteria.rb +2 -0
- data/lib/mongoid/document.rb +1 -0
- data/lib/mongoid/errors.rb +1 -0
- data/lib/mongoid/errors/in_memory_collation_not_supported.rb +20 -0
- data/lib/mongoid/errors/mongoid_error.rb +1 -1
- data/lib/mongoid/extensions.rb +1 -0
- data/lib/mongoid/extensions/decimal128.rb +39 -0
- data/lib/mongoid/fields/localized.rb +8 -3
- data/lib/mongoid/indexable/validators/options.rb +2 -1
- data/lib/mongoid/persistable/deletable.rb +3 -7
- data/lib/mongoid/persistable/settable.rb +3 -1
- data/lib/mongoid/query_cache.rb +24 -2
- data/lib/mongoid/relations/accessors.rb +1 -1
- data/lib/mongoid/relations/builders.rb +2 -2
- data/lib/mongoid/relations/eager.rb +2 -2
- data/lib/mongoid/relations/reflections.rb +5 -3
- data/lib/mongoid/relations/touchable.rb +1 -1
- data/lib/mongoid/scopable.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +6 -2
- data/spec/app/models/band.rb +1 -0
- data/spec/config/mongoid.yml +5 -0
- data/spec/mongoid/clients/factory_spec.rb +8 -0
- data/spec/mongoid/clients_spec.rb +78 -1
- data/spec/mongoid/config_spec.rb +31 -0
- data/spec/mongoid/contextual/atomic_spec.rb +342 -76
- data/spec/mongoid/contextual/map_reduce_spec.rb +111 -119
- data/spec/mongoid/contextual/memory_spec.rb +316 -56
- data/spec/mongoid/contextual/mongo_spec.rb +391 -11
- data/spec/mongoid/criteria_spec.rb +21 -2
- data/spec/mongoid/extensions/decimal128_spec.rb +44 -0
- data/spec/mongoid/extensions/time_spec.rb +2 -2
- data/spec/mongoid/fields/localized_spec.rb +91 -0
- data/spec/mongoid/indexable_spec.rb +44 -0
- data/spec/mongoid/persistable/settable_spec.rb +44 -0
- data/spec/mongoid/query_cache_spec.rb +86 -0
- data/spec/mongoid/relations/cyclic_spec.rb +22 -0
- data/spec/mongoid/relations/referenced/many_spec.rb +11 -0
- data/spec/mongoid/relations/referenced/many_to_many_spec.rb +11 -0
- data/spec/mongoid/relations/reflections_spec.rb +9 -9
- data/spec/mongoid/scopable_spec.rb +12 -0
- data/spec/spec_helper.rb +9 -0
- metadata +26 -16
- metadata.gz.sig +0 -0
@@ -3078,14 +3078,14 @@ describe Mongoid::Criteria do
|
|
3078
3078
|
context "when not including private methods" do
|
3079
3079
|
|
3080
3080
|
it "returns false" do
|
3081
|
-
expect(criteria).to_not respond_to(:
|
3081
|
+
expect(criteria).to_not respond_to(:initialize_copy)
|
3082
3082
|
end
|
3083
3083
|
end
|
3084
3084
|
|
3085
3085
|
context "when including private methods" do
|
3086
3086
|
|
3087
3087
|
it "returns true" do
|
3088
|
-
expect(criteria.respond_to?(:
|
3088
|
+
expect(criteria.respond_to?(:initialize_copy, true)).to be true
|
3089
3089
|
end
|
3090
3090
|
end
|
3091
3091
|
end
|
@@ -3352,6 +3352,25 @@ describe Mongoid::Criteria do
|
|
3352
3352
|
end
|
3353
3353
|
end
|
3354
3354
|
|
3355
|
+
context "when querying on a BSON::Decimal128", if: decimal128_supported? do
|
3356
|
+
|
3357
|
+
let(:decimal) do
|
3358
|
+
BSON::Decimal128.new("0.0005")
|
3359
|
+
end
|
3360
|
+
|
3361
|
+
let!(:band) do
|
3362
|
+
Band.create(name: "Boards of Canada", decimal: decimal)
|
3363
|
+
end
|
3364
|
+
|
3365
|
+
let(:from_db) do
|
3366
|
+
Band.where(decimal: decimal).first
|
3367
|
+
end
|
3368
|
+
|
3369
|
+
it "finds the document by the big decimal value" do
|
3370
|
+
expect(from_db).to eq(band)
|
3371
|
+
end
|
3372
|
+
end
|
3373
|
+
|
3355
3374
|
context 'when querying on a polymorphic relation' do
|
3356
3375
|
|
3357
3376
|
let(:movie) do
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Mongoid::Extensions::Decimal128 do
|
4
|
+
|
5
|
+
let(:decimal128) do
|
6
|
+
BSON::Decimal128.new("0.0005")
|
7
|
+
end
|
8
|
+
|
9
|
+
describe "#__evolve_decimal128__" do
|
10
|
+
|
11
|
+
it "returns the same instance" do
|
12
|
+
expect(decimal128.__evolve_decimal128__).to be(decimal128)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe ".evolve" do
|
17
|
+
|
18
|
+
context "when provided a single decimal128" do
|
19
|
+
|
20
|
+
let(:evolved) do
|
21
|
+
BSON::Decimal128.evolve(decimal128)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "returns the decimal128" do
|
25
|
+
expect(evolved).to be(decimal128)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when provided an array of decimal128s" do
|
30
|
+
|
31
|
+
let(:other_decimal128) do
|
32
|
+
BSON::Decimal128.new("3.14")
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:evolved) do
|
36
|
+
BSON::ObjectId.evolve([decimal128, other_decimal128])
|
37
|
+
end
|
38
|
+
|
39
|
+
it "returns the array of decimal128s" do
|
40
|
+
expect(evolved).to eq([decimal128, other_decimal128])
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -281,7 +281,7 @@ describe Mongoid::Extensions::Time do
|
|
281
281
|
end
|
282
282
|
|
283
283
|
it "does not alter seconds with fractions" do
|
284
|
-
expect(DateTime.mongoize(
|
284
|
+
expect(DateTime.mongoize(1.11).to_f).to eq(1.11)
|
285
285
|
end
|
286
286
|
|
287
287
|
context "when using the ActiveSupport time zone" do
|
@@ -344,7 +344,7 @@ describe Mongoid::Extensions::Time do
|
|
344
344
|
end
|
345
345
|
|
346
346
|
it "does not alter seconds with fractions" do
|
347
|
-
expect(Time.mongoize(102.
|
347
|
+
expect(Time.mongoize(102.25).to_f).to eq(102.25)
|
348
348
|
end
|
349
349
|
end
|
350
350
|
|
@@ -430,6 +430,97 @@ describe Mongoid::Fields::Localized do
|
|
430
430
|
expect(value).to eq({ "de" => 100 })
|
431
431
|
end
|
432
432
|
end
|
433
|
+
|
434
|
+
context 'when the type is Boolean' do
|
435
|
+
|
436
|
+
before do
|
437
|
+
I18n.enforce_available_locales = false
|
438
|
+
::I18n.locale = :de
|
439
|
+
end
|
440
|
+
|
441
|
+
after do
|
442
|
+
::I18n.locale = :en
|
443
|
+
end
|
444
|
+
|
445
|
+
context "when the value is false" do
|
446
|
+
|
447
|
+
let(:field) do
|
448
|
+
described_class.new(:boolean_value, localize: true, type: Boolean)
|
449
|
+
end
|
450
|
+
|
451
|
+
let(:value) do
|
452
|
+
field.demongoize({ "de" => false })
|
453
|
+
end
|
454
|
+
|
455
|
+
it "returns the boolean value from the set locale" do
|
456
|
+
expect(value).to eq(false)
|
457
|
+
end
|
458
|
+
end
|
459
|
+
|
460
|
+
context "when the value is true" do
|
461
|
+
|
462
|
+
let(:field) do
|
463
|
+
described_class.new(:boolean_value, localize: true, type: Boolean)
|
464
|
+
end
|
465
|
+
|
466
|
+
let(:value) do
|
467
|
+
field.demongoize({"de" => true})
|
468
|
+
end
|
469
|
+
|
470
|
+
it "returns the boolean value from the set locale" do
|
471
|
+
expect(value).to eq(true)
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
475
|
+
context "when fallbacks are defined" do
|
476
|
+
|
477
|
+
before(:all) do
|
478
|
+
require "i18n/backend/fallbacks"
|
479
|
+
I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks)
|
480
|
+
end
|
481
|
+
|
482
|
+
context "when the lookup does not need to use fallbacks" do
|
483
|
+
|
484
|
+
context "when the value is false" do
|
485
|
+
|
486
|
+
before do
|
487
|
+
::I18n.fallbacks[:de] = [:en, :es]
|
488
|
+
end
|
489
|
+
|
490
|
+
let(:field) do
|
491
|
+
described_class.new(:boolean_value, localize: true, type: Boolean)
|
492
|
+
end
|
493
|
+
|
494
|
+
let(:value) do
|
495
|
+
field.demongoize({"de" => false})
|
496
|
+
end
|
497
|
+
|
498
|
+
it "returns the boolean value from the set locale" do
|
499
|
+
expect(value).to eq(false)
|
500
|
+
end
|
501
|
+
end
|
502
|
+
|
503
|
+
context "when the value is true" do
|
504
|
+
|
505
|
+
before do
|
506
|
+
::I18n.fallbacks[:de] = [:en, :es]
|
507
|
+
end
|
508
|
+
|
509
|
+
let(:field) do
|
510
|
+
described_class.new(:boolean_value, localize: true, type: Boolean)
|
511
|
+
end
|
512
|
+
|
513
|
+
let(:value) do
|
514
|
+
field.demongoize({"de" => true})
|
515
|
+
end
|
516
|
+
|
517
|
+
it "returns the boolean value from the set locale" do
|
518
|
+
expect(value).to eq(true)
|
519
|
+
end
|
520
|
+
end
|
521
|
+
end
|
522
|
+
end
|
523
|
+
end
|
433
524
|
end
|
434
525
|
end
|
435
526
|
end
|
@@ -114,6 +114,34 @@ describe Mongoid::Indexable do
|
|
114
114
|
expect(indexes.get(_type: 1)).to_not be_nil
|
115
115
|
end
|
116
116
|
end
|
117
|
+
|
118
|
+
context "when a collation option is specified", if: collation_supported? do
|
119
|
+
|
120
|
+
let(:klass) do
|
121
|
+
Class.new do
|
122
|
+
include Mongoid::Document
|
123
|
+
store_in collection: "test_db_indexes"
|
124
|
+
index({name: 1}, {collation: {locale: 'en_US', strength: 2}})
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
before do
|
129
|
+
klass.create_indexes
|
130
|
+
end
|
131
|
+
|
132
|
+
after do
|
133
|
+
klass.remove_indexes
|
134
|
+
end
|
135
|
+
|
136
|
+
let(:indexes) do
|
137
|
+
klass.collection.indexes
|
138
|
+
end
|
139
|
+
|
140
|
+
it "creates the indexes" do
|
141
|
+
expect(indexes.get("name_1")["collation"]).to_not be_nil
|
142
|
+
expect(indexes.get("name_1")["collation"]["locale"]).to eq('en_US')
|
143
|
+
end
|
144
|
+
end
|
117
145
|
end
|
118
146
|
|
119
147
|
describe ".add_indexes" do
|
@@ -149,6 +177,7 @@ describe Mongoid::Indexable do
|
|
149
177
|
Class.new do
|
150
178
|
include Mongoid::Document
|
151
179
|
field :a, as: :authentication_token
|
180
|
+
store_in collection: :specs
|
152
181
|
end
|
153
182
|
end
|
154
183
|
|
@@ -257,6 +286,21 @@ describe Mongoid::Indexable do
|
|
257
286
|
end
|
258
287
|
end
|
259
288
|
|
289
|
+
context "when providing a collation option", if: collation_supported? do
|
290
|
+
|
291
|
+
before do
|
292
|
+
klass.index({ name: 1 }, collation: { locale: 'en_US', strength: 2 })
|
293
|
+
end
|
294
|
+
|
295
|
+
let(:options) do
|
296
|
+
klass.index_specification(name: 1).options
|
297
|
+
end
|
298
|
+
|
299
|
+
it "sets the index with a collation option" do
|
300
|
+
expect(options).to eq(collation: { locale: 'en_US', strength: 2 })
|
301
|
+
end
|
302
|
+
end
|
303
|
+
|
260
304
|
context "when providing a compound index" do
|
261
305
|
|
262
306
|
before do
|
@@ -263,6 +263,50 @@ describe Mongoid::Persistable::Settable do
|
|
263
263
|
end
|
264
264
|
end
|
265
265
|
|
266
|
+
context 'when the field is a nested hash' do
|
267
|
+
|
268
|
+
context 'when a leaf value in the nested hash is updated' do
|
269
|
+
|
270
|
+
let(:church) do
|
271
|
+
Church.new.tap do |a|
|
272
|
+
a.location = {'address' => {'city' => 'Berlin', 'street' => 'Yorckstr'}}
|
273
|
+
a.name = 'Church1'
|
274
|
+
a.save
|
275
|
+
end
|
276
|
+
end
|
277
|
+
|
278
|
+
before do
|
279
|
+
church.set('location.address.city' => 'Munich')
|
280
|
+
end
|
281
|
+
|
282
|
+
it 'does not reset the nested hash' do
|
283
|
+
expect(church.name).to eq('Church1')
|
284
|
+
expect(church.location).to eql({'address' => {'city' => 'Munich', 'street' => 'Yorckstr'}})
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
|
289
|
+
context 'when the nested hash is many levels deep' do
|
290
|
+
|
291
|
+
let(:church) do
|
292
|
+
Church.new.tap do |a|
|
293
|
+
a.location = {'address' => {'state' => {'address' => {'city' => 'Berlin', 'street' => 'Yorckstr'}}}}
|
294
|
+
a.name = 'Church1'
|
295
|
+
a.save
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
before do
|
300
|
+
church.set('location.address.state.address.city' => 'Munich')
|
301
|
+
end
|
302
|
+
|
303
|
+
it 'does not reset the nested hash' do
|
304
|
+
expect(church.name).to eq('Church1')
|
305
|
+
expect(church.location).to eql({'address' => {'state' => {'address' => {'city' => 'Munich', 'street' => 'Yorckstr'}}}})
|
306
|
+
end
|
307
|
+
end
|
308
|
+
end
|
309
|
+
|
266
310
|
context 'when the field is not already set locally' do
|
267
311
|
|
268
312
|
let(:church) do
|
@@ -75,6 +75,40 @@ describe Mongoid::QueryCache do
|
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
|
+
context 'when the first query has a collation', if: collation_supported? do
|
79
|
+
|
80
|
+
before do
|
81
|
+
Band.where(name: 'DEPECHE MODE').collation(locale: 'en_US', strength: 2).to_a
|
82
|
+
end
|
83
|
+
|
84
|
+
context "when the next query has the same collation" do
|
85
|
+
|
86
|
+
it "uses the cache" do
|
87
|
+
expect_no_queries do
|
88
|
+
Band.where(name: 'DEPECHE MODE').collation(locale: 'en_US', strength: 2).to_a
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context "when the next query does not have the same collation" do
|
94
|
+
|
95
|
+
it "queries again" do
|
96
|
+
expect_query(1) do
|
97
|
+
Band.where(name: 'DEPECHE MODE').collation(locale: 'fr', strength: 2).to_a
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context "when the next query does not have a collation" do
|
103
|
+
|
104
|
+
it "queries again" do
|
105
|
+
expect_query(1) do
|
106
|
+
Band.where(name: 'DEPECHE MODE').to_a
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
78
112
|
context "when the first query has no limit" do
|
79
113
|
|
80
114
|
let(:game) do
|
@@ -173,6 +207,27 @@ describe Mongoid::QueryCache do
|
|
173
207
|
end
|
174
208
|
end
|
175
209
|
|
210
|
+
context "when sorting documents" do
|
211
|
+
before do
|
212
|
+
Band.asc(:id).to_a
|
213
|
+
end
|
214
|
+
|
215
|
+
context "with different selector" do
|
216
|
+
|
217
|
+
it "queries again" do
|
218
|
+
expect_query(1) do
|
219
|
+
Band.desc(:id).to_a
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
it "does not query again" do
|
225
|
+
expect_query(0) do
|
226
|
+
Band.asc(:id).to_a
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
176
231
|
context "when query caching is enabled and the batch_size is set" do
|
177
232
|
|
178
233
|
around(:each) do |example|
|
@@ -250,6 +305,37 @@ describe Mongoid::QueryCache do
|
|
250
305
|
end
|
251
306
|
end
|
252
307
|
|
308
|
+
context "when reloading a document" do
|
309
|
+
|
310
|
+
let!(:band_id) do
|
311
|
+
Band.create.id
|
312
|
+
end
|
313
|
+
|
314
|
+
context 'when query cache is disabled' do
|
315
|
+
|
316
|
+
before do
|
317
|
+
Mongoid::QueryCache.enabled = false
|
318
|
+
end
|
319
|
+
|
320
|
+
it "queries again" do
|
321
|
+
band = Band.find(band_id)
|
322
|
+
expect_query(1) do
|
323
|
+
band.reload
|
324
|
+
end
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
328
|
+
context 'when query cache is enabled' do
|
329
|
+
|
330
|
+
it "queries again" do
|
331
|
+
band = Band.find(band_id)
|
332
|
+
expect_query(1) do
|
333
|
+
band.reload
|
334
|
+
end
|
335
|
+
end
|
336
|
+
end
|
337
|
+
end
|
338
|
+
|
253
339
|
context "when querying a very large collection" do
|
254
340
|
|
255
341
|
before do
|
@@ -21,6 +21,17 @@ describe Mongoid::Relations::Cyclic do
|
|
21
21
|
it "sets cyclic to true" do
|
22
22
|
expect(document.cyclic).to be true
|
23
23
|
end
|
24
|
+
|
25
|
+
context "when a query is executed" do
|
26
|
+
|
27
|
+
before do
|
28
|
+
document.save
|
29
|
+
end
|
30
|
+
|
31
|
+
it "queries the database, not memory" do
|
32
|
+
expect(Role.first).to be_a(Role)
|
33
|
+
end
|
34
|
+
end
|
24
35
|
end
|
25
36
|
|
26
37
|
context "when the name is not inflected easily" do
|
@@ -133,6 +144,17 @@ describe Mongoid::Relations::Cyclic do
|
|
133
144
|
expect(document.class.relations['child_mango']).to be_cascading_callbacks
|
134
145
|
end
|
135
146
|
end
|
147
|
+
|
148
|
+
context "when a query is executed" do
|
149
|
+
|
150
|
+
before do
|
151
|
+
document.save
|
152
|
+
end
|
153
|
+
|
154
|
+
it "queries the database, not memory" do
|
155
|
+
expect(Shelf.first).to be_a(Shelf)
|
156
|
+
end
|
157
|
+
end
|
136
158
|
end
|
137
159
|
|
138
160
|
context "when building a namespaced hierarchy" do
|