mongoid 6.2.1 → 6.3.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 +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
|