mongoid 7.4.3 → 7.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/lib/config/locales/en.yml +7 -0
- data/lib/mongoid/association/embedded/batchable.rb +3 -20
- data/lib/mongoid/association/macros.rb +20 -0
- data/lib/mongoid/association/referenced/has_many/enumerable.rb +12 -8
- data/lib/mongoid/association/referenced/has_many/proxy.rb +2 -2
- data/lib/mongoid/atomic/paths/embedded/many.rb +0 -19
- data/lib/mongoid/config.rb +6 -1
- data/lib/mongoid/contextual/memory.rb +144 -12
- data/lib/mongoid/contextual/mongo.rb +118 -26
- data/lib/mongoid/contextual/none.rb +45 -1
- data/lib/mongoid/criteria/queryable/extensions/array.rb +2 -0
- data/lib/mongoid/criteria/queryable/extensions/hash.rb +2 -0
- data/lib/mongoid/criteria/queryable/mergeable.rb +21 -0
- data/lib/mongoid/criteria/queryable/selectable.rb +26 -10
- data/lib/mongoid/criteria.rb +2 -0
- data/lib/mongoid/document.rb +2 -0
- data/lib/mongoid/equality.rb +4 -4
- data/lib/mongoid/errors/document_not_found.rb +23 -6
- data/lib/mongoid/fields.rb +145 -21
- data/lib/mongoid/findable.rb +20 -5
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/warnings.rb +29 -0
- data/lib/mongoid.rb +1 -0
- data/lib/rails/generators/mongoid/config/templates/mongoid.yml +4 -3
- data/spec/integration/i18n_fallbacks_spec.rb +15 -1
- data/spec/mongoid/association/embedded/embeds_many/proxy_spec.rb +0 -21
- data/spec/mongoid/association/embedded/embeds_many_models.rb +0 -121
- data/spec/mongoid/association/referenced/has_and_belongs_to_many/proxy_spec.rb +0 -8
- data/spec/mongoid/association/referenced/has_many/enumerable_spec.rb +54 -0
- data/spec/mongoid/association/referenced/has_many/proxy_spec.rb +8 -24
- data/spec/mongoid/clients/options_spec.rb +1 -0
- data/spec/mongoid/config_spec.rb +10 -4
- data/spec/mongoid/contextual/memory_spec.rb +826 -65
- data/spec/mongoid/contextual/mongo_spec.rb +781 -18
- data/spec/mongoid/contextual/none_spec.rb +46 -0
- data/spec/mongoid/criteria/queryable/selectable_spec.rb +212 -39
- data/spec/mongoid/criteria_spec.rb +8 -0
- data/spec/mongoid/equality_spec.rb +12 -12
- data/spec/mongoid/errors/document_not_found_spec.rb +49 -0
- data/spec/mongoid/findable_spec.rb +30 -0
- data/spec/support/models/code.rb +2 -0
- data.tar.gz.sig +0 -0
- metadata +3 -2
- metadata.gz.sig +0 -0
@@ -52,6 +52,27 @@ module Mongoid
|
|
52
52
|
self
|
53
53
|
end
|
54
54
|
|
55
|
+
# Merge criteria with operators using the and operator.
|
56
|
+
#
|
57
|
+
# @param [ Hash ] criterion The criterion to add to the criteria.
|
58
|
+
# @param [ String ] operator The MongoDB operator.
|
59
|
+
#
|
60
|
+
# @return [ Criteria ] The resulting criteria.
|
61
|
+
def and_with_operator(criterion, operator)
|
62
|
+
crit = self
|
63
|
+
if criterion
|
64
|
+
criterion.each_pair do |field, value|
|
65
|
+
val = prepare(field, operator, value)
|
66
|
+
# The prepare method already takes the negation into account. We
|
67
|
+
# set negating to false here so that ``and`` doesn't also apply
|
68
|
+
# negation and we have a double negative.
|
69
|
+
crit.negating = false
|
70
|
+
crit = crit.and(field => val)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
crit
|
74
|
+
end
|
75
|
+
|
55
76
|
private
|
56
77
|
|
57
78
|
# Adds the criterion to the existing selection.
|
@@ -154,7 +154,7 @@ module Mongoid
|
|
154
154
|
raise Errors::CriteriaArgumentRequired, :elem_match
|
155
155
|
end
|
156
156
|
|
157
|
-
|
157
|
+
and_or_override(criterion, "$elemMatch")
|
158
158
|
end
|
159
159
|
key :elem_match, :override, "$elemMatch"
|
160
160
|
|
@@ -270,7 +270,7 @@ module Mongoid
|
|
270
270
|
raise Errors::CriteriaArgumentRequired, :eq
|
271
271
|
end
|
272
272
|
|
273
|
-
|
273
|
+
and_or_override(criterion, "$eq")
|
274
274
|
end
|
275
275
|
key :eq, :override, "$eq"
|
276
276
|
|
@@ -290,7 +290,7 @@ module Mongoid
|
|
290
290
|
raise Errors::CriteriaArgumentRequired, :gt
|
291
291
|
end
|
292
292
|
|
293
|
-
|
293
|
+
and_or_override(criterion, "$gt")
|
294
294
|
end
|
295
295
|
key :gt, :override, "$gt"
|
296
296
|
|
@@ -310,7 +310,7 @@ module Mongoid
|
|
310
310
|
raise Errors::CriteriaArgumentRequired, :gte
|
311
311
|
end
|
312
312
|
|
313
|
-
|
313
|
+
and_or_override(criterion, "$gte")
|
314
314
|
end
|
315
315
|
key :gte, :override, "$gte"
|
316
316
|
|
@@ -366,7 +366,7 @@ module Mongoid
|
|
366
366
|
raise Errors::CriteriaArgumentRequired, :lt
|
367
367
|
end
|
368
368
|
|
369
|
-
|
369
|
+
and_or_override(criterion, "$lt")
|
370
370
|
end
|
371
371
|
key :lt, :override, "$lt"
|
372
372
|
|
@@ -386,7 +386,7 @@ module Mongoid
|
|
386
386
|
raise Errors::CriteriaArgumentRequired, :lte
|
387
387
|
end
|
388
388
|
|
389
|
-
|
389
|
+
and_or_override(criterion, "$lte")
|
390
390
|
end
|
391
391
|
key :lte, :override, "$lte"
|
392
392
|
|
@@ -423,7 +423,7 @@ module Mongoid
|
|
423
423
|
raise Errors::CriteriaArgumentRequired, :mod
|
424
424
|
end
|
425
425
|
|
426
|
-
|
426
|
+
and_or_override(criterion, "$mod")
|
427
427
|
end
|
428
428
|
key :mod, :override, "$mod"
|
429
429
|
|
@@ -443,7 +443,7 @@ module Mongoid
|
|
443
443
|
raise Errors::CriteriaArgumentRequired, :ne
|
444
444
|
end
|
445
445
|
|
446
|
-
|
446
|
+
and_or_override(criterion, "$ne")
|
447
447
|
end
|
448
448
|
alias :excludes :ne
|
449
449
|
key :ne, :override, "$ne"
|
@@ -464,7 +464,7 @@ module Mongoid
|
|
464
464
|
raise Errors::CriteriaArgumentRequired, :near
|
465
465
|
end
|
466
466
|
|
467
|
-
|
467
|
+
and_or_override(criterion, "$near")
|
468
468
|
end
|
469
469
|
key :near, :override, "$near"
|
470
470
|
|
@@ -484,7 +484,7 @@ module Mongoid
|
|
484
484
|
raise Errors::CriteriaArgumentRequired, :near_sphere
|
485
485
|
end
|
486
486
|
|
487
|
-
|
487
|
+
and_or_override(criterion, "$nearSphere")
|
488
488
|
end
|
489
489
|
key :near_sphere, :override, "$nearSphere"
|
490
490
|
|
@@ -924,6 +924,22 @@ module Mongoid
|
|
924
924
|
end
|
925
925
|
end
|
926
926
|
|
927
|
+
# Combine operator expessions onto a Criteria using either
|
928
|
+
# an override or ands depending on the status of the
|
929
|
+
# Mongoid.overwrite_chained_operators feature flag.
|
930
|
+
#
|
931
|
+
# @param [ Hash ] The criterion to add to the criteria.
|
932
|
+
# @param [ String ] operator The MongoDB operator.
|
933
|
+
#
|
934
|
+
# @return [ Criteria ] The resulting criteria.
|
935
|
+
def and_or_override(criterion, operator)
|
936
|
+
if Mongoid.overwrite_chained_operators
|
937
|
+
__override__(criterion, operator)
|
938
|
+
else
|
939
|
+
and_with_operator(criterion, operator)
|
940
|
+
end
|
941
|
+
end
|
942
|
+
|
927
943
|
class << self
|
928
944
|
|
929
945
|
# Get the methods on the selectable that can be forwarded to from a model.
|
data/lib/mongoid/criteria.rb
CHANGED
@@ -122,6 +122,7 @@ module Mongoid
|
|
122
122
|
#
|
123
123
|
# @return [ Criteria ] The cloned criteria.
|
124
124
|
def cache
|
125
|
+
Mongoid::Warnings.warn_criteria_cache_deprecated
|
125
126
|
crit = clone
|
126
127
|
crit.options.merge!(cache: true)
|
127
128
|
crit
|
@@ -134,6 +135,7 @@ module Mongoid
|
|
134
135
|
#
|
135
136
|
# @return [ true, false ] If the criteria is flagged as cached.
|
136
137
|
def cached?
|
138
|
+
Mongoid::Warnings.warn_criteria_cache_deprecated
|
137
139
|
options[:cache] == true
|
138
140
|
end
|
139
141
|
|
data/lib/mongoid/document.rb
CHANGED
data/lib/mongoid/equality.rb
CHANGED
@@ -44,9 +44,9 @@ module Mongoid
|
|
44
44
|
# @return [ true, false ] True if the classes are equal, false if not.
|
45
45
|
def ===(other)
|
46
46
|
if Mongoid.legacy_triple_equals
|
47
|
-
other.class == Class ? self.class === other : self == other
|
48
|
-
else
|
49
47
|
super
|
48
|
+
else
|
49
|
+
other.class == Class ? self.class === other : self == other
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -73,9 +73,9 @@ module Mongoid
|
|
73
73
|
# @return [ true, false ] True if the classes are equal, false if not.
|
74
74
|
def ===(other)
|
75
75
|
if Mongoid.legacy_triple_equals
|
76
|
-
other.class == Class ? self <= other : other.is_a?(self)
|
77
|
-
else
|
78
76
|
other.is_a?(self)
|
77
|
+
else
|
78
|
+
other.class == Class ? self <= other : other.is_a?(self)
|
79
79
|
end
|
80
80
|
end
|
81
81
|
end
|
@@ -23,13 +23,13 @@ module Mongoid
|
|
23
23
|
# @param [ Array ] unmatched The unmatched ids, if appropriate
|
24
24
|
def initialize(klass, params, unmatched = nil)
|
25
25
|
if !unmatched && !params.is_a?(Hash)
|
26
|
-
unmatched = Array(params)
|
26
|
+
unmatched = Array(params) if params
|
27
27
|
end
|
28
28
|
|
29
29
|
@klass, @params = klass, params
|
30
30
|
super(
|
31
31
|
compose_message(
|
32
|
-
message_key(params),
|
32
|
+
message_key(params, unmatched),
|
33
33
|
{
|
34
34
|
klass: klass.name,
|
35
35
|
searched: searched(params),
|
@@ -93,10 +93,27 @@ module Mongoid
|
|
93
93
|
# error.problem
|
94
94
|
#
|
95
95
|
# @return [ String ] The problem.
|
96
|
-
def message_key(params)
|
97
|
-
|
98
|
-
|
99
|
-
|
96
|
+
def message_key(params, unmatched)
|
97
|
+
if !params && !unmatched
|
98
|
+
"no_documents_found"
|
99
|
+
elsif Hash === params
|
100
|
+
"document_with_attributes_not_found"
|
101
|
+
elsif Hash === unmatched && unmatched.size >= 2
|
102
|
+
"document_with_shard_key_not_found"
|
103
|
+
else
|
104
|
+
"document_not_found"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
# Get the shard key from the unmatched hash.
|
109
|
+
#
|
110
|
+
# @return [ String ] the shard key and value.
|
111
|
+
def shard_key(unmatched)
|
112
|
+
if Hash === unmatched
|
113
|
+
h = unmatched.dup
|
114
|
+
h.delete("_id")
|
115
|
+
h.delete(:_id)
|
116
|
+
h.map{|k,v| "#{k}: #{v}" }.join(", ")
|
100
117
|
end
|
101
118
|
end
|
102
119
|
end
|
data/lib/mongoid/fields.rb
CHANGED
@@ -270,21 +270,64 @@ module Mongoid
|
|
270
270
|
def options
|
271
271
|
@options ||= {}
|
272
272
|
end
|
273
|
-
end
|
274
|
-
|
275
|
-
module ClassMethods
|
276
273
|
|
277
|
-
#
|
274
|
+
# Traverse down the association tree and search for the field for the
|
275
|
+
# given key. To do this, split the key by '.' and for each part (meth) of
|
276
|
+
# the key:
|
278
277
|
#
|
279
|
-
#
|
280
|
-
#
|
278
|
+
# - If the meth is a field, yield the meth, field, and is_field as true.
|
279
|
+
# - If the meth is an association, update the klass to the association's
|
280
|
+
# klass, and yield the meth, klass, and is_field as false.
|
281
281
|
#
|
282
|
-
#
|
283
|
-
#
|
282
|
+
# The next iteration will use klass's fields and associations to continue
|
283
|
+
# traversing the tree.
|
284
284
|
#
|
285
|
-
# @
|
286
|
-
|
287
|
-
|
285
|
+
# @param [ String ] key The key used to search the association tree.
|
286
|
+
# @param [ Hash ] fields The fields to begin the search with.
|
287
|
+
# @param [ Hash ] associations The associations to begin the search with.
|
288
|
+
# @param [ Hash ] aliased_associations The alaised associations to begin
|
289
|
+
# the search with.
|
290
|
+
# @param [ Proc ] block The block takes in three paramaters, the current
|
291
|
+
# meth, the field or the relation, and whether the second parameter is a
|
292
|
+
# field or not.
|
293
|
+
#
|
294
|
+
# @return [ Field ] The field found for the given key at the end of the
|
295
|
+
# search. This will return nil if the last thing found is an association
|
296
|
+
# or no field was found for the given key.
|
297
|
+
#
|
298
|
+
# @api private
|
299
|
+
def traverse_association_tree(key, fields, associations, aliased_associations)
|
300
|
+
klass = nil
|
301
|
+
field = nil
|
302
|
+
key.split('.').each_with_index do |meth, i|
|
303
|
+
fs = i == 0 ? fields : klass&.fields
|
304
|
+
rs = i == 0 ? associations : klass&.relations
|
305
|
+
as = i == 0 ? aliased_associations : klass&.aliased_associations
|
306
|
+
|
307
|
+
# Associations can possibly have two "keys", their name and their alias.
|
308
|
+
# The fields name is what is used to store it in the klass's relations
|
309
|
+
# and field hashes, and the alias is what's used to store that field
|
310
|
+
# in the database. The key inputted to this function is the aliased
|
311
|
+
# key. We can convert them back to their names by looking in the
|
312
|
+
# aliased_associations hash.
|
313
|
+
aliased = meth
|
314
|
+
if as && a = as.fetch(meth, nil)
|
315
|
+
aliased = a.to_s
|
316
|
+
end
|
317
|
+
|
318
|
+
field = nil
|
319
|
+
klass = nil
|
320
|
+
if fs && f = fs[aliased]
|
321
|
+
field = f
|
322
|
+
yield(meth, f, true) if block_given?
|
323
|
+
elsif rs && rel = rs[aliased]
|
324
|
+
klass = rel.klass
|
325
|
+
yield(meth, rel, false) if block_given?
|
326
|
+
else
|
327
|
+
yield(meth, nil, false) if block_given?
|
328
|
+
end
|
329
|
+
end
|
330
|
+
field
|
288
331
|
end
|
289
332
|
|
290
333
|
# Get the name of the provided field as it is stored in the database.
|
@@ -292,16 +335,43 @@ module Mongoid
|
|
292
335
|
# finds aliases for embedded documents and fields, delimited with
|
293
336
|
# period "." character.
|
294
337
|
#
|
295
|
-
#
|
296
|
-
#
|
338
|
+
# Note that this method returns the name of associations as they're
|
339
|
+
# stored in the database, whereas the `relations` hash uses their in-code
|
340
|
+
# aliases. In order to check for membership in the relations hash, you
|
341
|
+
# would first have to look up the string returned from this method in
|
342
|
+
# the aliased_associations hash.
|
343
|
+
#
|
344
|
+
# This method will not expand the alias of a belongs_to association that
|
345
|
+
# is not the last item. For example, if we had a School that has_many
|
346
|
+
# Students, and the field name passed was (from the Student's perspective):
|
347
|
+
#
|
348
|
+
# school._id
|
349
|
+
#
|
350
|
+
# The alias for a belongs_to association is that association's _id field.
|
351
|
+
# Therefore, expanding out this association would yield:
|
352
|
+
#
|
353
|
+
# school_id._id
|
297
354
|
#
|
298
|
-
#
|
299
|
-
#
|
355
|
+
# This is not the correct field name, because the intention here was not
|
356
|
+
# to get a property of the _id field. The intention was to get a property
|
357
|
+
# of the referenced document. Therefore, if a part of the name passed is
|
358
|
+
# a belongs_to association that is not the last part of the name, we
|
359
|
+
# won't expand its alias, and return:
|
360
|
+
#
|
361
|
+
# school._id
|
362
|
+
#
|
363
|
+
# If the belongs_to association is the last part of the name, we will
|
364
|
+
# pass back the _id field.
|
300
365
|
#
|
301
366
|
# @param [ String, Symbol ] name The name to get.
|
367
|
+
# @param [ Hash ] relations The associations.
|
368
|
+
# @param [ Hash ] alaiased_fields The aliased fields.
|
369
|
+
# @param [ Hash ] alaiased_associations The aliased associations.
|
302
370
|
#
|
303
371
|
# @return [ String ] The name of the field as stored in the database.
|
304
|
-
|
372
|
+
#
|
373
|
+
# @api private
|
374
|
+
def database_field_name(name, relations, aliased_fields, aliased_associations)
|
305
375
|
if Mongoid.broken_alias_handling
|
306
376
|
return nil unless name
|
307
377
|
normalized = name.to_s
|
@@ -310,31 +380,68 @@ module Mongoid
|
|
310
380
|
return nil unless name.present?
|
311
381
|
key = name.to_s
|
312
382
|
segment, remaining = key.split('.', 2)
|
313
|
-
|
383
|
+
|
384
|
+
# Don't get the alias for the field when a belongs_to association
|
385
|
+
# is not the last item. Therefore, get the alias when one of the
|
386
|
+
# following is true:
|
387
|
+
# 1. This is the last item, i.e. there is no remaining.
|
388
|
+
# 2. It is not an association.
|
389
|
+
# 3. It is not a belongs association
|
390
|
+
if !remaining || !relations.key?(segment) || !relations[segment].is_a?(Association::Referenced::BelongsTo)
|
391
|
+
segment = aliased_fields[segment]&.dup || segment
|
392
|
+
end
|
393
|
+
|
314
394
|
return segment unless remaining
|
315
395
|
|
316
396
|
relation = relations[aliased_associations[segment] || segment]
|
317
397
|
if relation
|
318
|
-
|
398
|
+
k = relation.klass
|
399
|
+
"#{segment}.#{database_field_name(remaining, k.relations, k.aliased_fields, k.aliased_associations)}"
|
319
400
|
else
|
320
401
|
"#{segment}.#{remaining}"
|
321
402
|
end
|
322
403
|
end
|
323
404
|
end
|
405
|
+
end
|
406
|
+
|
407
|
+
module ClassMethods
|
408
|
+
|
409
|
+
# Returns an array of names for the attributes available on this object.
|
410
|
+
#
|
411
|
+
# Provides the field names in an ORM-agnostic way. Rails v3.1+ uses this
|
412
|
+
# method to automatically wrap params in JSON requests.
|
413
|
+
#
|
414
|
+
# @example Get the field names
|
415
|
+
# Model.attribute_names
|
416
|
+
#
|
417
|
+
# @return [ Array<String> ] The field names
|
418
|
+
def attribute_names
|
419
|
+
fields.keys
|
420
|
+
end
|
421
|
+
|
422
|
+
# Get the name of the provided field as it is stored in the database.
|
423
|
+
# Used in determining if the field is aliased or not.
|
424
|
+
#
|
425
|
+
# @param [ String, Symbol ] name The name to get.
|
426
|
+
#
|
427
|
+
# @return [ String ] The name of the field as it's stored in the db.
|
428
|
+
def database_field_name(name)
|
429
|
+
Fields.database_field_name(name, relations, aliased_fields, aliased_associations)
|
430
|
+
end
|
324
431
|
|
325
432
|
# Defines all the fields that are accessible on the Document
|
326
433
|
# For each field that is defined, a getter and setter will be
|
327
434
|
# added as an instance method to the Document.
|
328
435
|
#
|
329
436
|
# @example Define a field.
|
330
|
-
# field :score, :
|
437
|
+
# field :score, type: Integer, default: 0
|
331
438
|
#
|
332
439
|
# @param [ Symbol ] name The name of the field.
|
333
440
|
# @param [ Hash ] options The options to pass to the field.
|
334
441
|
#
|
335
|
-
# @option options [ Class ] :type The type of the field.
|
442
|
+
# @option options [ Class | Symbol | String ] :type The type of the field.
|
336
443
|
# @option options [ String ] :label The label for the field.
|
337
|
-
# @option options [ Object
|
444
|
+
# @option options [ Object | Proc ] :default The field's default.
|
338
445
|
#
|
339
446
|
# @return [ Field ] The generated field
|
340
447
|
def field(name, options = {})
|
@@ -372,6 +479,23 @@ module Mongoid
|
|
372
479
|
fields["_id"].object_id_field?
|
373
480
|
end
|
374
481
|
|
482
|
+
# Traverse down the association tree and search for the field for the
|
483
|
+
# given key.
|
484
|
+
#
|
485
|
+
# @param [ String ] key The key used to search the association tree.
|
486
|
+
# @param [ Proc ] block The block takes in three paramaters, the current
|
487
|
+
# meth, the field or the relation, and whether the second parameter is a
|
488
|
+
# field or not.
|
489
|
+
#
|
490
|
+
# @return [ Field ] The field found for the given key at the end of the
|
491
|
+
# search. This will return nil if the last thing found is an association
|
492
|
+
# or no field was found for the given key.
|
493
|
+
#
|
494
|
+
# @api private
|
495
|
+
def traverse_association_tree(key, &block)
|
496
|
+
Fields.traverse_association_tree(key, fields, relations, aliased_associations, &block)
|
497
|
+
end
|
498
|
+
|
375
499
|
protected
|
376
500
|
|
377
501
|
# Add the defaults to the model. This breaks them up between ones that
|
data/lib/mongoid/findable.rb
CHANGED
@@ -41,9 +41,12 @@ module Mongoid
|
|
41
41
|
:pluck,
|
42
42
|
:read,
|
43
43
|
:sum,
|
44
|
+
:take,
|
45
|
+
:take!,
|
46
|
+
:tally,
|
44
47
|
:text_search,
|
45
48
|
:update,
|
46
|
-
:update_all
|
49
|
+
:update_all,
|
47
50
|
|
48
51
|
# Returns a count of records in the database.
|
49
52
|
# If you want to specify conditions use where.
|
@@ -179,9 +182,15 @@ module Mongoid
|
|
179
182
|
# @example Find the first document.
|
180
183
|
# Person.first
|
181
184
|
#
|
185
|
+
# @param [ Integer | Hash ] limit_or_opts The number of documents to
|
186
|
+
# return, or a hash of options.
|
187
|
+
#
|
188
|
+
# @option limit_or_opts [ :none ] :id_sort This option is deprecated.
|
189
|
+
# Don't apply a sort on _id if no other sort is defined on the criteria.
|
190
|
+
#
|
182
191
|
# @return [ Document ] The first matching document.
|
183
|
-
def first
|
184
|
-
with_default_scope.first
|
192
|
+
def first(limit_or_opts = nil)
|
193
|
+
with_default_scope.first(limit_or_opts)
|
185
194
|
end
|
186
195
|
alias :one :first
|
187
196
|
|
@@ -190,9 +199,15 @@ module Mongoid
|
|
190
199
|
# @example Find the last document.
|
191
200
|
# Person.last
|
192
201
|
#
|
202
|
+
# @param [ Integer | Hash ] limit_or_opts The number of documents to
|
203
|
+
# return, or a hash of options.
|
204
|
+
#
|
205
|
+
# @option limit_or_opts [ :none ] :id_sort This option is deprecated.
|
206
|
+
# Don't apply a sort on _id if no other sort is defined on the criteria.
|
207
|
+
#
|
193
208
|
# @return [ Document ] The last matching document.
|
194
|
-
def last
|
195
|
-
with_default_scope.last
|
209
|
+
def last(limit_or_opts = nil)
|
210
|
+
with_default_scope.last(limit_or_opts)
|
196
211
|
end
|
197
212
|
end
|
198
213
|
end
|
data/lib/mongoid/version.rb
CHANGED
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Mongoid
|
4
|
+
|
5
|
+
# Encapsulates behavior around logging and caching warnings so they are only
|
6
|
+
# logged once.
|
7
|
+
#
|
8
|
+
# @api private
|
9
|
+
module Warnings
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def warning(id, message)
|
13
|
+
singleton_class.class_eval do
|
14
|
+
define_method("warn_#{id}") do
|
15
|
+
unless instance_variable_get("@#{id}")
|
16
|
+
Mongoid.logger.warn(message)
|
17
|
+
instance_variable_set("@#{id}", true)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
warning :id_sort_deprecated, 'The :id_sort option has been deprecated. Use Mongo#take to get a document without a sort on _id.'
|
25
|
+
warning :criteria_cache_deprecated, 'The criteria cache has been deprecated and will be removed in Mongoid 8. Please enable the Mongoid QueryCache to have caching functionality.'
|
26
|
+
warning :map_field_deprecated, 'The field argument to the Mongo#map method has been deprecated, please pass in a block instead. Support will be dropped in Mongoid 8.'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
data/lib/mongoid.rb
CHANGED
@@ -23,6 +23,7 @@ require "mongoid/clients"
|
|
23
23
|
require "mongoid/document"
|
24
24
|
require "mongoid/tasks/database"
|
25
25
|
require "mongoid/query_cache"
|
26
|
+
require "mongoid/warnings"
|
26
27
|
|
27
28
|
# If we are using Rails then we will include the Mongoid railtie. This has all
|
28
29
|
# the nifty initializers that Mongoid needs.
|
@@ -125,9 +125,6 @@ development:
|
|
125
125
|
# database name is not explicitly defined. (default: nil)
|
126
126
|
# app_name: MyApplicationName
|
127
127
|
|
128
|
-
# Create indexes in background by default. (default: false)
|
129
|
-
# background_indexing: false
|
130
|
-
|
131
128
|
# Mark belongs_to associations as required by default, so that saving a
|
132
129
|
# model with a missing belongs_to association will trigger a validation
|
133
130
|
# error. (default: true)
|
@@ -172,6 +169,10 @@ development:
|
|
172
169
|
# (default: false)
|
173
170
|
# use_utc: false
|
174
171
|
|
172
|
+
# (Deprecated) In MongoDB 4.0 and earlier, set whether to create
|
173
|
+
# indexes in the background by default. (default: false)
|
174
|
+
# background_indexing: false
|
175
|
+
|
175
176
|
test:
|
176
177
|
clients:
|
177
178
|
default:
|
@@ -23,6 +23,10 @@ describe 'i18n fallbacks' do
|
|
23
23
|
I18n.fallbacks[:de] = [ :en ]
|
24
24
|
end
|
25
25
|
|
26
|
+
after do
|
27
|
+
I18n.locale = :en
|
28
|
+
end
|
29
|
+
|
26
30
|
context 'when translation is present in active locale' do
|
27
31
|
it 'uses active locale' do
|
28
32
|
product = Product.new
|
@@ -36,6 +40,9 @@ describe 'i18n fallbacks' do
|
|
36
40
|
end
|
37
41
|
|
38
42
|
context 'when translation is missing in active locale and present in fallback locale' do
|
43
|
+
after do
|
44
|
+
I18n.locale = :en
|
45
|
+
end
|
39
46
|
|
40
47
|
it 'falls back on default locale' do
|
41
48
|
product = Product.new
|
@@ -57,6 +64,10 @@ describe 'i18n fallbacks' do
|
|
57
64
|
end
|
58
65
|
end
|
59
66
|
|
67
|
+
after do
|
68
|
+
I18n.locale = :en
|
69
|
+
end
|
70
|
+
|
60
71
|
it 'returns nil' do
|
61
72
|
product = Product.new
|
62
73
|
I18n.locale = :en
|
@@ -75,6 +86,10 @@ describe 'i18n fallbacks' do
|
|
75
86
|
end
|
76
87
|
end
|
77
88
|
|
89
|
+
after do
|
90
|
+
I18n.locale = :en
|
91
|
+
end
|
92
|
+
|
78
93
|
it 'falls back on default locale' do
|
79
94
|
product = Product.new
|
80
95
|
I18n.locale = :en
|
@@ -82,7 +97,6 @@ describe 'i18n fallbacks' do
|
|
82
97
|
I18n.locale = :ru
|
83
98
|
product.description.should == 'Marvelous!'
|
84
99
|
end
|
85
|
-
|
86
100
|
end
|
87
101
|
end
|
88
102
|
end
|
@@ -1,7 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
|
-
require_relative '../embeds_many_models.rb'
|
5
4
|
|
6
5
|
describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
|
7
6
|
|
@@ -4650,24 +4649,4 @@ describe Mongoid::Association::Embedded::EmbedsMany::Proxy do
|
|
4650
4649
|
end
|
4651
4650
|
end
|
4652
4651
|
end
|
4653
|
-
|
4654
|
-
context "when using assign_attributes with an already populated array" do
|
4655
|
-
let(:post) { EmmPost.create! }
|
4656
|
-
|
4657
|
-
before do
|
4658
|
-
post.assign_attributes(company_tags: [{id: BSON::ObjectId.new, title: 'a'}],
|
4659
|
-
user_tags: [{id: BSON::ObjectId.new, title: 'b'}])
|
4660
|
-
post.save!
|
4661
|
-
post.reload
|
4662
|
-
post.assign_attributes(company_tags: [{id: BSON::ObjectId.new, title: 'c'}],
|
4663
|
-
user_tags: [])
|
4664
|
-
post.save!
|
4665
|
-
post.reload
|
4666
|
-
end
|
4667
|
-
|
4668
|
-
it "has the correct embedded documents" do
|
4669
|
-
expect(post.company_tags.length).to eq(1)
|
4670
|
-
expect(post.company_tags.first.title).to eq("c")
|
4671
|
-
end
|
4672
|
-
end
|
4673
4652
|
end
|