mongoid 6.2.1 → 6.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +3 -2
- data.tar.gz.sig +2 -2
- data/lib/mongoid/atomic.rb +3 -3
- data/lib/mongoid/atomic/modifiers.rb +12 -8
- data/lib/mongoid/composable.rb +1 -0
- data/lib/mongoid/contextual/atomic.rb +6 -3
- data/lib/mongoid/contextual/mongo.rb +14 -6
- data/lib/mongoid/factory.rb +2 -1
- data/lib/mongoid/persistence_context.rb +5 -4
- data/lib/mongoid/query_cache.rb +5 -3
- data/lib/mongoid/relations/embedded/batchable.rb +32 -12
- data/lib/mongoid/relations/synchronization.rb +1 -1
- data/lib/mongoid/relations/targets/enumerable.rb +24 -4
- data/lib/mongoid/version.rb +1 -1
- data/spec/app/models/band.rb +1 -0
- data/spec/mongoid/atomic/modifiers_spec.rb +17 -17
- data/spec/mongoid/atomic_spec.rb +17 -17
- data/spec/mongoid/contextual/mongo_spec.rb +70 -0
- data/spec/mongoid/factory_spec.rb +11 -0
- data/spec/mongoid/persistable/savable_spec.rb +2 -2
- data/spec/mongoid/persistable/updatable_spec.rb +2 -2
- data/spec/mongoid/persistence_context_spec.rb +14 -0
- data/spec/mongoid/positional_spec.rb +10 -10
- data/spec/mongoid/relations/macros_spec.rb +20 -0
- data/spec/mongoid/relations/targets/enumerable_spec.rb +108 -0
- data/spec/spec_helper.rb +4 -0
- metadata +460 -460
- metadata.gz.sig +0 -0
data/spec/mongoid/atomic_spec.rb
CHANGED
@@ -76,13 +76,13 @@ describe Mongoid::Atomic do
|
|
76
76
|
person.addresses.build(street: "Oxford St")
|
77
77
|
end
|
78
78
|
|
79
|
-
it "returns a $set and $
|
79
|
+
it "returns a $set and $push for modifications" do
|
80
80
|
expect(person.atomic_updates).to eq(
|
81
81
|
{
|
82
82
|
"$set" => { "title" => "Sir" },
|
83
|
-
"$
|
83
|
+
"$push" => { "addresses" => { '$each' => [
|
84
84
|
{ "_id" => "oxford-st", "street" => "Oxford St" }
|
85
|
-
]}
|
85
|
+
]} }
|
86
86
|
}
|
87
87
|
)
|
88
88
|
end
|
@@ -197,8 +197,8 @@ describe Mongoid::Atomic do
|
|
197
197
|
"addresses.0.street" => "Bond St"
|
198
198
|
},
|
199
199
|
conflicts: {
|
200
|
-
"$
|
201
|
-
"addresses.0.locations" => [{ "_id" => location.id, "name" => "Home" }]
|
200
|
+
"$push" => {
|
201
|
+
"addresses.0.locations" => { '$each' => [{ "_id" => location.id, "name" => "Home" }] }
|
202
202
|
}
|
203
203
|
}
|
204
204
|
}
|
@@ -215,8 +215,8 @@ describe Mongoid::Atomic do
|
|
215
215
|
"addresses.0.street" => "Bond St"
|
216
216
|
},
|
217
217
|
conflicts: {
|
218
|
-
"$
|
219
|
-
"addresses.0.locations" => [{ "_id" => location.id, "name" => "Home" }]
|
218
|
+
"$push" => {
|
219
|
+
"addresses.0.locations" => { '$each' => [{ "_id" => location.id, "name" => "Home" }] }
|
220
220
|
}
|
221
221
|
}
|
222
222
|
}
|
@@ -263,15 +263,15 @@ describe Mongoid::Atomic do
|
|
263
263
|
"addresses.0.street" => "Bond St"
|
264
264
|
},
|
265
265
|
conflicts: {
|
266
|
-
"$
|
267
|
-
"addresses" => [{
|
266
|
+
"$push" => {
|
267
|
+
"addresses" => { '$each' => [{
|
268
268
|
"_id" => new_address.id,
|
269
269
|
"street" => "Another",
|
270
270
|
"locations" => [
|
271
271
|
"_id" => location.id,
|
272
272
|
"name" => "Home"
|
273
273
|
]
|
274
|
-
}]
|
274
|
+
}] }
|
275
275
|
}
|
276
276
|
}
|
277
277
|
}
|
@@ -310,15 +310,15 @@ describe Mongoid::Atomic do
|
|
310
310
|
"$set" => {
|
311
311
|
"title" => "Sir"
|
312
312
|
},
|
313
|
-
"$
|
314
|
-
"addresses" => [{
|
313
|
+
"$push" => {
|
314
|
+
"addresses" => { '$each' => [{
|
315
315
|
"_id" => new_address.id,
|
316
316
|
"street" => "Ipanema",
|
317
317
|
"locations" => [
|
318
318
|
"_id" => location.id,
|
319
319
|
"name" => "Home"
|
320
320
|
]
|
321
|
-
}]
|
321
|
+
}] }
|
322
322
|
},
|
323
323
|
conflicts: {
|
324
324
|
"$set" => { "addresses.0.street"=>"Bond St" }
|
@@ -339,21 +339,21 @@ describe Mongoid::Atomic do
|
|
339
339
|
address.locations.build(name: "Home")
|
340
340
|
end
|
341
341
|
|
342
|
-
it "returns the proper $sets and $
|
342
|
+
it "returns the proper $sets and $pushes for all levels" do
|
343
343
|
expect(person.atomic_updates).to eq(
|
344
344
|
{
|
345
345
|
"$set" => {
|
346
346
|
"title" => "Sir",
|
347
347
|
},
|
348
|
-
"$
|
349
|
-
"addresses" => [{
|
348
|
+
"$push" => {
|
349
|
+
"addresses" => { '$each' => [{
|
350
350
|
"_id" => address.id,
|
351
351
|
"street" => "Another",
|
352
352
|
"locations" => [
|
353
353
|
"_id" => location.id,
|
354
354
|
"name" => "Home"
|
355
355
|
]
|
356
|
-
}]
|
356
|
+
}] }
|
357
357
|
}
|
358
358
|
}
|
359
359
|
)
|
@@ -2094,6 +2094,41 @@ describe Mongoid::Contextual::Mongo do
|
|
2094
2094
|
expect(context.update).to be false
|
2095
2095
|
end
|
2096
2096
|
end
|
2097
|
+
|
2098
|
+
context 'when provided array filters', if: array_filters_supported? do
|
2099
|
+
|
2100
|
+
before do
|
2101
|
+
Band.delete_all
|
2102
|
+
b = Band.new(name: 'Depeche Mode')
|
2103
|
+
b.labels << Label.new(name: 'Warner')
|
2104
|
+
b.labels << Label.new(name: 'Sony')
|
2105
|
+
b.labels << Label.new(name: 'Cbs')
|
2106
|
+
b.save
|
2107
|
+
|
2108
|
+
b = Band.new(name: 'FKA Twigs')
|
2109
|
+
b.labels << Label.new(name: 'Warner')
|
2110
|
+
b.labels << Label.new(name: 'Cbs')
|
2111
|
+
b.save
|
2112
|
+
end
|
2113
|
+
|
2114
|
+
|
2115
|
+
let(:criteria) do
|
2116
|
+
Band.where(name: 'Depeche Mode')
|
2117
|
+
end
|
2118
|
+
|
2119
|
+
let!(:update) do
|
2120
|
+
context.update({ '$set' => { 'labels.$[i].name' => 'Sony' } },
|
2121
|
+
array_filters: [{ 'i.name' => 'Cbs' }])
|
2122
|
+
end
|
2123
|
+
|
2124
|
+
it 'applies the array filters' do
|
2125
|
+
expect(Band.where(name: 'Depeche Mode').first.labels.collect(&:name)).to match_array(['Warner', 'Sony', 'Sony'])
|
2126
|
+
end
|
2127
|
+
|
2128
|
+
it 'does not affect other documents' do
|
2129
|
+
expect(Band.where(name: 'FKA Twigs').first.labels.collect(&:name)).to match_array(['Warner', 'Cbs'])
|
2130
|
+
end
|
2131
|
+
end
|
2097
2132
|
end
|
2098
2133
|
|
2099
2134
|
describe "#update_all" do
|
@@ -2231,6 +2266,41 @@ describe Mongoid::Contextual::Mongo do
|
|
2231
2266
|
expect(context.update_all).to be false
|
2232
2267
|
end
|
2233
2268
|
end
|
2269
|
+
|
2270
|
+
context 'when provided array filters', if: array_filters_supported? do
|
2271
|
+
|
2272
|
+
before do
|
2273
|
+
Band.delete_all
|
2274
|
+
b = Band.new(name: 'Depeche Mode')
|
2275
|
+
b.labels << Label.new(name: 'Warner')
|
2276
|
+
b.labels << Label.new(name: 'Sony')
|
2277
|
+
b.labels << Label.new(name: 'Cbs')
|
2278
|
+
b.save
|
2279
|
+
|
2280
|
+
b = Band.new(name: 'FKA Twigs')
|
2281
|
+
b.labels << Label.new(name: 'Warner')
|
2282
|
+
b.labels << Label.new(name: 'Cbs')
|
2283
|
+
b.save
|
2284
|
+
end
|
2285
|
+
|
2286
|
+
|
2287
|
+
let(:criteria) do
|
2288
|
+
Band.all
|
2289
|
+
end
|
2290
|
+
|
2291
|
+
let!(:update) do
|
2292
|
+
context.update_all({ '$set' => { 'labels.$[i].name' => 'Sony' } },
|
2293
|
+
array_filters: [{ 'i.name' => 'Cbs' }])
|
2294
|
+
end
|
2295
|
+
|
2296
|
+
it 'applies the array filters' do
|
2297
|
+
expect(Band.where(name: 'Depeche Mode').first.labels.collect(&:name)).to match_array(['Warner', 'Sony', 'Sony'])
|
2298
|
+
end
|
2299
|
+
|
2300
|
+
it 'updates all documents' do
|
2301
|
+
expect(Band.where(name: 'FKA Twigs').first.labels.collect(&:name)).to match_array(['Warner', 'Sony'])
|
2302
|
+
end
|
2303
|
+
end
|
2234
2304
|
end
|
2235
2305
|
|
2236
2306
|
describe '#pipeline' do
|
@@ -88,6 +88,17 @@ describe Mongoid::Factory do
|
|
88
88
|
expect(person.title).to eq("Sir")
|
89
89
|
end
|
90
90
|
end
|
91
|
+
|
92
|
+
context "when the type is a symbol" do
|
93
|
+
|
94
|
+
let(:person) do
|
95
|
+
described_class.build(Person, {:_type => "Doctor"})
|
96
|
+
end
|
97
|
+
|
98
|
+
it "instantiates the subclass" do
|
99
|
+
expect(person.class).to eq(Doctor)
|
100
|
+
end
|
101
|
+
end
|
91
102
|
end
|
92
103
|
|
93
104
|
describe ".from_db" do
|
@@ -189,8 +189,8 @@ describe Mongoid::Persistable::Savable do
|
|
189
189
|
"title" => "King",
|
190
190
|
"name.first_name" => "Ryan"
|
191
191
|
},
|
192
|
-
"$
|
193
|
-
"addresses" => [ { "_id" => address.id, "street" => "Bond St" } ]
|
192
|
+
"$push"=> {
|
193
|
+
"addresses" => { '$each' => [ { "_id" => address.id, "street" => "Bond St" } ] }
|
194
194
|
}
|
195
195
|
})
|
196
196
|
end
|
@@ -462,7 +462,7 @@ describe Mongoid::Persistable::Updatable do
|
|
462
462
|
|
463
463
|
it "raises an error" do
|
464
464
|
expect {
|
465
|
-
person.update_attributes(map: { "bad.key" => "value" })
|
465
|
+
person.update_attributes(map: { "$bad.key" => "value" })
|
466
466
|
}.to raise_error(Mongo::Error::OperationFailure)
|
467
467
|
end
|
468
468
|
end
|
@@ -498,7 +498,7 @@ describe Mongoid::Persistable::Updatable do
|
|
498
498
|
|
499
499
|
it "raises an error" do
|
500
500
|
expect {
|
501
|
-
person.send(method, map: { "bad.key" => "value" })
|
501
|
+
person.send(method, map: { "$bad.key" => "value" })
|
502
502
|
}.to raise_error(Mongo::Error::OperationFailure)
|
503
503
|
end
|
504
504
|
end
|
@@ -70,6 +70,20 @@ describe Mongoid::PersistenceContext do
|
|
70
70
|
{ collection: :other }
|
71
71
|
end
|
72
72
|
|
73
|
+
context 'when the method throws an error' do
|
74
|
+
|
75
|
+
let!(:persistence_context) do
|
76
|
+
described_class.set(object, options).tap do |cxt|
|
77
|
+
allow(cxt).to receive(:client).and_raise(Mongoid::Errors::NoClientConfig.new('default'))
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'clears the context anyway' do
|
82
|
+
begin; described_class.clear(object); rescue; end
|
83
|
+
expect(described_class.get(object)).to be(nil)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
73
87
|
context 'when there has been a persistence context set on the current thread' do
|
74
88
|
|
75
89
|
let!(:persistence_context) do
|
@@ -17,8 +17,8 @@ describe Mongoid::Positional do
|
|
17
17
|
"children.0.field" => "value",
|
18
18
|
"children.0.children.1.children.3.field" => "value"
|
19
19
|
},
|
20
|
-
"$
|
21
|
-
"children.0.children.1.children.3.fields" => [ "value", "value" ]
|
20
|
+
"$push" => {
|
21
|
+
"children.0.children.1.children.3.fields" => { '$each' => [ "value", "value" ] }
|
22
22
|
}
|
23
23
|
}
|
24
24
|
end
|
@@ -113,8 +113,8 @@ describe Mongoid::Positional do
|
|
113
113
|
"children.$.field" => "value",
|
114
114
|
"children.0.children.1.children.3.field" => "value"
|
115
115
|
},
|
116
|
-
"$
|
117
|
-
"children.0.children.1.children.3.fields" => [ "value", "value" ]
|
116
|
+
"$push" => {
|
117
|
+
"children.0.children.1.children.3.fields" => { '$each' => [ "value", "value" ] }
|
118
118
|
}
|
119
119
|
}
|
120
120
|
end
|
@@ -141,8 +141,8 @@ describe Mongoid::Positional do
|
|
141
141
|
"children.0.field" => "value",
|
142
142
|
"children.0.children.1.children.3.field" => "value"
|
143
143
|
},
|
144
|
-
"$
|
145
|
-
"children.0.children.1.children.3.fields" => [ "value", "value" ]
|
144
|
+
"$push" => {
|
145
|
+
"children.0.children.1.children.3.fields" => { '$each' => [ "value", "value" ] }
|
146
146
|
}
|
147
147
|
}
|
148
148
|
end
|
@@ -170,8 +170,8 @@ describe Mongoid::Positional do
|
|
170
170
|
"children.$.field" => "value",
|
171
171
|
"children.0.children.1.children.3.field" => "value"
|
172
172
|
},
|
173
|
-
"$
|
174
|
-
"children.0.children.1.children.3.fields" => [ "value", "value" ]
|
173
|
+
"$push" => {
|
174
|
+
"children.0.children.1.children.3.fields" => { '$each' => [ "value", "value" ] }
|
175
175
|
}
|
176
176
|
}
|
177
177
|
end
|
@@ -203,8 +203,8 @@ describe Mongoid::Positional do
|
|
203
203
|
"children.$.field" => "value",
|
204
204
|
"children.0.children.1.children.3.field" => "value"
|
205
205
|
},
|
206
|
-
"$
|
207
|
-
"children.0.children.1.children.3.fields" => [ "value", "value" ]
|
206
|
+
"$push" => {
|
207
|
+
"children.0.children.1.children.3.fields" => { '$each' => [ "value", "value" ] }
|
208
208
|
}
|
209
209
|
}
|
210
210
|
end
|
@@ -20,6 +20,26 @@ describe Mongoid::Relations::Macros do
|
|
20
20
|
klass.validators.clear
|
21
21
|
end
|
22
22
|
|
23
|
+
describe 'Model loading' do
|
24
|
+
|
25
|
+
let(:model_associations) do
|
26
|
+
class TestModel
|
27
|
+
include Mongoid::Document
|
28
|
+
field :associations
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
after do
|
33
|
+
Object.send(:remove_const, :TestModel)
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'prohibits the use of :associations as an attribute' do
|
37
|
+
expect {
|
38
|
+
model_associations
|
39
|
+
}.to raise_exception(Mongoid::Errors::InvalidField)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
23
43
|
describe ".embedded_in" do
|
24
44
|
|
25
45
|
it "defines the macro" do
|
@@ -928,6 +928,60 @@ describe Mongoid::Relations::Targets::Enumerable do
|
|
928
928
|
end
|
929
929
|
end
|
930
930
|
end
|
931
|
+
|
932
|
+
context 'when the id_sort option is none' do
|
933
|
+
|
934
|
+
let(:person) do
|
935
|
+
Person.create
|
936
|
+
end
|
937
|
+
|
938
|
+
let(:criteria) do
|
939
|
+
Post.where(person_id: person.id)
|
940
|
+
end
|
941
|
+
|
942
|
+
let(:enumerable) do
|
943
|
+
described_class.new(criteria)
|
944
|
+
end
|
945
|
+
|
946
|
+
let!(:first_post) do
|
947
|
+
person.posts.create(title: "One")
|
948
|
+
end
|
949
|
+
|
950
|
+
let!(:second_post) do
|
951
|
+
person.posts.create(title: "Two")
|
952
|
+
end
|
953
|
+
|
954
|
+
it 'does not use the sort on id' do
|
955
|
+
expect(enumerable.first(id_sort: :none)).to eq(first_post)
|
956
|
+
end
|
957
|
+
end
|
958
|
+
|
959
|
+
context 'when the id_sort option is not provided' do
|
960
|
+
|
961
|
+
let(:person) do
|
962
|
+
Person.create
|
963
|
+
end
|
964
|
+
|
965
|
+
let(:criteria) do
|
966
|
+
Post.where(person_id: person.id)
|
967
|
+
end
|
968
|
+
|
969
|
+
let(:enumerable) do
|
970
|
+
described_class.new(criteria)
|
971
|
+
end
|
972
|
+
|
973
|
+
let!(:first_post) do
|
974
|
+
person.posts.create(title: "One")
|
975
|
+
end
|
976
|
+
|
977
|
+
let!(:second_post) do
|
978
|
+
person.posts.create(title: "Two")
|
979
|
+
end
|
980
|
+
|
981
|
+
it 'uses the sort on id' do
|
982
|
+
expect(enumerable.first).to eq(first_post)
|
983
|
+
end
|
984
|
+
end
|
931
985
|
end
|
932
986
|
|
933
987
|
describe "#include?" do
|
@@ -1344,6 +1398,60 @@ describe Mongoid::Relations::Targets::Enumerable do
|
|
1344
1398
|
end
|
1345
1399
|
end
|
1346
1400
|
end
|
1401
|
+
|
1402
|
+
context 'when the id_sort option is none' do
|
1403
|
+
|
1404
|
+
let(:person) do
|
1405
|
+
Person.create
|
1406
|
+
end
|
1407
|
+
|
1408
|
+
let(:criteria) do
|
1409
|
+
Post.where(person_id: person.id)
|
1410
|
+
end
|
1411
|
+
|
1412
|
+
let(:enumerable) do
|
1413
|
+
described_class.new(criteria)
|
1414
|
+
end
|
1415
|
+
|
1416
|
+
let!(:first_post) do
|
1417
|
+
person.posts.create(title: "One")
|
1418
|
+
end
|
1419
|
+
|
1420
|
+
let!(:second_post) do
|
1421
|
+
person.posts.create(title: "Two")
|
1422
|
+
end
|
1423
|
+
|
1424
|
+
it 'does not use the sort on id' do
|
1425
|
+
expect(enumerable.last(id_sort: :none)).to eq(first_post)
|
1426
|
+
end
|
1427
|
+
end
|
1428
|
+
|
1429
|
+
context 'when the id_sort option is not provided' do
|
1430
|
+
|
1431
|
+
let(:person) do
|
1432
|
+
Person.create
|
1433
|
+
end
|
1434
|
+
|
1435
|
+
let(:criteria) do
|
1436
|
+
Post.where(person_id: person.id)
|
1437
|
+
end
|
1438
|
+
|
1439
|
+
let(:enumerable) do
|
1440
|
+
described_class.new(criteria)
|
1441
|
+
end
|
1442
|
+
|
1443
|
+
let!(:first_post) do
|
1444
|
+
person.posts.create(title: "One")
|
1445
|
+
end
|
1446
|
+
|
1447
|
+
let!(:second_post) do
|
1448
|
+
person.posts.create(title: "Two")
|
1449
|
+
end
|
1450
|
+
|
1451
|
+
it 'uses the sort on id' do
|
1452
|
+
expect(enumerable.last).to eq(second_post)
|
1453
|
+
end
|
1454
|
+
end
|
1347
1455
|
end
|
1348
1456
|
|
1349
1457
|
describe "#kind_of?" do
|