mongoid 7.2.0 → 7.2.4
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/README.md +1 -1
- data/lib/mongoid/attributes.rb +8 -1
- data/lib/mongoid/criteria/queryable/selector.rb +0 -4
- data/lib/mongoid/document.rb +3 -2
- data/lib/mongoid/errors/mongoid_error.rb +1 -1
- data/lib/mongoid/interceptable.rb +3 -1
- data/lib/mongoid/matcher.rb +19 -43
- data/lib/mongoid/matcher/elem_match.rb +2 -1
- data/lib/mongoid/matcher/expression.rb +5 -14
- data/lib/mongoid/matcher/field_expression.rb +4 -5
- data/lib/mongoid/matcher/field_operator.rb +7 -11
- data/lib/mongoid/reloadable.rb +5 -0
- data/lib/mongoid/validatable/associated.rb +1 -1
- data/lib/mongoid/validatable/presence.rb +3 -3
- data/lib/mongoid/validatable/uniqueness.rb +1 -1
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +1 -1
- data/spec/integration/app_spec.rb +174 -84
- data/spec/integration/callbacks_models.rb +49 -0
- data/spec/integration/callbacks_spec.rb +216 -0
- data/spec/integration/document_spec.rb +21 -0
- data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
- data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
- data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
- data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
- data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
- data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
- data/spec/lite_spec_helper.rb +3 -4
- data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
- data/spec/mongoid/atomic/paths_spec.rb +41 -0
- data/spec/mongoid/attributes_spec.rb +241 -0
- data/spec/mongoid/contextual/atomic_spec.rb +17 -4
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +36 -0
- data/spec/mongoid/document_fields_spec.rb +26 -0
- data/spec/mongoid/document_query_spec.rb +51 -0
- data/spec/mongoid/errors/mongoid_error_spec.rb +20 -8
- data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
- data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
- data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
- data/spec/mongoid/persistable/settable_spec.rb +30 -0
- data/spec/mongoid/persistable_spec.rb +2 -2
- data/spec/shared/bin/get-mongodb-download-url +17 -0
- data/spec/shared/bin/s3-copy +45 -0
- data/spec/shared/bin/s3-upload +69 -0
- data/spec/shared/lib/mrss/cluster_config.rb +226 -0
- data/spec/shared/lib/mrss/constraints.rb +71 -6
- data/spec/shared/lib/mrss/docker_runner.rb +271 -0
- data/spec/shared/lib/mrss/lite_constraints.rb +16 -0
- data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
- data/spec/shared/lib/mrss/spec_organizer.rb +32 -2
- data/spec/shared/lib/mrss/utils.rb +15 -0
- data/spec/shared/share/Dockerfile.erb +322 -0
- data/spec/shared/share/haproxy-1.conf +16 -0
- data/spec/shared/share/haproxy-2.conf +17 -0
- data/spec/shared/shlib/distro.sh +73 -0
- data/spec/shared/shlib/server.sh +317 -0
- data/spec/shared/shlib/set_env.sh +131 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/support/models/customer.rb +11 -0
- data/spec/support/models/customer_address.rb +12 -0
- data/spec/support/models/dictionary.rb +6 -0
- data/spec/support/models/mop.rb +10 -0
- data/spec/support/spec_config.rb +8 -0
- metadata +554 -508
- metadata.gz.sig +3 -2
@@ -0,0 +1,49 @@
|
|
1
|
+
class Galaxy
|
2
|
+
include Mongoid::Document
|
3
|
+
|
4
|
+
field :age, type: Integer
|
5
|
+
|
6
|
+
before_validation :set_age
|
7
|
+
|
8
|
+
embeds_many :stars
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def set_age
|
13
|
+
self.age ||= 100_000
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
class Star
|
18
|
+
include Mongoid::Document
|
19
|
+
|
20
|
+
embedded_in :galaxy
|
21
|
+
|
22
|
+
field :age, type: Integer
|
23
|
+
|
24
|
+
before_validation :set_age
|
25
|
+
|
26
|
+
embeds_many :planets
|
27
|
+
|
28
|
+
private
|
29
|
+
|
30
|
+
def set_age
|
31
|
+
self.age ||= 42_000
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class Planet
|
36
|
+
include Mongoid::Document
|
37
|
+
|
38
|
+
embedded_in :star
|
39
|
+
|
40
|
+
field :age, type: Integer
|
41
|
+
|
42
|
+
before_validation :set_age
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def set_age
|
47
|
+
self.age ||= 2_000
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,216 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
require_relative './callbacks_models'
|
6
|
+
|
7
|
+
describe 'callbacks integration tests' do
|
8
|
+
context 'when modifying attributes in a callback' do
|
9
|
+
|
10
|
+
context 'when creating top-level document' do
|
11
|
+
context 'top level document' do
|
12
|
+
let(:instance) do
|
13
|
+
Galaxy.create!
|
14
|
+
end
|
15
|
+
|
16
|
+
it 'writes the attribute value into the model' do
|
17
|
+
instance.age.should == 100_000
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'persists the attribute value' do
|
21
|
+
Galaxy.find(instance.id).age.should == 100_000
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
context 'embedded document' do
|
26
|
+
shared_examples 'persists the attribute value' do
|
27
|
+
it 'writes the attribute value into the model' do
|
28
|
+
instance.stars.first.age.should == 42_000
|
29
|
+
end
|
30
|
+
|
31
|
+
it 'persists the attribute value' do
|
32
|
+
Galaxy.find(instance.id).stars.first.age.should == 42_000
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'set as a document instance' do
|
37
|
+
let(:instance) do
|
38
|
+
Galaxy.create!(stars: [Star.new])
|
39
|
+
end
|
40
|
+
|
41
|
+
include_examples 'persists the attribute value'
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'set as attributes on parent' do
|
45
|
+
let(:instance) do
|
46
|
+
Galaxy.create!(stars: [{}])
|
47
|
+
end
|
48
|
+
|
49
|
+
include_examples 'persists the attribute value'
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
context 'nested embedded document' do
|
54
|
+
shared_examples 'persists the attribute value' do
|
55
|
+
it 'writes the attribute value into the model' do
|
56
|
+
instance.stars.first.planets.first.age.should == 2_000
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'persists the attribute value' do
|
60
|
+
Galaxy.find(instance.id).stars.first.planets.first.age.should == 2_000
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
context 'set as a document instance' do
|
65
|
+
let(:instance) do
|
66
|
+
Galaxy.create!(stars: [Star.new(
|
67
|
+
planets: [Planet.new],
|
68
|
+
)])
|
69
|
+
end
|
70
|
+
|
71
|
+
include_examples 'persists the attribute value'
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'set as attributes on parent' do
|
75
|
+
let(:instance) do
|
76
|
+
Galaxy.create!(stars: [
|
77
|
+
planets: [{}],
|
78
|
+
])
|
79
|
+
end
|
80
|
+
|
81
|
+
include_examples 'persists the attribute value'
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context 'when updating top-level document via #save' do
|
87
|
+
let!(:instance) do
|
88
|
+
Galaxy.create!
|
89
|
+
end
|
90
|
+
|
91
|
+
context 'embedded document' do
|
92
|
+
shared_examples 'persists the attribute value' do
|
93
|
+
it 'writes the attribute value into the model' do
|
94
|
+
instance.stars.first.age.should == 42_000
|
95
|
+
end
|
96
|
+
|
97
|
+
it 'persists the attribute value' do
|
98
|
+
Galaxy.find(instance.id).stars.first.age.should == 42_000
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
context 'set as a document instance' do
|
103
|
+
before do
|
104
|
+
instance.stars = [Star.new]
|
105
|
+
instance.save!
|
106
|
+
end
|
107
|
+
|
108
|
+
include_examples 'persists the attribute value'
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'set as attributes on parent' do
|
112
|
+
before do
|
113
|
+
instance.stars = [{}]
|
114
|
+
instance.save!
|
115
|
+
end
|
116
|
+
|
117
|
+
include_examples 'persists the attribute value'
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
context 'nested embedded document' do
|
122
|
+
shared_examples 'persists the attribute value' do
|
123
|
+
it 'writes the attribute value into the model' do
|
124
|
+
instance.stars.first.planets.first.age.should == 2_000
|
125
|
+
end
|
126
|
+
|
127
|
+
it 'persists the attribute value' do
|
128
|
+
Galaxy.find(instance.id).stars.first.planets.first.age.should == 2_000
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
context 'set as a document instance' do
|
133
|
+
before do
|
134
|
+
instance.stars = [Star.new(planets: [Planet.new])]
|
135
|
+
instance.save!
|
136
|
+
end
|
137
|
+
|
138
|
+
include_examples 'persists the attribute value'
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'set as attributes on parent' do
|
142
|
+
before do
|
143
|
+
instance.stars = [planets: [{}]]
|
144
|
+
instance.save!
|
145
|
+
end
|
146
|
+
|
147
|
+
include_examples 'persists the attribute value'
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
context 'when updating top-level document via #update_attributes' do
|
153
|
+
let!(:instance) do
|
154
|
+
Galaxy.create!
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'embedded document' do
|
158
|
+
shared_examples 'persists the attribute value' do
|
159
|
+
it 'writes the attribute value into the model' do
|
160
|
+
instance.stars.first.age.should == 42_000
|
161
|
+
end
|
162
|
+
|
163
|
+
it 'persists the attribute value' do
|
164
|
+
Galaxy.find(instance.id).stars.first.age.should == 42_000
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'set as a document instance' do
|
169
|
+
before do
|
170
|
+
instance.update_attributes(stars: [Star.new])
|
171
|
+
end
|
172
|
+
|
173
|
+
include_examples 'persists the attribute value'
|
174
|
+
end
|
175
|
+
|
176
|
+
context 'set as attributes on parent' do
|
177
|
+
before do
|
178
|
+
instance.update_attributes(stars: [{}])
|
179
|
+
end
|
180
|
+
|
181
|
+
include_examples 'persists the attribute value'
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
context 'nested embedded document' do
|
186
|
+
shared_examples 'persists the attribute value' do
|
187
|
+
it 'writes the attribute value into the model' do
|
188
|
+
instance.stars.first.planets.first.age.should == 2_000
|
189
|
+
end
|
190
|
+
|
191
|
+
it 'persists the attribute value' do
|
192
|
+
pending 'MONGOID-4476'
|
193
|
+
|
194
|
+
Galaxy.find(instance.id).stars.first.planets.first.age.should == 2_000
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
context 'set as a document instance' do
|
199
|
+
before do
|
200
|
+
instance.update_attributes(stars: [Star.new(planets: [Planet.new])])
|
201
|
+
end
|
202
|
+
|
203
|
+
include_examples 'persists the attribute value'
|
204
|
+
end
|
205
|
+
|
206
|
+
context 'set as attributes on parent' do
|
207
|
+
before do
|
208
|
+
instance.update_attributes(stars: [planets: [{}]])
|
209
|
+
end
|
210
|
+
|
211
|
+
include_examples 'persists the attribute value'
|
212
|
+
end
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
@@ -19,4 +19,25 @@ describe Mongoid::Document do
|
|
19
19
|
DelegatingPatient.default_client.should be Mongoid.default_client
|
20
20
|
end
|
21
21
|
end
|
22
|
+
|
23
|
+
describe '#reload' do
|
24
|
+
context 'when changing shard key value' do
|
25
|
+
require_topology :sharded
|
26
|
+
|
27
|
+
let(:profile) do
|
28
|
+
# Profile shard_key :name
|
29
|
+
Profile.create!(name: "Alice")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "successfully reloads the document after saving an update to the sharded field" do
|
33
|
+
expect(profile.name).to eq("Alice")
|
34
|
+
profile.name = "Bob"
|
35
|
+
profile.save!
|
36
|
+
|
37
|
+
profile.reload
|
38
|
+
|
39
|
+
expect(profile.name).to eq("Bob")
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
22
43
|
end
|
@@ -361,3 +361,49 @@
|
|
361
361
|
# https://jira.mongodb.org/browse/MONGOID-4908
|
362
362
|
matches: false
|
363
363
|
error: [matcher, driver]
|
364
|
+
|
365
|
+
- name: $elemMatch given as symbol
|
366
|
+
document:
|
367
|
+
tags:
|
368
|
+
- intelligent
|
369
|
+
query:
|
370
|
+
tags:
|
371
|
+
:$elemMatch:
|
372
|
+
$eq: intelligent
|
373
|
+
matches: true
|
374
|
+
|
375
|
+
- name: $elemMatch given as symbol - document does not contain the matched field
|
376
|
+
document:
|
377
|
+
query:
|
378
|
+
tags:
|
379
|
+
:$elemMatch:
|
380
|
+
$eq: intelligent
|
381
|
+
matches: false
|
382
|
+
|
383
|
+
- name: $elemMatch argument operator given as symbol - matches
|
384
|
+
document:
|
385
|
+
tags:
|
386
|
+
- intelligent
|
387
|
+
query:
|
388
|
+
tags:
|
389
|
+
$elemMatch:
|
390
|
+
:$eq: intelligent
|
391
|
+
matches: true
|
392
|
+
|
393
|
+
- name: $elemMatch argument operator given as symbol - does not match
|
394
|
+
document:
|
395
|
+
tags:
|
396
|
+
- intelligent
|
397
|
+
query:
|
398
|
+
tags:
|
399
|
+
$elemMatch:
|
400
|
+
:$eq: intelli
|
401
|
+
matches: false
|
402
|
+
|
403
|
+
- name: $elemMatch argument operator given as symbol - document does not contain the matched field
|
404
|
+
document:
|
405
|
+
query:
|
406
|
+
tags:
|
407
|
+
$elemMatch:
|
408
|
+
:$eq: intelli
|
409
|
+
matches: false
|
@@ -0,0 +1,63 @@
|
|
1
|
+
- name: Date field - matches
|
2
|
+
document:
|
3
|
+
date_field: 2020-12-22
|
4
|
+
query:
|
5
|
+
date_field:
|
6
|
+
$gt: 2020-12-21
|
7
|
+
matches: true
|
8
|
+
|
9
|
+
- name: Date field - does not match
|
10
|
+
document:
|
11
|
+
date_field: 2020-12-21
|
12
|
+
query:
|
13
|
+
date_field:
|
14
|
+
$gt: 2020-12-21
|
15
|
+
matches: false
|
16
|
+
|
17
|
+
- name: Date value in generic field - matches
|
18
|
+
document:
|
19
|
+
field: 2020-12-22
|
20
|
+
query:
|
21
|
+
field:
|
22
|
+
$gt: 2020-12-21
|
23
|
+
matches: true
|
24
|
+
|
25
|
+
- name: Date field - does not match
|
26
|
+
document:
|
27
|
+
field: 2020-12-21
|
28
|
+
query:
|
29
|
+
field:
|
30
|
+
$gt: 2020-12-21
|
31
|
+
matches: false
|
32
|
+
|
33
|
+
- name: Time value in generic field queried by date - matches
|
34
|
+
document:
|
35
|
+
field: 2020-12-22 00:00:00
|
36
|
+
query:
|
37
|
+
field:
|
38
|
+
$gt: 2020-12-21
|
39
|
+
matches: true
|
40
|
+
|
41
|
+
- name: Time value in generic field queried by date - does not match
|
42
|
+
document:
|
43
|
+
field: 2020-12-21 00:00:00
|
44
|
+
query:
|
45
|
+
field:
|
46
|
+
$gt: 2020-12-21
|
47
|
+
matches: false
|
48
|
+
|
49
|
+
- name: Time value in generic field - matches
|
50
|
+
document:
|
51
|
+
field: 2020-12-22 00:00:00
|
52
|
+
query:
|
53
|
+
field:
|
54
|
+
$gt: 2020-12-21 00:00:00
|
55
|
+
matches: true
|
56
|
+
|
57
|
+
- name: Time value in generic field - does not match
|
58
|
+
document:
|
59
|
+
field: 2020-12-21 00:00:00
|
60
|
+
query:
|
61
|
+
field:
|
62
|
+
$gt: 2020-12-21 00:00:00
|
63
|
+
matches: false
|
@@ -0,0 +1,15 @@
|
|
1
|
+
- name: Date field - matches
|
2
|
+
document:
|
3
|
+
date_field: 2020-12-22
|
4
|
+
query:
|
5
|
+
date_field:
|
6
|
+
$gte: 2020-12-21
|
7
|
+
matches: true
|
8
|
+
|
9
|
+
- name: Date field - does not match
|
10
|
+
document:
|
11
|
+
date_field: 2020-12-20
|
12
|
+
query:
|
13
|
+
date_field:
|
14
|
+
$gte: 2020-12-21
|
15
|
+
matches: false
|
@@ -14,3 +14,99 @@
|
|
14
14
|
query:
|
15
15
|
foo.bar: 2
|
16
16
|
matches: true
|
17
|
+
|
18
|
+
- name: numeric key - matches
|
19
|
+
document: &numeric-key
|
20
|
+
foo:
|
21
|
+
'42':
|
22
|
+
bar: 1
|
23
|
+
query:
|
24
|
+
foo.42.bar: 1
|
25
|
+
matches: true
|
26
|
+
|
27
|
+
- name: numeric key - does not match
|
28
|
+
document: *numeric-key
|
29
|
+
query:
|
30
|
+
foo.142.bar: 1
|
31
|
+
matches: false
|
32
|
+
|
33
|
+
- name: array under numeric key - matches
|
34
|
+
document: &numeric-key-array
|
35
|
+
foo:
|
36
|
+
'42':
|
37
|
+
-
|
38
|
+
bar: 1
|
39
|
+
query:
|
40
|
+
foo.42.bar: 1
|
41
|
+
matches: true
|
42
|
+
|
43
|
+
- name: array under numeric key - does not match
|
44
|
+
document: *numeric-key-array
|
45
|
+
query:
|
46
|
+
foo.142.bar: 1
|
47
|
+
matches: false
|
48
|
+
|
49
|
+
- name: numeric key under array - matches
|
50
|
+
document: &array-numeric-key
|
51
|
+
foo:
|
52
|
+
-
|
53
|
+
'42':
|
54
|
+
bar: 1
|
55
|
+
query:
|
56
|
+
foo.42.bar: 1
|
57
|
+
matches: true
|
58
|
+
|
59
|
+
- name: numeric key under array - does not match
|
60
|
+
document: *array-numeric-key
|
61
|
+
query:
|
62
|
+
foo.142.bar: 1
|
63
|
+
matches: false
|
64
|
+
|
65
|
+
- name: numeric key eligible as both array index and hash key - matches array index
|
66
|
+
document: &numeric-key-mixed
|
67
|
+
foo:
|
68
|
+
-
|
69
|
+
'1':
|
70
|
+
bar: 1
|
71
|
+
-
|
72
|
+
'1':
|
73
|
+
bar: 2
|
74
|
+
query:
|
75
|
+
foo.1:
|
76
|
+
'1':
|
77
|
+
bar: 2
|
78
|
+
matches: true
|
79
|
+
|
80
|
+
- name: numeric key eligible as both array index and hash key - does not match array index
|
81
|
+
document: *numeric-key-mixed
|
82
|
+
query:
|
83
|
+
foo.1:
|
84
|
+
# The second array item has bar: 2, bar: 1 is not matched
|
85
|
+
'1':
|
86
|
+
bar: 1
|
87
|
+
matches: false
|
88
|
+
|
89
|
+
- name: numeric key eligible as both array index and hash key - matches hash key
|
90
|
+
document: *numeric-key-mixed
|
91
|
+
query:
|
92
|
+
foo.1:
|
93
|
+
# Both bar: 1 and bar: 2 are ok, 1 in query matches the key under each
|
94
|
+
# array element
|
95
|
+
bar: 2
|
96
|
+
matches: true
|
97
|
+
|
98
|
+
- name: numeric key eligible as both array index and hash key - matches hash key again
|
99
|
+
document: *numeric-key-mixed
|
100
|
+
query:
|
101
|
+
foo.1:
|
102
|
+
# Both bar: 1 and bar: 2 are ok, 1 in query matches the key under each
|
103
|
+
# array element
|
104
|
+
bar: 1
|
105
|
+
matches: true
|
106
|
+
|
107
|
+
- name: numeric key eligible as both array index and hash key - does not match hash key
|
108
|
+
document: *numeric-key-mixed
|
109
|
+
query:
|
110
|
+
foo.0:
|
111
|
+
bar: 2
|
112
|
+
matches: false
|