mongoid 8.0.3 → 8.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (188) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/CHANGELOG.md +3 -3
  4. data/README.md +3 -3
  5. data/lib/config/locales/en.yml +46 -14
  6. data/lib/mongoid/association/accessors.rb +2 -2
  7. data/lib/mongoid/association/builders.rb +1 -1
  8. data/lib/mongoid/association/embedded/batchable.rb +2 -2
  9. data/lib/mongoid/association/embedded/embedded_in/buildable.rb +2 -2
  10. data/lib/mongoid/association/embedded/embedded_in/proxy.rb +2 -1
  11. data/lib/mongoid/association/embedded/embeds_many/buildable.rb +3 -2
  12. data/lib/mongoid/association/embedded/embeds_many/proxy.rb +23 -21
  13. data/lib/mongoid/association/embedded/embeds_one/buildable.rb +1 -1
  14. data/lib/mongoid/association/embedded/embeds_one/proxy.rb +1 -1
  15. data/lib/mongoid/association/nested/one.rb +40 -2
  16. data/lib/mongoid/association/proxy.rb +1 -1
  17. data/lib/mongoid/association/referenced/counter_cache.rb +2 -2
  18. data/lib/mongoid/association/referenced/has_and_belongs_to_many/proxy.rb +5 -1
  19. data/lib/mongoid/association/referenced/has_many/enumerable.rb +2 -2
  20. data/lib/mongoid/association/referenced/has_many/proxy.rb +7 -3
  21. data/lib/mongoid/association/reflections.rb +2 -2
  22. data/lib/mongoid/attributes/dynamic.rb +1 -1
  23. data/lib/mongoid/attributes/nested.rb +2 -2
  24. data/lib/mongoid/attributes/projector.rb +1 -1
  25. data/lib/mongoid/attributes/readonly.rb +1 -1
  26. data/lib/mongoid/attributes.rb +8 -2
  27. data/lib/mongoid/changeable.rb +104 -4
  28. data/lib/mongoid/clients/storage_options.rb +2 -5
  29. data/lib/mongoid/clients/validators/storage.rb +1 -13
  30. data/lib/mongoid/collection_configurable.rb +58 -0
  31. data/lib/mongoid/composable.rb +2 -0
  32. data/lib/mongoid/config/defaults.rb +60 -0
  33. data/lib/mongoid/config/validators/async_query_executor.rb +24 -0
  34. data/lib/mongoid/config/validators.rb +1 -0
  35. data/lib/mongoid/config.rb +101 -0
  36. data/lib/mongoid/contextual/atomic.rb +1 -1
  37. data/lib/mongoid/contextual/memory.rb +233 -33
  38. data/lib/mongoid/contextual/mongo/documents_loader.rb +177 -0
  39. data/lib/mongoid/contextual/mongo.rb +373 -113
  40. data/lib/mongoid/contextual/none.rb +162 -7
  41. data/lib/mongoid/contextual.rb +12 -0
  42. data/lib/mongoid/criteria/findable.rb +2 -2
  43. data/lib/mongoid/criteria/includable.rb +4 -3
  44. data/lib/mongoid/criteria/queryable/extensions/array.rb +1 -1
  45. data/lib/mongoid/criteria/queryable/extensions/hash.rb +1 -1
  46. data/lib/mongoid/criteria/queryable/extensions/numeric.rb +0 -8
  47. data/lib/mongoid/criteria/queryable/extensions/string.rb +1 -11
  48. data/lib/mongoid/criteria/queryable/extensions/symbol.rb +0 -10
  49. data/lib/mongoid/criteria/queryable/key.rb +1 -1
  50. data/lib/mongoid/criteria/queryable/mergeable.rb +1 -1
  51. data/lib/mongoid/criteria/queryable/optional.rb +8 -8
  52. data/lib/mongoid/criteria/queryable/selectable.rb +43 -12
  53. data/lib/mongoid/criteria/translator.rb +45 -0
  54. data/lib/mongoid/criteria.rb +7 -5
  55. data/lib/mongoid/deprecable.rb +1 -1
  56. data/lib/mongoid/document.rb +50 -13
  57. data/lib/mongoid/errors/create_collection_failure.rb +33 -0
  58. data/lib/mongoid/errors/drop_collection_failure.rb +27 -0
  59. data/lib/mongoid/errors/immutable_attribute.rb +26 -0
  60. data/lib/mongoid/errors/invalid_async_query_executor.rb +25 -0
  61. data/lib/mongoid/errors/invalid_global_executor_concurrency.rb +22 -0
  62. data/lib/mongoid/errors/invalid_storage_parent.rb +2 -0
  63. data/lib/mongoid/errors.rb +4 -1
  64. data/lib/mongoid/extensions/object.rb +2 -2
  65. data/lib/mongoid/extensions/time.rb +2 -0
  66. data/lib/mongoid/factory.rb +21 -8
  67. data/lib/mongoid/fields/localized.rb +10 -0
  68. data/lib/mongoid/fields/standard.rb +10 -0
  69. data/lib/mongoid/fields.rb +69 -13
  70. data/lib/mongoid/findable.rb +27 -3
  71. data/lib/mongoid/interceptable.rb +7 -6
  72. data/lib/mongoid/matcher/eq_impl.rb +1 -1
  73. data/lib/mongoid/matcher/type.rb +1 -1
  74. data/lib/mongoid/matcher.rb +21 -6
  75. data/lib/mongoid/persistable/creatable.rb +1 -0
  76. data/lib/mongoid/persistable/deletable.rb +1 -1
  77. data/lib/mongoid/persistable/savable.rb +13 -1
  78. data/lib/mongoid/persistable/unsettable.rb +2 -2
  79. data/lib/mongoid/persistable/updatable.rb +51 -1
  80. data/lib/mongoid/persistable/upsertable.rb +20 -1
  81. data/lib/mongoid/persistable.rb +3 -0
  82. data/lib/mongoid/query_cache.rb +5 -1
  83. data/lib/mongoid/railties/database.rake +7 -2
  84. data/lib/mongoid/shardable.rb +35 -11
  85. data/lib/mongoid/stateful.rb +22 -1
  86. data/lib/mongoid/tasks/database.rake +12 -0
  87. data/lib/mongoid/tasks/database.rb +20 -0
  88. data/lib/mongoid/threaded.rb +30 -0
  89. data/lib/mongoid/traversable.rb +1 -1
  90. data/lib/mongoid/utils.rb +22 -0
  91. data/lib/mongoid/validatable/macros.rb +5 -5
  92. data/lib/mongoid/validatable.rb +4 -1
  93. data/lib/mongoid/version.rb +1 -1
  94. data/lib/mongoid/warnings.rb +17 -1
  95. data/lib/mongoid.rb +16 -3
  96. data/spec/integration/app_spec.rb +2 -2
  97. data/spec/integration/callbacks_models.rb +37 -0
  98. data/spec/integration/callbacks_spec.rb +134 -0
  99. data/spec/integration/discriminator_key_spec.rb +4 -5
  100. data/spec/integration/i18n_fallbacks_spec.rb +3 -2
  101. data/spec/mongoid/association/embedded/embedded_in/proxy_spec.rb +27 -0
  102. data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +57 -57
  103. data/spec/mongoid/association/embedded/embeds_many_models.rb +1 -0
  104. data/spec/mongoid/association/embedded/embeds_one/proxy_spec.rb +15 -2
  105. data/spec/mongoid/association/referenced/belongs_to_spec.rb +2 -18
  106. data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +148 -224
  107. data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +111 -164
  108. data/spec/mongoid/association/syncable_spec.rb +1 -1
  109. data/spec/mongoid/attributes_spec.rb +5 -8
  110. data/spec/mongoid/changeable_spec.rb +299 -24
  111. data/spec/mongoid/clients_spec.rb +122 -13
  112. data/spec/mongoid/collection_configurable_spec.rb +158 -0
  113. data/spec/mongoid/config/defaults_spec.rb +160 -0
  114. data/spec/mongoid/config_spec.rb +154 -18
  115. data/spec/mongoid/contextual/memory_spec.rb +332 -76
  116. data/spec/mongoid/contextual/mongo/documents_loader_spec.rb +187 -0
  117. data/spec/mongoid/contextual/mongo_spec.rb +995 -36
  118. data/spec/mongoid/contextual/none_spec.rb +49 -2
  119. data/spec/mongoid/copyable_spec.rb +3 -11
  120. data/spec/mongoid/criteria/queryable/extensions/string_spec.rb +4 -69
  121. data/spec/mongoid/criteria/queryable/extensions/symbol_spec.rb +0 -59
  122. data/spec/mongoid/criteria/queryable/optional_spec.rb +15 -0
  123. data/spec/mongoid/criteria/queryable/options_spec.rb +1 -1
  124. data/spec/mongoid/criteria/queryable/selectable_logical_spec.rb +419 -0
  125. data/spec/mongoid/criteria/queryable/selectable_spec.rb +1 -1
  126. data/spec/mongoid/criteria/queryable/selector_spec.rb +1 -1
  127. data/spec/mongoid/criteria/translator_spec.rb +132 -0
  128. data/spec/mongoid/criteria_projection_spec.rb +1 -4
  129. data/spec/mongoid/criteria_spec.rb +5 -9
  130. data/spec/mongoid/errors/readonly_document_spec.rb +2 -2
  131. data/spec/mongoid/extensions/time_spec.rb +8 -43
  132. data/spec/mongoid/extensions/time_with_zone_spec.rb +7 -52
  133. data/spec/mongoid/fields/localized_spec.rb +46 -28
  134. data/spec/mongoid/fields_spec.rb +136 -34
  135. data/spec/mongoid/findable_spec.rb +391 -34
  136. data/spec/mongoid/indexable_spec.rb +16 -10
  137. data/spec/mongoid/interceptable_spec.rb +15 -3
  138. data/spec/mongoid/persistable/deletable_spec.rb +26 -6
  139. data/spec/mongoid/persistable/destroyable_spec.rb +26 -6
  140. data/spec/mongoid/persistable/incrementable_spec.rb +37 -0
  141. data/spec/mongoid/persistable/logical_spec.rb +37 -0
  142. data/spec/mongoid/persistable/poppable_spec.rb +36 -0
  143. data/spec/mongoid/persistable/pullable_spec.rb +72 -0
  144. data/spec/mongoid/persistable/pushable_spec.rb +72 -0
  145. data/spec/mongoid/persistable/renamable_spec.rb +36 -0
  146. data/spec/mongoid/persistable/savable_spec.rb +96 -0
  147. data/spec/mongoid/persistable/settable_spec.rb +37 -0
  148. data/spec/mongoid/persistable/unsettable_spec.rb +36 -0
  149. data/spec/mongoid/persistable/updatable_spec.rb +20 -28
  150. data/spec/mongoid/persistable/upsertable_spec.rb +80 -6
  151. data/spec/mongoid/persistence_context_spec.rb +7 -57
  152. data/spec/mongoid/query_cache_spec.rb +56 -61
  153. data/spec/mongoid/reloadable_spec.rb +24 -4
  154. data/spec/mongoid/scopable_spec.rb +70 -0
  155. data/spec/mongoid/serializable_spec.rb +9 -30
  156. data/spec/mongoid/shardable_models.rb +14 -0
  157. data/spec/mongoid/shardable_spec.rb +153 -61
  158. data/spec/mongoid/stateful_spec.rb +122 -8
  159. data/spec/mongoid/tasks/database_rake_spec.rb +74 -0
  160. data/spec/mongoid/tasks/database_spec.rb +127 -0
  161. data/spec/mongoid/timestamps_spec.rb +9 -11
  162. data/spec/mongoid/touchable_spec.rb +277 -5
  163. data/spec/mongoid/touchable_spec_models.rb +3 -1
  164. data/spec/mongoid/traversable_spec.rb +9 -24
  165. data/spec/mongoid/validatable/uniqueness_spec.rb +2 -3
  166. data/spec/mongoid_spec.rb +35 -9
  167. data/spec/shared/lib/mrss/docker_runner.rb +7 -0
  168. data/spec/shared/lib/mrss/event_subscriber.rb +15 -5
  169. data/spec/shared/lib/mrss/lite_constraints.rb +10 -2
  170. data/spec/shared/lib/mrss/server_version_registry.rb +16 -23
  171. data/spec/shared/lib/mrss/utils.rb +28 -6
  172. data/spec/shared/share/Dockerfile.erb +36 -40
  173. data/spec/shared/shlib/server.sh +32 -8
  174. data/spec/shared/shlib/set_env.sh +4 -4
  175. data/spec/spec_helper.rb +5 -0
  176. data/spec/support/immutable_ids.rb +118 -0
  177. data/spec/support/macros.rb +47 -15
  178. data/spec/support/models/artist.rb +0 -1
  179. data/spec/support/models/band.rb +1 -0
  180. data/spec/support/models/book.rb +1 -0
  181. data/spec/support/models/building.rb +2 -0
  182. data/spec/support/models/cover.rb +10 -0
  183. data/spec/support/models/product.rb +1 -0
  184. data.tar.gz.sig +0 -0
  185. metadata +700 -656
  186. metadata.gz.sig +0 -0
  187. data/spec/mongoid/criteria/queryable/extensions/bignum_spec.rb +0 -60
  188. data/spec/mongoid/criteria/queryable/extensions/fixnum_spec.rb +0 -60
@@ -80,15 +80,24 @@ module Mongoid
80
80
  # @example Do any documents exist in the null context.
81
81
  # context.exists?
82
82
  #
83
+ # @example Do any documents exist for given _id.
84
+ # context.exists?(BSON::ObjectId(...))
85
+ #
86
+ # @example Do any documents exist for given conditions.
87
+ # context.exists?(name: "...")
88
+ #
89
+ # @param [ Hash | Object | false ] id_or_conditions an _id to
90
+ # search for, a hash of conditions, nil or false.
91
+ #
83
92
  # @return [ false ] Always false.
84
- def exists?; false; end
93
+ def exists?(id_or_conditions = :none); false; end
85
94
 
86
95
  # Pluck the field values in null context.
87
96
  #
88
97
  # @example Get the values for null context.
89
98
  # context.pluck(:name)
90
99
  #
91
- # @param [ String | Symbol ] *_fields Field(s) to pluck.
100
+ # @param [ [ String | Symbol ]... ] *_fields Field(s) to pluck.
92
101
  #
93
102
  # @return [ Array ] An empty Array.
94
103
  def pluck(*_fields)
@@ -100,9 +109,9 @@ module Mongoid
100
109
  # @example Get the value for null context.
101
110
  # context.pick(:name)
102
111
  #
103
- # @param [ String | Symbol ] *_fields Field or fields to pick.
112
+ # @param [ [ String | Symbol ]... ] *_fields Field(s) to pick.
104
113
  #
105
- # @return [ nil ] Always reeturn nil.
114
+ # @return [ nil ] Always return nil.
106
115
  def pick(*_fields)
107
116
  nil
108
117
  end
@@ -136,11 +145,21 @@ module Mongoid
136
145
  #
137
146
  # @param [ Integer ] limit The number of documents to return.
138
147
  #
139
- # @return [ nil ] Always nil.
148
+ # @return [ [] | nil ] Empty array or nil.
140
149
  def first(limit = nil)
141
150
  [] unless limit.nil?
142
151
  end
143
152
 
153
+ # Always raises an error.
154
+ #
155
+ # @example Get the first document in null context.
156
+ # context.first!
157
+ #
158
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
159
+ def first!
160
+ raise_document_not_found_error
161
+ end
162
+
144
163
  # Always returns nil.
145
164
  #
146
165
  # @example Get the last document in null context.
@@ -148,11 +167,21 @@ module Mongoid
148
167
  #
149
168
  # @param [ Integer ] limit The number of documents to return.
150
169
  #
151
- # @return [ nil ] Always nil.
170
+ # @return [ [] | nil ] Empty array or nil.
152
171
  def last(limit = nil)
153
172
  [] unless limit.nil?
154
173
  end
155
174
 
175
+ # Always raises an error.
176
+ #
177
+ # @example Get the last document in null context.
178
+ # context.last!
179
+ #
180
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
181
+ def last!
182
+ raise_document_not_found_error
183
+ end
184
+
156
185
  # Returns nil or empty array.
157
186
  #
158
187
  # @example Take a document in null context.
@@ -172,7 +201,127 @@ module Mongoid
172
201
  #
173
202
  # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
174
203
  def take!
175
- raise Errors::DocumentNotFound.new(klass, nil, nil)
204
+ raise_document_not_found_error
205
+ end
206
+
207
+ # Always returns nil.
208
+ #
209
+ # @example Get the second document in null context.
210
+ # context.second
211
+ #
212
+ # @return [ nil ] Always nil.
213
+ def second
214
+ nil
215
+ end
216
+
217
+ # Always raises an error.
218
+ #
219
+ # @example Get the second document in null context.
220
+ # context.second!
221
+ #
222
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
223
+ def second!
224
+ raise_document_not_found_error
225
+ end
226
+
227
+ # Always returns nil.
228
+ #
229
+ # @example Get the third document in null context.
230
+ # context.third
231
+ #
232
+ # @return [ nil ] Always nil.
233
+ def third
234
+ nil
235
+ end
236
+
237
+ # Always raises an error.
238
+ #
239
+ # @example Get the third document in null context.
240
+ # context.third!
241
+ #
242
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
243
+ def third!
244
+ raise_document_not_found_error
245
+ end
246
+
247
+ # Always returns nil.
248
+ #
249
+ # @example Get the fourth document in null context.
250
+ # context.fourth
251
+ #
252
+ # @return [ nil ] Always nil.
253
+ def fourth
254
+ nil
255
+ end
256
+
257
+ # Always raises an error.
258
+ #
259
+ # @example Get the fourth document in null context.
260
+ # context.fourth!
261
+ #
262
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
263
+ def fourth!
264
+ raise_document_not_found_error
265
+ end
266
+
267
+ # Always returns nil.
268
+ #
269
+ # @example Get the fifth document in null context.
270
+ # context.fifth
271
+ #
272
+ # @return [ nil ] Always nil.
273
+ def fifth
274
+ nil
275
+ end
276
+
277
+ # Always raises an error.
278
+ #
279
+ # @example Get the fifth document in null context.
280
+ # context.fifth!
281
+ #
282
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
283
+ def fifth!
284
+ raise_document_not_found_error
285
+ end
286
+
287
+ # Always returns nil.
288
+ #
289
+ # @example Get the second to last document in null context.
290
+ # context.second_to_last
291
+ #
292
+ # @return [ nil ] Always nil.
293
+ def second_to_last
294
+ nil
295
+ end
296
+
297
+ # Always raises an error.
298
+ #
299
+ # @example Get the second to last document in null context.
300
+ # context.second_to_last!
301
+ #
302
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
303
+ def second_to_last!
304
+ raise_document_not_found_error
305
+ end
306
+
307
+ # Always returns nil.
308
+ #
309
+ # @example Get the third to last document in null context.
310
+ # context.third_to_last
311
+ #
312
+ # @return [ nil ] Always nil.
313
+ def third_to_last
314
+ nil
315
+ end
316
+
317
+ # Always raises an error.
318
+ #
319
+ # @example Get the third to last document in null context.
320
+ # context.third_to_last!
321
+ #
322
+ # @raises [ Mongoid::Errors::DocumentNotFound ] always raises.
323
+ def third_to_last!
324
+ raise_document_not_found_error
176
325
  end
177
326
 
178
327
  # Always returns zero.
@@ -188,6 +337,12 @@ module Mongoid
188
337
 
189
338
  alias :find_first :first
190
339
  alias :one :first
340
+
341
+ private
342
+
343
+ def raise_document_not_found_error
344
+ raise Errors::DocumentNotFound.new(klass, nil, nil)
345
+ end
191
346
  end
192
347
  end
193
348
  end
@@ -35,6 +35,18 @@ module Mongoid
35
35
  @context ||= create_context
36
36
  end
37
37
 
38
+ # Instructs the context to schedule an asynchronous loading of documents
39
+ # specified by the criteria.
40
+ #
41
+ # Note that depending on the context and on the Mongoid configuration,
42
+ # documents can be loaded synchronously on the caller's thread.
43
+ #
44
+ # @return [ Criteria ] Returns self.
45
+ def load_async
46
+ context.load_async if context.respond_to?(:load_async)
47
+ self
48
+ end
49
+
38
50
  private
39
51
 
40
52
  # Create the context for the queries to execute. Will be memory for
@@ -21,7 +21,7 @@ module Mongoid
21
21
  multi ? result : result.first
22
22
  end
23
23
 
24
- # Find the matchind document(s) in the criteria for the provided ids.
24
+ # Find the matching document(s) in the criteria for the provided id(s).
25
25
  #
26
26
  # @note Each argument can be an individual id, an array of ids or
27
27
  # a nested array. Each array will be flattened.
@@ -32,7 +32,7 @@ module Mongoid
32
32
  # @example Find by multiple ids.
33
33
  # criteria.find([ BSON::ObjectId.new, BSON::ObjectId.new ])
34
34
  #
35
- # @param [ Object | Array<Object> ] *args The ids to search for.
35
+ # @param [ [ Object | Array<Object> ]... ] *args The id(s) to find.
36
36
  #
37
37
  # @return [ Document | Array<Document> ] The matching document(s).
38
38
  def find(*args)
@@ -21,8 +21,8 @@ module Mongoid
21
21
  # @example Eager load the provided associations.
22
22
  # Person.includes(:posts, :game)
23
23
  #
24
- # @param [ Array<Symbol>, Array<Hash> ] relations The names of the associations to eager
25
- # load.
24
+ # @param [ [ Symbol | Hash ]... ] *relations The names of the association(s)
25
+ # to eager load.
26
26
  #
27
27
  # @return [ Criteria ] The cloned criteria.
28
28
  def includes(*relations)
@@ -70,7 +70,8 @@ module Mongoid
70
70
  # association originates.
71
71
  # @param [ String ] parent The name of the association above this one in
72
72
  # the inclusion tree, if it is a nested inclusion.
73
- # @param relations_list The names of the associations to eager load.
73
+ # @param [ [ Symbol | Hash | Array<Symbol | Hash> ]... ] *relations_list
74
+ # The names of the association(s) to eager load.
74
75
  def extract_includes_list(_parent_class, parent, *relations_list)
75
76
  relations_list.flatten.each do |relation_object|
76
77
  if relation_object.is_a?(Hash)
@@ -105,7 +105,7 @@ module Mongoid
105
105
  #
106
106
  # @return [ Hash ] The field/direction pair.
107
107
  def __sort_pair__
108
- { first => last.to_direction }
108
+ { first => Mongoid::Criteria::Translator.to_direction(last) }
109
109
  end
110
110
 
111
111
  private
@@ -115,7 +115,7 @@ module Mongoid
115
115
  def __sort_option__
116
116
  tap do |hash|
117
117
  hash.each_pair do |key, value|
118
- hash.store(key, value.to_direction)
118
+ hash.store(key, Mongoid::Criteria::Translator.to_direction(value))
119
119
  end
120
120
  end
121
121
  end
@@ -30,14 +30,6 @@ module Mongoid
30
30
  ::Time.at(self).utc
31
31
  end
32
32
 
33
- # Get the integer as a sort direction.
34
- #
35
- # @example Get the integer as a sort direction.
36
- # 1.to_direction
37
- #
38
- # @return [ Integer ] self.
39
- def to_direction; self; end
40
-
41
33
  module ClassMethods
42
34
 
43
35
  # Get the object as a numeric.
@@ -49,7 +49,7 @@ module Mongoid
49
49
  split(/,/).inject({}) do |hash, spec|
50
50
  hash.tap do |_hash|
51
51
  field, direction = spec.strip.split(/\s/)
52
- _hash[field.to_sym] = direction.to_direction
52
+ _hash[field.to_sym] = Mongoid::Criteria::Translator.to_direction(direction)
53
53
  end
54
54
  end
55
55
  end
@@ -67,16 +67,6 @@ module Mongoid
67
67
  ::String.__expr_part__(self, value, negating)
68
68
  end
69
69
 
70
- # Get the string as a sort direction.
71
- #
72
- # @example Get the string as a sort direction.
73
- # "1".to_direction
74
- #
75
- # @return [ Integer ] The direction.
76
- def to_direction
77
- self =~ /desc/i ? -1 : 1
78
- end
79
-
80
70
  module ClassMethods
81
71
 
82
72
  # Get the value as a expression.
@@ -21,16 +21,6 @@ module Mongoid
21
21
  ::String.__expr_part__(self, value, negating)
22
22
  end
23
23
 
24
- # Get the symbol as a sort direction.
25
- #
26
- # @example Get the symbol as a sort direction.
27
- # "1".to_direction
28
- #
29
- # @return [ Integer ] The direction.
30
- def to_direction
31
- to_s.to_direction
32
- end
33
-
34
24
  module ClassMethods
35
25
 
36
26
  # Adds a method on symbol as a convenience for the MongoDB operator.
@@ -91,7 +91,7 @@ module Mongoid
91
91
 
92
92
  # Calculate the hash code for a key.
93
93
  #
94
- # @return [ Fixnum ] The hash code for the key.
94
+ # @return [ Integer ] The hash code for the key.
95
95
  def hash
96
96
  [name, operator, expanded].hash
97
97
  end
@@ -283,7 +283,7 @@ module Mongoid
283
283
  # The new value is a simple value.
284
284
  # Transform the implicit equality to either $eq or $regexp
285
285
  # depending on the type of the argument. See
286
- # https://docs.mongodb.com/manual/reference/operator/query/eq/#std-label-eq-usage-examples
286
+ # https://www.mongodb.com/docs/manual/reference/operator/query/eq/#std-label-eq-usage-examples
287
287
  # for the description of relevant server behavior.
288
288
  op = case v
289
289
  when Regexp, BSON::Regexp::Raw
@@ -17,7 +17,7 @@ module Mongoid
17
17
  # @example Add ascending sorting.
18
18
  # optional.ascending(:first_name, :last_name)
19
19
  #
20
- # @param [ Array<Symbol> ] fields The fields to sort.
20
+ # @param [ Symbol... ] *fields The field(s) to sort.
21
21
  #
22
22
  # @return [ Optional ] The cloned optional.
23
23
  def ascending(*fields)
@@ -45,7 +45,7 @@ module Mongoid
45
45
  # @example Add descending sorting.
46
46
  # optional.descending(:first_name, :last_name)
47
47
  #
48
- # @param [ Array<Symbol> ] fields The fields to sort.
48
+ # @param [ Symbol... ] *fields The field(s) to sort.
49
49
  #
50
50
  # @return [ Optional ] The cloned optional.
51
51
  def descending(*fields)
@@ -123,7 +123,7 @@ module Mongoid
123
123
  # @example Limit the results to the provided fields.
124
124
  # optional.only(:name, :dob)
125
125
  #
126
- # @param [ Array<Symbol> ] args The fields to return.
126
+ # @param [ Symbol... ] *args The field(s) to return.
127
127
  #
128
128
  # @return [ Optional ] The cloned optional.
129
129
  def only(*args)
@@ -163,7 +163,7 @@ module Mongoid
163
163
  # @example Add sorting options via a string.
164
164
  # optional.order_by("name ASC, dob DESC")
165
165
  #
166
- # @param [ Array | Hash | String ] spec The sorting specification.
166
+ # @param [ [ Array | Hash | String ]... ] *spec The sorting specification.
167
167
  #
168
168
  # @return [ Optional ] The cloned optional.
169
169
  def order_by(*spec)
@@ -184,7 +184,7 @@ module Mongoid
184
184
  # @example Replace the ordering.
185
185
  # optional.reorder(name: :asc)
186
186
  #
187
- # @param [ Array | Hash | String ] spec The sorting specification.
187
+ # @param [ [ Array | Hash | String ]... ] *spec The sorting specification.
188
188
  #
189
189
  # @return [ Optional ] The cloned optional.
190
190
  def reorder(*spec)
@@ -245,7 +245,7 @@ module Mongoid
245
245
  # @example Limit the results to the fields not provided.
246
246
  # optional.without(:name, :dob)
247
247
  #
248
- # @param [ Array<Symbol> ] args The fields to ignore.
248
+ # @param [ Symbol... ] *args The field(s) to ignore.
249
249
  #
250
250
  # @return [ Optional ] The cloned optional.
251
251
  def without(*args)
@@ -331,7 +331,7 @@ module Mongoid
331
331
  # @example Store the option.
332
332
  # optional.option({ skip: 10 })
333
333
  #
334
- # @param [ Array ] args The options.
334
+ # @param [ Object... ] *args The options.
335
335
  #
336
336
  # @return [ Queryable ] The cloned queryable.
337
337
  def option(*args)
@@ -349,7 +349,7 @@ module Mongoid
349
349
  # @example Add multiple sort options.
350
350
  # optional.sort_with_list(:name, :dob, 1)
351
351
  #
352
- # @param [ Array<String> ] fields The field names.
352
+ # @param [ [ Symbol | String ]... ] *fields The field name(s).
353
353
  # @param [ Integer ] direction The sort direction.
354
354
  #
355
355
  # @return [ Optional ] The cloned optional.
@@ -31,7 +31,7 @@ module Mongoid
31
31
  # @example Execute an $all in a where query.
32
32
  # selectable.where(:field.all => [ 1, 2 ])
33
33
  #
34
- # @param [ Hash ] criterion The key value pairs for $all matching.
34
+ # @param [ Hash... ] *criteria The key value pair(s) for $all matching.
35
35
  #
36
36
  # @return [ Selectable ] The cloned selectable.
37
37
  def all(*criteria)
@@ -69,8 +69,9 @@ module Mongoid
69
69
  # @example Add the criterion.
70
70
  # selectable.and({ field: value }, { other: value })
71
71
  #
72
- # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
73
- # matches or Criteria objects that all must match to return results.
72
+ # @param [ [ Hash | Criteria | Array<Hash | Criteria> ]... ] *criteria
73
+ # Multiple key/value pair matches or Criteria objects that all must
74
+ # match to return results.
74
75
  #
75
76
  # @return [ Selectable ] The new selectable.
76
77
  def and(*criteria)
@@ -199,7 +200,7 @@ module Mongoid
199
200
  # the upper right (north east) as the second argument.
200
201
  # Important: When latitude and longitude are passed, longitude is
201
202
  # expected as the first element of the coordinate pair.
202
- # Source: https://docs.mongodb.com/manual/reference/operator/query/box/
203
+ # Source: https://www.mongodb.com/docs/manual/reference/operator/query/box/
203
204
  #
204
205
  # @example Add a geo intersect criterion for a line.
205
206
  # query.geo_spatial(:location.intersects_line => [[ 1, 10 ], [ 2, 10 ]])
@@ -516,8 +517,8 @@ module Mongoid
516
517
  # @example Add the $nor selection.
517
518
  # selectable.nor(field: 1, field: 2)
518
519
  #
519
- # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
520
- # matches or Criteria objects.
520
+ # @param [ [ Hash | Criteria | Array<Hash | Criteria> ]... ] *criteria
521
+ # Multiple key/value pair matches or Criteria objects.
521
522
  #
522
523
  # @return [ Selectable ] The new selectable.
523
524
  def nor(*criteria)
@@ -545,7 +546,7 @@ module Mongoid
545
546
  # @example Execute a $not in a where query.
546
547
  # selectable.where(:field.not => /Bob/)
547
548
  #
548
- # @param [ Array<Hash | Criteria> ] criteria Multiple key/value pair
549
+ # @param [ [ Hash | Criteria ]... ] *criteria The key/value pair
549
550
  # matches or Criteria objects to negate.
550
551
  #
551
552
  # @return [ Selectable ] The new selectable.
@@ -580,6 +581,35 @@ module Mongoid
580
581
  end
581
582
  key :not, :override, "$not"
582
583
 
584
+ # Negate the arguments, constraining the query to only those documents
585
+ # that do NOT match the arguments.
586
+ #
587
+ # @example Exclude a single criterion.
588
+ # selectable.none_of(name: /Bob/)
589
+ #
590
+ # @example Exclude multiple criteria.
591
+ # selectable.none_of(name: /Bob/, country: "USA")
592
+ #
593
+ # @example Exclude multiple criteria as an array.
594
+ # selectable.none_of([{ name: /Bob/ }, { country: "USA" }])
595
+ #
596
+ # @param [ [ Hash | Criteria ]... ] *criteria The key/value pair
597
+ # matches or Criteria objects to negate.
598
+ #
599
+ # @return [ Selectable ] The new selectable.
600
+ def none_of(*criteria)
601
+ criteria = _mongoid_flatten_arrays(criteria)
602
+ return dup if criteria.empty?
603
+
604
+ exprs = criteria.map do |criterion|
605
+ _mongoid_expand_keys(
606
+ criterion.is_a?(Selectable) ?
607
+ criterion.selector : criterion)
608
+ end
609
+
610
+ self.and('$nor' => exprs)
611
+ end
612
+
583
613
  # Creates a disjunction using $or from the existing criteria in the
584
614
  # receiver and the provided arguments.
585
615
  #
@@ -605,7 +635,7 @@ module Mongoid
605
635
  # @example Same as previous example, also deprecated.
606
636
  # selectable.or([{field: 1}], [{field: 2}])
607
637
  #
608
- # @param [ Hash | Criteria | Array<Hash | Criteria>, ... ] criteria
638
+ # @param [ [ Hash | Criteria | Array<Hash | Criteria> ]... ] *criteria
609
639
  # Multiple key/value pair matches or Criteria objects, or arrays
610
640
  # thereof. Passing arrays is deprecated.
611
641
  #
@@ -635,7 +665,7 @@ module Mongoid
635
665
  # @example Same as previous example, also deprecated.
636
666
  # selectable.any_of([{field: 1}], [{field: 2}])
637
667
  #
638
- # @param [ Hash | Criteria | Array<Hash | Criteria>, ... ] criteria
668
+ # @param [ [ Hash | Criteria | Array<Hash | Criteria> ]... ] *criteria
639
669
  # Multiple key/value pair matches or Criteria objects, or arrays
640
670
  # thereof. Passing arrays is deprecated.
641
671
  #
@@ -731,7 +761,7 @@ module Mongoid
731
761
  # @example Construct a text search selector with options.
732
762
  # selectable.text_search("testing", :$language => "fr")
733
763
  #
734
- # @note Per https://docs.mongodb.com/manual/reference/operator/query/text/
764
+ # @note Per https://www.mongodb.com/docs/manual/reference/operator/query/text/
735
765
  # it is not currently possible to supply multiple text search
736
766
  # conditions in a query. Mongoid will build such a query but the
737
767
  # server will return an error when trying to execute it.
@@ -751,7 +781,7 @@ module Mongoid
751
781
  criterion = {'$text' => { '$search' => terms }}
752
782
  criterion['$text'].merge!(opts) if opts
753
783
  if query.selector['$text']
754
- # Per https://docs.mongodb.com/manual/reference/operator/query/text/
784
+ # Per https://www.mongodb.com/docs/manual/reference/operator/query/text/
755
785
  # multiple $text expressions are not currently supported by
756
786
  # MongoDB server, but build the query correctly instead of
757
787
  # overwriting previous text search condition with the currently
@@ -774,7 +804,8 @@ module Mongoid
774
804
  # @example Add a javascript selection.
775
805
  # selectable.where("this.name == 'syd'")
776
806
  #
777
- # @param [ String | Hash ] criterion The javascript or standard selection.
807
+ # @param [ [ Hash | String ]... ] *criterion The standard selection
808
+ # or javascript string.
778
809
  #
779
810
  # @return [ Selectable ] The cloned selectable.
780
811
  def where(*criteria)
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Mongoid
4
+ class Criteria
5
+
6
+ # This is a helper module for translating atomic and composite
7
+ # Ruby values into corresponding query and option components.
8
+ # Originally implemented as patches to core classes, that approach
9
+ # has generally fallen into disfavor, as it bleeds too much into
10
+ # the public namespace.
11
+ #
12
+ # @api private
13
+ module Translator
14
+ extend self
15
+
16
+ # Converts the given value to a direction specification for use in
17
+ # sorting.
18
+ #
19
+ # @example Convert the value to a direction.
20
+ # Translator.to_direction(:desc)
21
+ # Translator.to_direction("1")
22
+ # Translator.to_direction(-1)
23
+ # Translator.to_direction(score: { "$meta": "textScore" })
24
+ #
25
+ # @param [ Hash | Numeric | String | Symbol ] value The value to convert.
26
+ #
27
+ # @return [ Hash | Numeric ] The direction.
28
+ def to_direction(value)
29
+ case value
30
+ when Hash then
31
+ value
32
+ when Numeric then
33
+ value
34
+ when String then
35
+ value =~ /desc/i ? -1 : 1
36
+ when Symbol then
37
+ to_direction(value.to_s)
38
+ else
39
+ raise ArgumentError, "cannot translate #{value.inspect} (#{value.class}) to a direction specification"
40
+ end
41
+ end
42
+ end
43
+
44
+ end
45
+ end
@@ -8,6 +8,7 @@ require "mongoid/criteria/modifiable"
8
8
  require "mongoid/criteria/queryable"
9
9
  require "mongoid/criteria/scopable"
10
10
  require "mongoid/criteria/options"
11
+ require "mongoid/criteria/translator"
11
12
 
12
13
  module Mongoid
13
14
 
@@ -88,7 +89,7 @@ module Mongoid
88
89
  # @example Tries to find a document whose _id is the stringification of the provided Proc, typically failing.
89
90
  # enumerator = criteria.find(-> { "Default Band" })
90
91
  #
91
- # @param [ Object | Array<Object> ] *args The ids.
92
+ # @param [ [ Object | Array<Object> ]... ] *args The id(s).
92
93
  # @param [ Proc ] block Optional block to pass.
93
94
  #
94
95
  # @return [ Document | Array<Document> | nil ] A document or matching documents.
@@ -284,7 +285,7 @@ module Mongoid
284
285
  # @example Limit the fields returned from the database.
285
286
  # Band.only(:name)
286
287
  #
287
- # @param [ Array<Symbol> ] args The names of the fields.
288
+ # @param [ [ Symbol | Array<Symbol> ]... ] *args The field name(s).
288
289
  #
289
290
  # @return [ Criteria ] The cloned criteria.
290
291
  def only(*args)
@@ -318,7 +319,7 @@ module Mongoid
318
319
  # @example Exclude fields returned from the database.
319
320
  # Band.without(:name)
320
321
  #
321
- # @param [ Array<Symbol> ] args The names of the fields.
322
+ # @param [ Symbol... ] *args The field name(s).
322
323
  #
323
324
  # @return [ Criteria ] The cloned criteria.
324
325
  def without(*args)
@@ -385,7 +386,8 @@ module Mongoid
385
386
  # @example Add a javascript selection.
386
387
  # criteria.where("this.name == 'syd'")
387
388
  #
388
- # @param [ String | Hash ] expression The javascript or standard selection.
389
+ # @param [ [ Hash | String ]... ] *args The standard selection
390
+ # or javascript string.
389
391
  #
390
392
  # @raise [ UnsupportedJavascript ] If provided a string and the criteria
391
393
  # is embedded.
@@ -495,7 +497,7 @@ module Mongoid
495
497
  # criteria.method_missing(:name)
496
498
  #
497
499
  # @param [ Symbol ] name The method name.
498
- # @param [ Array ] args The arguments.
500
+ # @param [ Object... ] *args The arguments.
499
501
  #
500
502
  # @return [ Object ] The result of the method call.
501
503
  ruby2_keywords def method_missing(name, *args, &block)