mongoid 7.2.3 → 7.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 +0 -0
- data.tar.gz.sig +0 -0
- data/Rakefile +16 -0
- data/lib/config/locales/en.yml +2 -2
- data/lib/mongoid/association/accessors.rb +1 -1
- data/lib/mongoid/association/constrainable.rb +1 -1
- data/lib/mongoid/association/depending.rb +4 -4
- data/lib/mongoid/association/embedded/batchable.rb +1 -1
- data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
- data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
- data/lib/mongoid/association/nested/many.rb +1 -1
- data/lib/mongoid/association/nested/one.rb +4 -2
- data/lib/mongoid/association/proxy.rb +6 -1
- data/lib/mongoid/association/referenced/auto_save.rb +2 -2
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
- data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
- data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
- data/lib/mongoid/attributes.rb +24 -13
- data/lib/mongoid/attributes/projector.rb +120 -0
- data/lib/mongoid/cacheable.rb +2 -2
- data/lib/mongoid/clients.rb +1 -1
- data/lib/mongoid/clients/factory.rb +22 -8
- data/lib/mongoid/config.rb +19 -2
- data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
- data/lib/mongoid/copyable.rb +1 -1
- data/lib/mongoid/criteria.rb +4 -5
- data/lib/mongoid/criteria/findable.rb +1 -1
- data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
- data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
- data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
- data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
- data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
- data/lib/mongoid/document.rb +1 -15
- data/lib/mongoid/errors/delete_restriction.rb +8 -9
- data/lib/mongoid/evolvable.rb +1 -1
- data/lib/mongoid/extensions/boolean.rb +1 -2
- data/lib/mongoid/extensions/false_class.rb +1 -1
- data/lib/mongoid/extensions/hash.rb +2 -2
- data/lib/mongoid/extensions/true_class.rb +1 -1
- data/lib/mongoid/fields.rb +43 -5
- data/lib/mongoid/inspectable.rb +1 -1
- data/lib/mongoid/matcher.rb +7 -0
- data/lib/mongoid/matcher/bits.rb +41 -0
- data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_all_set.rb +20 -0
- data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
- data/lib/mongoid/matcher/bits_any_set.rb +20 -0
- data/lib/mongoid/matcher/expression.rb +4 -0
- data/lib/mongoid/matcher/field_operator.rb +6 -0
- data/lib/mongoid/matcher/mod.rb +17 -0
- data/lib/mongoid/matcher/type.rb +99 -0
- data/lib/mongoid/persistable/deletable.rb +1 -2
- data/lib/mongoid/persistable/destroyable.rb +8 -2
- data/lib/mongoid/persistable/updatable.rb +27 -2
- data/lib/mongoid/query_cache.rb +35 -29
- data/lib/mongoid/selectable.rb +5 -7
- data/lib/mongoid/shardable.rb +21 -5
- data/lib/mongoid/touchable.rb +23 -4
- data/lib/mongoid/version.rb +1 -1
- data/spec/integration/associations/embeds_many_spec.rb +44 -0
- data/spec/integration/associations/has_one_spec.rb +48 -0
- data/spec/integration/criteria/date_field_spec.rb +1 -1
- data/spec/integration/document_spec.rb +9 -0
- data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
- data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
- data/spec/integration/matcher_operator_data/comment.yml +22 -0
- data/spec/integration/matcher_operator_data/in.yml +16 -0
- data/spec/integration/matcher_operator_data/mod.yml +55 -0
- data/spec/integration/matcher_operator_data/type.yml +70 -0
- data/spec/integration/matcher_operator_data/type_array.yml +16 -0
- data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
- data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
- data/spec/integration/matcher_operator_data/type_code.yml +26 -0
- data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
- data/spec/integration/matcher_operator_data/type_date.yml +39 -0
- data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
- data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
- data/spec/integration/matcher_operator_data/type_double.yml +15 -0
- data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
- data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
- data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
- data/spec/integration/matcher_operator_data/type_null.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object.yml +23 -0
- data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
- data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
- data/spec/integration/matcher_operator_data/type_string.yml +15 -0
- data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
- data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
- data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
- data/spec/lite_spec_helper.rb +2 -0
- data/spec/mongoid/association/depending_spec.rb +391 -352
- data/spec/mongoid/association/nested/one_spec.rb +18 -14
- data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
- data/spec/mongoid/association/referenced/has_one_models.rb +8 -0
- data/spec/mongoid/atomic/paths_spec.rb +64 -12
- data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
- data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
- data/spec/mongoid/attributes/projector_spec.rb +41 -0
- data/spec/mongoid/attributes_spec.rb +98 -6
- data/spec/mongoid/clients/factory_spec.rb +48 -0
- data/spec/mongoid/config_spec.rb +32 -0
- data/spec/mongoid/contextual/mongo_spec.rb +2 -2
- data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
- data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
- data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
- data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +229 -24
- data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
- data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
- data/spec/mongoid/criteria_projection_spec.rb +411 -0
- data/spec/mongoid/criteria_spec.rb +0 -275
- data/spec/mongoid/document_spec.rb +13 -13
- data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
- data/spec/mongoid/extensions/false_class_spec.rb +1 -1
- data/spec/mongoid/extensions/string_spec.rb +5 -5
- data/spec/mongoid/extensions/true_class_spec.rb +1 -1
- data/spec/mongoid/fields/localized_spec.rb +4 -4
- data/spec/mongoid/fields_spec.rb +4 -4
- data/spec/mongoid/inspectable_spec.rb +12 -4
- data/spec/mongoid/persistable/deletable_spec.rb +175 -1
- data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
- data/spec/mongoid/persistable/savable_spec.rb +3 -5
- data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
- data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
- data/spec/mongoid/reloadable_spec.rb +18 -1
- data/spec/mongoid/shardable_spec.rb +44 -0
- data/spec/mongoid/touchable_spec.rb +104 -16
- data/spec/mongoid/touchable_spec_models.rb +52 -0
- data/spec/mongoid/validatable_spec.rb +1 -1
- data/spec/spec_helper.rb +6 -2
- data/spec/support/client_registry.rb +9 -0
- data/spec/support/models/bolt.rb +8 -0
- data/spec/support/models/hole.rb +13 -0
- data/spec/support/models/mop.rb +0 -1
- data/spec/support/models/nut.rb +8 -0
- data/spec/support/models/person.rb +6 -0
- data/spec/support/models/sealer.rb +8 -0
- data/spec/support/models/shirt.rb +12 -0
- data/spec/support/models/spacer.rb +8 -0
- data/spec/support/models/threadlocker.rb +8 -0
- data/spec/support/models/washer.rb +8 -0
- metadata +97 -3
- metadata.gz.sig +5 -3
- data/spec/support/cluster_config.rb +0 -158
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
# encoding: utf-8
|
|
3
|
+
|
|
4
|
+
require "spec_helper"
|
|
5
|
+
|
|
6
|
+
describe Mongoid::Criteria do
|
|
7
|
+
|
|
8
|
+
describe "#only" do
|
|
9
|
+
|
|
10
|
+
let!(:band) do
|
|
11
|
+
Band.create(name: "Depeche Mode", likes: 3, views: 10)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
context "when not using inheritance" do
|
|
15
|
+
|
|
16
|
+
context "when passing splat args" do
|
|
17
|
+
|
|
18
|
+
let(:criteria) do
|
|
19
|
+
Band.only(:_id)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "limits the returned fields" do
|
|
23
|
+
expect {
|
|
24
|
+
criteria.first.name
|
|
25
|
+
}.to raise_error(ActiveModel::MissingAttributeError)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "does not add _type to the fields" do
|
|
29
|
+
expect(criteria.options[:fields]["_type"]).to be_nil
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
context "when not including id" do
|
|
34
|
+
|
|
35
|
+
let(:criteria) do
|
|
36
|
+
Band.only(:name)
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "responds to id anyway" do
|
|
40
|
+
expect {
|
|
41
|
+
criteria.first.id
|
|
42
|
+
}.to_not raise_error
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context "when passing an array" do
|
|
47
|
+
|
|
48
|
+
let(:criteria) do
|
|
49
|
+
Band.only([ :name, :likes ])
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "includes the limited fields" do
|
|
53
|
+
expect(criteria.first.name).to_not be_nil
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "excludes the non included fields" do
|
|
57
|
+
expect {
|
|
58
|
+
criteria.first.active
|
|
59
|
+
}.to raise_error(ActiveModel::MissingAttributeError)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "does not add _type to the fields" do
|
|
63
|
+
expect(criteria.options[:fields]["_type"]).to be_nil
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
context "when instantiating a class of another type inside the iteration" do
|
|
68
|
+
|
|
69
|
+
let(:criteria) do
|
|
70
|
+
Band.only(:name)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "only limits the fields on the correct model" do
|
|
74
|
+
criteria.each do |band|
|
|
75
|
+
expect(Person.new.age).to eq(100)
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
context "when instantiating a document not in the result set" do
|
|
81
|
+
|
|
82
|
+
let(:criteria) do
|
|
83
|
+
Band.only(:name)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
it "only limits the fields on the correct criteria" do
|
|
87
|
+
criteria.each do |band|
|
|
88
|
+
expect(Band.new.active).to be true
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
context "when nesting a criteria within a criteria" do
|
|
94
|
+
|
|
95
|
+
let(:criteria) do
|
|
96
|
+
Band.only(:name)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "only limits the fields on the correct criteria" do
|
|
100
|
+
criteria.each do |band|
|
|
101
|
+
Band.all.each do |b|
|
|
102
|
+
expect(b.active).to be true
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
context "when using inheritance" do
|
|
110
|
+
context "when using the default discriminator key" do
|
|
111
|
+
let(:criteria) do
|
|
112
|
+
Doctor.only(:_id)
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "adds _type to the fields" do
|
|
116
|
+
expect(criteria.options[:fields]).to include("_type")
|
|
117
|
+
end
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
context "when setting a custom discriminator key" do
|
|
121
|
+
before do
|
|
122
|
+
Person.discriminator_key = "dkey"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
after do
|
|
126
|
+
Person.discriminator_key = nil
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
let(:criteria) do
|
|
130
|
+
Doctor.only(:_id)
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "adds custom discriminator key to the fields" do
|
|
134
|
+
expect(criteria.options[:fields]).to include("dkey")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
it "does not add _type to the fields" do
|
|
138
|
+
expect(criteria.options[:fields]).to_not include("_type")
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
context "when limiting to embedded documents" do
|
|
144
|
+
|
|
145
|
+
context "when the embedded documents are aliased" do
|
|
146
|
+
|
|
147
|
+
let(:criteria) do
|
|
148
|
+
Person.only(:phones)
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
it "properly uses the database field name" do
|
|
152
|
+
expect(criteria.options).to eq(fields: { "_id" => 1, "mobile_phones" => 1 })
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context 'when the field is localized' do
|
|
158
|
+
|
|
159
|
+
before do
|
|
160
|
+
I18n.locale = :en
|
|
161
|
+
d = Dictionary.create(description: 'english-text')
|
|
162
|
+
I18n.locale = :de
|
|
163
|
+
d.description = 'deutsch-text'
|
|
164
|
+
d.save
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
after do
|
|
168
|
+
I18n.locale = :en
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
context 'when entire field is included' do
|
|
172
|
+
|
|
173
|
+
let(:dictionary) do
|
|
174
|
+
Dictionary.only(:description).first
|
|
175
|
+
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'loads all translations' do
|
|
179
|
+
expect(dictionary.description_translations.keys).to include('de', 'en')
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it 'returns the field value for the current locale' do
|
|
183
|
+
I18n.locale = :en
|
|
184
|
+
expect(dictionary.description).to eq('english-text')
|
|
185
|
+
I18n.locale = :de
|
|
186
|
+
expect(dictionary.description).to eq('deutsch-text')
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
context 'when a specific locale is included' do
|
|
191
|
+
|
|
192
|
+
let(:dictionary) do
|
|
193
|
+
Dictionary.only(:'description.de').first
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it 'loads translations only for the included locale' do
|
|
197
|
+
expect(dictionary.description_translations.keys).to include('de')
|
|
198
|
+
expect(dictionary.description_translations.keys).to_not include('en')
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
it 'returns the field value for the included locale' do
|
|
202
|
+
I18n.locale = :en
|
|
203
|
+
expect(dictionary.description).to be_nil
|
|
204
|
+
I18n.locale = :de
|
|
205
|
+
expect(dictionary.description).to eq('deutsch-text')
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
context 'when entire field is excluded' do
|
|
210
|
+
|
|
211
|
+
let(:dictionary) do
|
|
212
|
+
Dictionary.without(:description).first
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
it 'does not load all translations' do
|
|
216
|
+
expect(dictionary.description_translations.keys).to_not include('de', 'en')
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
it 'raises an ActiveModel::MissingAttributeError when attempting to access the field' do
|
|
220
|
+
expect{dictionary.description}.to raise_error ActiveModel::MissingAttributeError
|
|
221
|
+
end
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
context 'when a specific locale is excluded' do
|
|
225
|
+
|
|
226
|
+
let(:dictionary) do
|
|
227
|
+
Dictionary.without(:'description.de').first
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
it 'does not load excluded translations' do
|
|
231
|
+
expect(dictionary.description_translations.keys).to_not include('de')
|
|
232
|
+
expect(dictionary.description_translations.keys).to include('en')
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it 'returns nil for excluded translations' do
|
|
236
|
+
I18n.locale = :en
|
|
237
|
+
expect(dictionary.description).to eq('english-text')
|
|
238
|
+
I18n.locale = :de
|
|
239
|
+
expect(dictionary.description).to be_nil
|
|
240
|
+
end
|
|
241
|
+
end
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
context 'when restricting to id' do
|
|
245
|
+
|
|
246
|
+
context 'when id is aliased to _id' do
|
|
247
|
+
shared_examples 'requests _id field' do
|
|
248
|
+
it 'requests _id field' do
|
|
249
|
+
criteria.options[:fields].should == {'_id' => 1}
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
['id', '_id', :id, :_id].each do |field|
|
|
254
|
+
context "using #{field.inspect}" do
|
|
255
|
+
let(:criteria) do
|
|
256
|
+
Band.where.only(field)
|
|
257
|
+
end
|
|
258
|
+
|
|
259
|
+
include_examples 'requests _id field'
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
context 'using a content field' do
|
|
264
|
+
let(:criteria) do
|
|
265
|
+
Band.where.only(:name)
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
it 'requests content field and _id field' do
|
|
269
|
+
criteria.options[:fields].should == {'_id' => 1, 'name' => 1}
|
|
270
|
+
end
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
context 'when id is not aliased to _id' do
|
|
275
|
+
shared_examples 'requests _id field' do
|
|
276
|
+
it 'requests _id field' do
|
|
277
|
+
criteria.options[:fields].should == {'_id' => 1}
|
|
278
|
+
end
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
shared_examples 'requests id field and _id field' do
|
|
282
|
+
it 'requests id field and _id field' do
|
|
283
|
+
criteria.options[:fields].should == {'_id' => 1, 'id' => 1}
|
|
284
|
+
end
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
['_id', :_id].each do |field|
|
|
288
|
+
context "using #{field.inspect}" do
|
|
289
|
+
let(:criteria) do
|
|
290
|
+
Shirt.where.only(field)
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
include_examples 'requests _id field'
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
|
|
297
|
+
['id', :id].each do |field|
|
|
298
|
+
context "using #{field.inspect}" do
|
|
299
|
+
let(:criteria) do
|
|
300
|
+
Shirt.where.only(field)
|
|
301
|
+
end
|
|
302
|
+
|
|
303
|
+
include_examples 'requests id field and _id field'
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
describe "#without" do
|
|
311
|
+
|
|
312
|
+
let!(:person) do
|
|
313
|
+
Person.create!(username: "davinci", age: 50, pets: false)
|
|
314
|
+
end
|
|
315
|
+
|
|
316
|
+
context "when omitting to embedded documents" do
|
|
317
|
+
|
|
318
|
+
context "when the embedded documents are aliased" do
|
|
319
|
+
|
|
320
|
+
let(:criteria) do
|
|
321
|
+
Person.without(:phones)
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
it "properly uses the database field name" do
|
|
325
|
+
expect(criteria.options).to eq(fields: { "mobile_phones" => 0 })
|
|
326
|
+
end
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
|
|
330
|
+
context "when excluding id fields" do
|
|
331
|
+
|
|
332
|
+
shared_examples 'does not raise error' do
|
|
333
|
+
it "does not raise error" do
|
|
334
|
+
expect {
|
|
335
|
+
criteria.first._id
|
|
336
|
+
}.to_not raise_error
|
|
337
|
+
end
|
|
338
|
+
end
|
|
339
|
+
|
|
340
|
+
shared_examples 'does not unproject _id' do
|
|
341
|
+
it 'does not unproject _id' do
|
|
342
|
+
criteria.options[:fields].should be nil
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "returns id anyway" do
|
|
346
|
+
expect(criteria.first.id).to_not be_nil
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
|
|
350
|
+
shared_examples 'unprojects id' do
|
|
351
|
+
it 'does not unproject _id' do
|
|
352
|
+
criteria.options[:fields].should == {'id' => 0}
|
|
353
|
+
end
|
|
354
|
+
|
|
355
|
+
let(:instance) { criteria.first }
|
|
356
|
+
|
|
357
|
+
it "returns _id" do
|
|
358
|
+
instance._id.should == 'foo'
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
it 'does not return id' do
|
|
362
|
+
lambda do
|
|
363
|
+
instance.id
|
|
364
|
+
end.should raise_error(ActiveModel::MissingAttributeError)
|
|
365
|
+
end
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
context 'model with id aliased to _id' do
|
|
369
|
+
context 'id field' do
|
|
370
|
+
let(:criteria) do
|
|
371
|
+
Person.without(:id, "id")
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
include_examples 'does not raise error'
|
|
375
|
+
include_examples 'does not unproject _id'
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
context '_id field' do
|
|
379
|
+
let(:criteria) do
|
|
380
|
+
Person.without(:_id, "_id")
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
include_examples 'does not raise error'
|
|
384
|
+
include_examples 'does not unproject _id'
|
|
385
|
+
end
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
context 'model without id aliased to _id' do
|
|
389
|
+
let!(:shirt) { Shirt.create!(id: 1, _id: 'foo') }
|
|
390
|
+
|
|
391
|
+
context 'id field' do
|
|
392
|
+
let(:criteria) do
|
|
393
|
+
Shirt.without(:id, "id")
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
include_examples 'does not raise error'
|
|
397
|
+
include_examples 'unprojects id'
|
|
398
|
+
end
|
|
399
|
+
|
|
400
|
+
context '_id field' do
|
|
401
|
+
let(:criteria) do
|
|
402
|
+
Shirt.without(:_id, "_id")
|
|
403
|
+
end
|
|
404
|
+
|
|
405
|
+
include_examples 'does not raise error'
|
|
406
|
+
include_examples 'does not unproject _id'
|
|
407
|
+
end
|
|
408
|
+
end
|
|
409
|
+
end
|
|
410
|
+
end
|
|
411
|
+
end
|
|
@@ -2762,243 +2762,6 @@ describe Mongoid::Criteria do
|
|
|
2762
2762
|
end
|
|
2763
2763
|
end
|
|
2764
2764
|
|
|
2765
|
-
describe "#only" do
|
|
2766
|
-
|
|
2767
|
-
let!(:band) do
|
|
2768
|
-
Band.create(name: "Depeche Mode", likes: 3, views: 10)
|
|
2769
|
-
end
|
|
2770
|
-
|
|
2771
|
-
context "when not using inheritance" do
|
|
2772
|
-
|
|
2773
|
-
context "when passing splat args" do
|
|
2774
|
-
|
|
2775
|
-
let(:criteria) do
|
|
2776
|
-
Band.only(:_id)
|
|
2777
|
-
end
|
|
2778
|
-
|
|
2779
|
-
it "limits the returned fields" do
|
|
2780
|
-
expect {
|
|
2781
|
-
criteria.first.name
|
|
2782
|
-
}.to raise_error(ActiveModel::MissingAttributeError)
|
|
2783
|
-
end
|
|
2784
|
-
|
|
2785
|
-
it "does not add _type to the fields" do
|
|
2786
|
-
expect(criteria.options[:fields]["_type"]).to be_nil
|
|
2787
|
-
end
|
|
2788
|
-
end
|
|
2789
|
-
|
|
2790
|
-
context "when not including id" do
|
|
2791
|
-
|
|
2792
|
-
let(:criteria) do
|
|
2793
|
-
Band.only(:name)
|
|
2794
|
-
end
|
|
2795
|
-
|
|
2796
|
-
it "responds to id anyway" do
|
|
2797
|
-
expect {
|
|
2798
|
-
criteria.first.id
|
|
2799
|
-
}.to_not raise_error
|
|
2800
|
-
end
|
|
2801
|
-
end
|
|
2802
|
-
|
|
2803
|
-
context "when passing an array" do
|
|
2804
|
-
|
|
2805
|
-
let(:criteria) do
|
|
2806
|
-
Band.only([ :name, :likes ])
|
|
2807
|
-
end
|
|
2808
|
-
|
|
2809
|
-
it "includes the limited fields" do
|
|
2810
|
-
expect(criteria.first.name).to_not be_nil
|
|
2811
|
-
end
|
|
2812
|
-
|
|
2813
|
-
it "excludes the non included fields" do
|
|
2814
|
-
expect {
|
|
2815
|
-
criteria.first.active
|
|
2816
|
-
}.to raise_error(ActiveModel::MissingAttributeError)
|
|
2817
|
-
end
|
|
2818
|
-
|
|
2819
|
-
it "does not add _type to the fields" do
|
|
2820
|
-
expect(criteria.options[:fields]["_type"]).to be_nil
|
|
2821
|
-
end
|
|
2822
|
-
end
|
|
2823
|
-
|
|
2824
|
-
context "when instantiating a class of another type inside the iteration" do
|
|
2825
|
-
|
|
2826
|
-
let(:criteria) do
|
|
2827
|
-
Band.only(:name)
|
|
2828
|
-
end
|
|
2829
|
-
|
|
2830
|
-
it "only limits the fields on the correct model" do
|
|
2831
|
-
criteria.each do |band|
|
|
2832
|
-
expect(Person.new.age).to eq(100)
|
|
2833
|
-
end
|
|
2834
|
-
end
|
|
2835
|
-
end
|
|
2836
|
-
|
|
2837
|
-
context "when instantiating a document not in the result set" do
|
|
2838
|
-
|
|
2839
|
-
let(:criteria) do
|
|
2840
|
-
Band.only(:name)
|
|
2841
|
-
end
|
|
2842
|
-
|
|
2843
|
-
it "only limits the fields on the correct criteria" do
|
|
2844
|
-
criteria.each do |band|
|
|
2845
|
-
expect(Band.new.active).to be true
|
|
2846
|
-
end
|
|
2847
|
-
end
|
|
2848
|
-
end
|
|
2849
|
-
|
|
2850
|
-
context "when nesting a criteria within a criteria" do
|
|
2851
|
-
|
|
2852
|
-
let(:criteria) do
|
|
2853
|
-
Band.only(:name)
|
|
2854
|
-
end
|
|
2855
|
-
|
|
2856
|
-
it "only limits the fields on the correct criteria" do
|
|
2857
|
-
criteria.each do |band|
|
|
2858
|
-
Band.all.each do |b|
|
|
2859
|
-
expect(b.active).to be true
|
|
2860
|
-
end
|
|
2861
|
-
end
|
|
2862
|
-
end
|
|
2863
|
-
end
|
|
2864
|
-
end
|
|
2865
|
-
|
|
2866
|
-
context "when using inheritance" do
|
|
2867
|
-
context "when using the default discriminator key" do
|
|
2868
|
-
let(:criteria) do
|
|
2869
|
-
Doctor.only(:_id)
|
|
2870
|
-
end
|
|
2871
|
-
|
|
2872
|
-
it "adds _type to the fields" do
|
|
2873
|
-
expect(criteria.options[:fields]).to include("_type")
|
|
2874
|
-
end
|
|
2875
|
-
end
|
|
2876
|
-
|
|
2877
|
-
context "when setting a custom discriminator key" do
|
|
2878
|
-
before do
|
|
2879
|
-
Person.discriminator_key = "dkey"
|
|
2880
|
-
end
|
|
2881
|
-
|
|
2882
|
-
after do
|
|
2883
|
-
Person.discriminator_key = nil
|
|
2884
|
-
end
|
|
2885
|
-
|
|
2886
|
-
let(:criteria) do
|
|
2887
|
-
Doctor.only(:_id)
|
|
2888
|
-
end
|
|
2889
|
-
|
|
2890
|
-
it "adds custom discriminator key to the fields" do
|
|
2891
|
-
expect(criteria.options[:fields]).to include("dkey")
|
|
2892
|
-
end
|
|
2893
|
-
|
|
2894
|
-
it "does not add _type to the fields" do
|
|
2895
|
-
expect(criteria.options[:fields]).to_not include("_type")
|
|
2896
|
-
end
|
|
2897
|
-
end
|
|
2898
|
-
end
|
|
2899
|
-
|
|
2900
|
-
context "when limiting to embedded documents" do
|
|
2901
|
-
|
|
2902
|
-
context "when the embedded documents are aliased" do
|
|
2903
|
-
|
|
2904
|
-
let(:criteria) do
|
|
2905
|
-
Person.only(:phones)
|
|
2906
|
-
end
|
|
2907
|
-
|
|
2908
|
-
it "properly uses the database field name" do
|
|
2909
|
-
expect(criteria.options).to eq(fields: { "_id" => 1, "mobile_phones" => 1 })
|
|
2910
|
-
end
|
|
2911
|
-
end
|
|
2912
|
-
end
|
|
2913
|
-
|
|
2914
|
-
context 'when the field is localized' do
|
|
2915
|
-
|
|
2916
|
-
before do
|
|
2917
|
-
I18n.locale = :en
|
|
2918
|
-
d = Dictionary.create(description: 'english-text')
|
|
2919
|
-
I18n.locale = :de
|
|
2920
|
-
d.description = 'deutsch-text'
|
|
2921
|
-
d.save
|
|
2922
|
-
end
|
|
2923
|
-
|
|
2924
|
-
after do
|
|
2925
|
-
I18n.locale = :en
|
|
2926
|
-
end
|
|
2927
|
-
|
|
2928
|
-
context 'when entire field is included' do
|
|
2929
|
-
|
|
2930
|
-
let(:dictionary) do
|
|
2931
|
-
Dictionary.only(:description).first
|
|
2932
|
-
|
|
2933
|
-
end
|
|
2934
|
-
|
|
2935
|
-
it 'loads all translations' do
|
|
2936
|
-
expect(dictionary.description_translations.keys).to include('de', 'en')
|
|
2937
|
-
end
|
|
2938
|
-
|
|
2939
|
-
it 'returns the field value for the current locale' do
|
|
2940
|
-
I18n.locale = :en
|
|
2941
|
-
expect(dictionary.description).to eq('english-text')
|
|
2942
|
-
I18n.locale = :de
|
|
2943
|
-
expect(dictionary.description).to eq('deutsch-text')
|
|
2944
|
-
end
|
|
2945
|
-
end
|
|
2946
|
-
|
|
2947
|
-
context 'when a specific locale is included' do
|
|
2948
|
-
|
|
2949
|
-
let(:dictionary) do
|
|
2950
|
-
Dictionary.only(:'description.de').first
|
|
2951
|
-
end
|
|
2952
|
-
|
|
2953
|
-
it 'loads translations only for the included locale' do
|
|
2954
|
-
expect(dictionary.description_translations.keys).to include('de')
|
|
2955
|
-
expect(dictionary.description_translations.keys).to_not include('en')
|
|
2956
|
-
end
|
|
2957
|
-
|
|
2958
|
-
it 'returns the field value for the included locale' do
|
|
2959
|
-
I18n.locale = :en
|
|
2960
|
-
expect(dictionary.description).to be_nil
|
|
2961
|
-
I18n.locale = :de
|
|
2962
|
-
expect(dictionary.description).to eq('deutsch-text')
|
|
2963
|
-
end
|
|
2964
|
-
end
|
|
2965
|
-
|
|
2966
|
-
context 'when entire field is excluded' do
|
|
2967
|
-
|
|
2968
|
-
let(:dictionary) do
|
|
2969
|
-
Dictionary.without(:description).first
|
|
2970
|
-
end
|
|
2971
|
-
|
|
2972
|
-
it 'does not load all translations' do
|
|
2973
|
-
expect(dictionary.description_translations.keys).to_not include('de', 'en')
|
|
2974
|
-
end
|
|
2975
|
-
|
|
2976
|
-
it 'raises an ActiveModel::MissingAttributeError when attempting to access the field' do
|
|
2977
|
-
expect{dictionary.description}.to raise_error ActiveModel::MissingAttributeError
|
|
2978
|
-
end
|
|
2979
|
-
end
|
|
2980
|
-
|
|
2981
|
-
context 'when a specific locale is excluded' do
|
|
2982
|
-
|
|
2983
|
-
let(:dictionary) do
|
|
2984
|
-
Dictionary.without(:'description.de').first
|
|
2985
|
-
end
|
|
2986
|
-
|
|
2987
|
-
it 'does not load excluded translations' do
|
|
2988
|
-
expect(dictionary.description_translations.keys).to_not include('de')
|
|
2989
|
-
expect(dictionary.description_translations.keys).to include('en')
|
|
2990
|
-
end
|
|
2991
|
-
|
|
2992
|
-
it 'returns nil for excluded translations' do
|
|
2993
|
-
I18n.locale = :en
|
|
2994
|
-
expect(dictionary.description).to eq('english-text')
|
|
2995
|
-
I18n.locale = :de
|
|
2996
|
-
expect(dictionary.description).to be_nil
|
|
2997
|
-
end
|
|
2998
|
-
end
|
|
2999
|
-
end
|
|
3000
|
-
end
|
|
3001
|
-
|
|
3002
2765
|
[ :or, :any_of ].each do |method|
|
|
3003
2766
|
|
|
3004
2767
|
describe "\##{method}" do
|
|
@@ -3917,44 +3680,6 @@ describe Mongoid::Criteria do
|
|
|
3917
3680
|
end
|
|
3918
3681
|
end
|
|
3919
3682
|
|
|
3920
|
-
describe "#without" do
|
|
3921
|
-
|
|
3922
|
-
let!(:person) do
|
|
3923
|
-
Person.create!(username: "davinci", age: 50, pets: false)
|
|
3924
|
-
end
|
|
3925
|
-
|
|
3926
|
-
context "when omitting to embedded documents" do
|
|
3927
|
-
|
|
3928
|
-
context "when the embedded documents are aliased" do
|
|
3929
|
-
|
|
3930
|
-
let(:criteria) do
|
|
3931
|
-
Person.without(:phones)
|
|
3932
|
-
end
|
|
3933
|
-
|
|
3934
|
-
it "properly uses the database field name" do
|
|
3935
|
-
expect(criteria.options).to eq(fields: { "mobile_phones" => 0 })
|
|
3936
|
-
end
|
|
3937
|
-
end
|
|
3938
|
-
end
|
|
3939
|
-
|
|
3940
|
-
context "when excluding id" do
|
|
3941
|
-
|
|
3942
|
-
let(:criteria) do
|
|
3943
|
-
Person.without(:_id, :id, "_id", "id")
|
|
3944
|
-
end
|
|
3945
|
-
|
|
3946
|
-
it "does not raise error" do
|
|
3947
|
-
expect {
|
|
3948
|
-
criteria.first.id
|
|
3949
|
-
}.to_not raise_error
|
|
3950
|
-
end
|
|
3951
|
-
|
|
3952
|
-
it "returns id anyway" do
|
|
3953
|
-
expect(criteria.first.id).to_not be_nil
|
|
3954
|
-
end
|
|
3955
|
-
end
|
|
3956
|
-
end
|
|
3957
|
-
|
|
3958
3683
|
describe "#type_selection" do
|
|
3959
3684
|
context "when using the default discriminator_key" do
|
|
3960
3685
|
context "when only one subclass exists" do
|