mongoid 7.2.0.rc1 → 7.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (214) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/Rakefile +45 -10
  5. data/lib/config/locales/en.yml +2 -2
  6. data/lib/mongoid/association/accessors.rb +1 -1
  7. data/lib/mongoid/association/constrainable.rb +1 -1
  8. data/lib/mongoid/association/depending.rb +4 -4
  9. data/lib/mongoid/association/embedded/batchable.rb +1 -1
  10. data/lib/mongoid/association/embedded/embedded_in.rb +1 -1
  11. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +10 -3
  12. data/lib/mongoid/association/nested/many.rb +1 -1
  13. data/lib/mongoid/association/nested/one.rb +4 -2
  14. data/lib/mongoid/association/proxy.rb +6 -1
  15. data/lib/mongoid/association/referenced/auto_save.rb +2 -2
  16. data/lib/mongoid/association/referenced/has_many/enumerable.rb +493 -495
  17. data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
  18. data/lib/mongoid/association/referenced/has_one/buildable.rb +8 -0
  19. data/lib/mongoid/association/referenced/has_one/nested_builder.rb +2 -2
  20. data/lib/mongoid/association/referenced/has_one/proxy.rb +6 -1
  21. data/lib/mongoid/attributes.rb +32 -14
  22. data/lib/mongoid/attributes/projector.rb +120 -0
  23. data/lib/mongoid/cacheable.rb +2 -2
  24. data/lib/mongoid/clients.rb +1 -1
  25. data/lib/mongoid/clients/factory.rb +22 -8
  26. data/lib/mongoid/config.rb +19 -2
  27. data/lib/mongoid/contextual/aggregable/mongo.rb +10 -8
  28. data/lib/mongoid/copyable.rb +6 -2
  29. data/lib/mongoid/criteria.rb +4 -5
  30. data/lib/mongoid/criteria/findable.rb +1 -1
  31. data/lib/mongoid/criteria/queryable/expandable.rb +0 -24
  32. data/lib/mongoid/criteria/queryable/extensions.rb +0 -4
  33. data/lib/mongoid/criteria/queryable/extensions/boolean.rb +1 -1
  34. data/lib/mongoid/criteria/queryable/mergeable.rb +46 -20
  35. data/lib/mongoid/criteria/queryable/selectable.rb +8 -8
  36. data/lib/mongoid/criteria/queryable/selector.rb +0 -4
  37. data/lib/mongoid/document.rb +4 -17
  38. data/lib/mongoid/errors/delete_restriction.rb +8 -9
  39. data/lib/mongoid/evolvable.rb +1 -1
  40. data/lib/mongoid/extensions.rb +1 -0
  41. data/lib/mongoid/extensions/boolean.rb +1 -2
  42. data/lib/mongoid/extensions/false_class.rb +1 -1
  43. data/lib/mongoid/extensions/hash.rb +2 -2
  44. data/lib/mongoid/extensions/true_class.rb +1 -1
  45. data/lib/mongoid/fields.rb +46 -5
  46. data/lib/mongoid/inspectable.rb +1 -1
  47. data/lib/mongoid/interceptable.rb +3 -1
  48. data/lib/mongoid/matcher.rb +26 -43
  49. data/lib/mongoid/matcher/bits.rb +41 -0
  50. data/lib/mongoid/matcher/bits_all_clear.rb +20 -0
  51. data/lib/mongoid/matcher/bits_all_set.rb +20 -0
  52. data/lib/mongoid/matcher/bits_any_clear.rb +20 -0
  53. data/lib/mongoid/matcher/bits_any_set.rb +20 -0
  54. data/lib/mongoid/matcher/elem_match.rb +2 -1
  55. data/lib/mongoid/matcher/expression.rb +9 -14
  56. data/lib/mongoid/matcher/field_expression.rb +4 -5
  57. data/lib/mongoid/matcher/field_operator.rb +13 -11
  58. data/lib/mongoid/matcher/mod.rb +17 -0
  59. data/lib/mongoid/matcher/type.rb +99 -0
  60. data/lib/mongoid/persistable/deletable.rb +1 -2
  61. data/lib/mongoid/persistable/destroyable.rb +8 -2
  62. data/lib/mongoid/persistable/updatable.rb +27 -2
  63. data/lib/mongoid/query_cache.rb +35 -29
  64. data/lib/mongoid/reloadable.rb +5 -0
  65. data/lib/mongoid/selectable.rb +5 -7
  66. data/lib/mongoid/shardable.rb +21 -5
  67. data/lib/mongoid/stringified_symbol.rb +53 -0
  68. data/lib/mongoid/touchable.rb +23 -4
  69. data/lib/mongoid/version.rb +1 -1
  70. data/lib/rails/generators/mongoid/config/config_generator.rb +8 -1
  71. data/spec/README.md +19 -4
  72. data/spec/integration/app_spec.rb +175 -88
  73. data/spec/integration/associations/embeds_many_spec.rb +68 -0
  74. data/spec/integration/associations/embeds_one_spec.rb +24 -0
  75. data/spec/integration/associations/has_many_spec.rb +60 -0
  76. data/spec/integration/associations/has_one_spec.rb +108 -0
  77. data/spec/integration/callbacks_models.rb +49 -0
  78. data/spec/integration/callbacks_spec.rb +216 -0
  79. data/spec/integration/criteria/date_field_spec.rb +1 -1
  80. data/spec/integration/document_spec.rb +30 -0
  81. data/spec/integration/matcher_operator_data/bits_all_clear.yml +159 -0
  82. data/spec/integration/matcher_operator_data/bits_all_set.yml +159 -0
  83. data/spec/integration/matcher_operator_data/bits_any_clear.yml +159 -0
  84. data/spec/integration/matcher_operator_data/bits_any_set.yml +159 -0
  85. data/spec/integration/matcher_operator_data/comment.yml +22 -0
  86. data/spec/integration/matcher_operator_data/elem_match.yml +46 -0
  87. data/spec/integration/matcher_operator_data/gt_types.yml +63 -0
  88. data/spec/integration/matcher_operator_data/gte_types.yml +15 -0
  89. data/spec/integration/matcher_operator_data/implicit_traversal.yml +96 -0
  90. data/spec/integration/matcher_operator_data/in.yml +16 -0
  91. data/spec/integration/matcher_operator_data/lt_types.yml +15 -0
  92. data/spec/integration/matcher_operator_data/lte_types.yml +15 -0
  93. data/spec/integration/matcher_operator_data/mod.yml +55 -0
  94. data/spec/integration/matcher_operator_data/ne_types.yml +15 -0
  95. data/spec/integration/matcher_operator_data/type.yml +70 -0
  96. data/spec/integration/matcher_operator_data/type_array.yml +16 -0
  97. data/spec/integration/matcher_operator_data/type_binary.yml +18 -0
  98. data/spec/integration/matcher_operator_data/type_boolean.yml +39 -0
  99. data/spec/integration/matcher_operator_data/type_code.yml +26 -0
  100. data/spec/integration/matcher_operator_data/type_code_with_scope.yml +26 -0
  101. data/spec/integration/matcher_operator_data/type_date.yml +39 -0
  102. data/spec/integration/matcher_operator_data/type_db_pointer.yml +19 -0
  103. data/spec/integration/matcher_operator_data/type_decimal.yml +40 -0
  104. data/spec/integration/matcher_operator_data/type_double.yml +15 -0
  105. data/spec/integration/matcher_operator_data/type_int32.yml +33 -0
  106. data/spec/integration/matcher_operator_data/type_int64.yml +33 -0
  107. data/spec/integration/matcher_operator_data/type_max_key.yml +17 -0
  108. data/spec/integration/matcher_operator_data/type_min_key.yml +17 -0
  109. data/spec/integration/matcher_operator_data/type_null.yml +23 -0
  110. data/spec/integration/matcher_operator_data/type_object.yml +23 -0
  111. data/spec/integration/matcher_operator_data/type_object_id.yml +25 -0
  112. data/spec/integration/matcher_operator_data/type_regex.yml +44 -0
  113. data/spec/integration/matcher_operator_data/type_string.yml +15 -0
  114. data/spec/integration/matcher_operator_data/type_symbol.yml +32 -0
  115. data/spec/integration/matcher_operator_data/type_timestamp.yml +25 -0
  116. data/spec/integration/matcher_operator_data/type_undefined.yml +17 -0
  117. data/spec/integration/stringified_symbol_field_spec.rb +190 -0
  118. data/spec/lite_spec_helper.rb +9 -7
  119. data/spec/mongoid/association/depending_spec.rb +391 -352
  120. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +50 -0
  121. data/spec/mongoid/association/nested/one_spec.rb +18 -14
  122. data/spec/mongoid/association/referenced/belongs_to/proxy_spec.rb +25 -8
  123. data/spec/mongoid/association/referenced/has_and_belongs_to_many/binding_spec.rb +1 -1
  124. data/spec/mongoid/association/referenced/has_many/binding_spec.rb +1 -1
  125. data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +1 -1
  126. data/spec/mongoid/association/referenced/has_many_models.rb +12 -0
  127. data/spec/mongoid/association/referenced/has_one_models.rb +20 -0
  128. data/spec/mongoid/association/referenced/has_one_spec.rb +1 -1
  129. data/spec/mongoid/atomic/paths_spec.rb +105 -12
  130. data/spec/mongoid/attributes/projector_data/embedded.yml +105 -0
  131. data/spec/mongoid/attributes/projector_data/fields.yml +93 -0
  132. data/spec/mongoid/attributes/projector_spec.rb +41 -0
  133. data/spec/mongoid/attributes_spec.rb +333 -0
  134. data/spec/mongoid/clients/factory_spec.rb +48 -0
  135. data/spec/mongoid/config_spec.rb +32 -0
  136. data/spec/mongoid/contextual/atomic_spec.rb +17 -4
  137. data/spec/mongoid/contextual/mongo_spec.rb +2 -2
  138. data/spec/mongoid/copyable_spec.rb +44 -17
  139. data/spec/mongoid/copyable_spec_models.rb +14 -0
  140. data/spec/mongoid/criteria/modifiable_spec.rb +1 -1
  141. data/spec/mongoid/criteria/queryable/expandable_spec.rb +0 -73
  142. data/spec/mongoid/criteria/queryable/extensions/boolean_spec.rb +1 -1
  143. data/spec/mongoid/criteria/queryable/mergeable_spec.rb +105 -7
  144. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +265 -24
  145. data/spec/mongoid/criteria/queryable/selectable_shared_examples.rb +39 -0
  146. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -565
  147. data/spec/mongoid/criteria/queryable/selectable_where_spec.rb +590 -0
  148. data/spec/mongoid/criteria_projection_spec.rb +411 -0
  149. data/spec/mongoid/criteria_spec.rb +0 -275
  150. data/spec/mongoid/document_fields_spec.rb +26 -0
  151. data/spec/mongoid/document_spec.rb +13 -13
  152. data/spec/mongoid/equality_spec.rb +0 -1
  153. data/spec/mongoid/errors/delete_restriction_spec.rb +1 -1
  154. data/spec/mongoid/extensions/false_class_spec.rb +1 -1
  155. data/spec/mongoid/extensions/string_spec.rb +5 -5
  156. data/spec/mongoid/extensions/stringified_symbol_spec.rb +85 -0
  157. data/spec/mongoid/extensions/true_class_spec.rb +1 -1
  158. data/spec/mongoid/fields/localized_spec.rb +4 -4
  159. data/spec/mongoid/fields_spec.rb +4 -4
  160. data/spec/mongoid/inspectable_spec.rb +12 -4
  161. data/spec/mongoid/matcher/extract_attribute_data/numeric_keys.yml +104 -0
  162. data/spec/mongoid/matcher/extract_attribute_data/traversal.yml +68 -88
  163. data/spec/mongoid/matcher/extract_attribute_spec.rb +3 -13
  164. data/spec/mongoid/persistable/deletable_spec.rb +175 -1
  165. data/spec/mongoid/persistable/destroyable_spec.rb +191 -3
  166. data/spec/mongoid/persistable/savable_spec.rb +3 -5
  167. data/spec/mongoid/persistable/settable_spec.rb +30 -0
  168. data/spec/mongoid/persistable/upsertable_spec.rb +1 -1
  169. data/spec/mongoid/query_cache_middleware_spec.rb +8 -0
  170. data/spec/mongoid/reloadable_spec.rb +18 -1
  171. data/spec/mongoid/shardable_spec.rb +44 -0
  172. data/spec/mongoid/touchable_spec.rb +104 -16
  173. data/spec/mongoid/touchable_spec_models.rb +52 -0
  174. data/spec/mongoid/validatable_spec.rb +1 -1
  175. data/spec/shared/LICENSE +20 -0
  176. data/spec/shared/bin/get-mongodb-download-url +17 -0
  177. data/spec/shared/lib/mrss/child_process_helper.rb +80 -0
  178. data/spec/shared/lib/mrss/cluster_config.rb +221 -0
  179. data/spec/shared/lib/mrss/constraints.rb +354 -0
  180. data/spec/shared/lib/mrss/docker_runner.rb +265 -0
  181. data/spec/shared/lib/mrss/lite_constraints.rb +191 -0
  182. data/spec/shared/lib/mrss/server_version_registry.rb +115 -0
  183. data/spec/shared/lib/mrss/spec_organizer.rb +162 -0
  184. data/spec/shared/lib/mrss/utils.rb +15 -0
  185. data/spec/shared/share/Dockerfile.erb +231 -0
  186. data/spec/shared/shlib/distro.sh +73 -0
  187. data/spec/shared/shlib/server.sh +290 -0
  188. data/spec/shared/shlib/set_env.sh +128 -0
  189. data/spec/spec_helper.rb +7 -1
  190. data/spec/support/client_registry.rb +9 -0
  191. data/spec/support/constraints.rb +0 -226
  192. data/spec/support/models/bolt.rb +8 -0
  193. data/spec/support/models/customer.rb +11 -0
  194. data/spec/support/models/customer_address.rb +12 -0
  195. data/spec/support/models/dictionary.rb +6 -0
  196. data/spec/support/models/hole.rb +13 -0
  197. data/spec/support/models/mop.rb +9 -0
  198. data/spec/support/models/nut.rb +8 -0
  199. data/spec/support/models/order.rb +11 -0
  200. data/spec/support/models/person.rb +8 -0
  201. data/spec/support/models/sealer.rb +8 -0
  202. data/spec/support/models/series.rb +1 -0
  203. data/spec/support/models/shirt.rb +12 -0
  204. data/spec/support/models/spacer.rb +8 -0
  205. data/spec/support/models/threadlocker.rb +8 -0
  206. data/spec/support/models/washer.rb +8 -0
  207. data/spec/support/models/wiki_page.rb +1 -0
  208. data/spec/support/spec_config.rb +8 -0
  209. metadata +655 -507
  210. metadata.gz.sig +0 -0
  211. data/spec/support/child_process_helper.rb +0 -79
  212. data/spec/support/cluster_config.rb +0 -158
  213. data/spec/support/lite_constraints.rb +0 -22
  214. data/spec/support/spec_organizer.rb +0 -130
@@ -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