mongoid 3.0.23 → 3.1.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.
- data/CHANGELOG.md +253 -9
- data/LICENSE +1 -1
- data/README.md +4 -1
- data/lib/config/locales/en.yml +7 -6
- data/lib/mongoid.rb +18 -1
- data/lib/mongoid/atomic.rb +22 -20
- data/lib/mongoid/atomic/paths/embedded.rb +19 -5
- data/lib/mongoid/atomic/paths/root.rb +1 -1
- data/lib/mongoid/atomic/positionable.rb +73 -0
- data/lib/mongoid/attributes.rb +63 -1
- data/lib/mongoid/callbacks.rb +58 -4
- data/lib/mongoid/components.rb +8 -3
- data/lib/mongoid/config.rb +71 -23
- data/lib/mongoid/contextual.rb +2 -1
- data/lib/mongoid/contextual/aggregable/mongo.rb +27 -63
- data/lib/mongoid/contextual/atomic.rb +4 -3
- data/lib/mongoid/contextual/find_and_modify.rb +1 -1
- data/lib/mongoid/contextual/geo_near.rb +238 -0
- data/lib/mongoid/contextual/map_reduce.rb +12 -1
- data/lib/mongoid/contextual/memory.rb +36 -31
- data/lib/mongoid/contextual/mongo.rb +147 -91
- data/lib/mongoid/contextual/queryable.rb +25 -0
- data/lib/mongoid/copyable.rb +4 -1
- data/lib/mongoid/criteria.rb +23 -275
- data/lib/mongoid/criterion/findable.rb +179 -0
- data/lib/mongoid/criterion/modifiable.rb +191 -0
- data/lib/mongoid/criterion/scoping.rb +11 -6
- data/lib/mongoid/document.rb +7 -56
- data/lib/mongoid/equality.rb +66 -0
- data/lib/mongoid/errors/mongoid_error.rb +7 -3
- data/lib/mongoid/extensions/array.rb +13 -1
- data/lib/mongoid/extensions/date.rb +9 -2
- data/lib/mongoid/extensions/hash.rb +38 -2
- data/lib/mongoid/extensions/nil_class.rb +12 -0
- data/lib/mongoid/extensions/object.rb +24 -0
- data/lib/mongoid/extensions/string.rb +14 -2
- data/lib/mongoid/extensions/time.rb +4 -1
- data/lib/mongoid/fields.rb +49 -5
- data/lib/mongoid/fields/foreign_key.rb +12 -0
- data/lib/mongoid/fields/standard.rb +12 -0
- data/lib/mongoid/finders.rb +8 -0
- data/lib/mongoid/hierarchy.rb +19 -1
- data/lib/mongoid/indexes.rb +30 -4
- data/lib/mongoid/indexes/validators/options.rb +12 -2
- data/lib/mongoid/inspection.rb +2 -1
- data/lib/mongoid/matchers/strategies.rb +5 -5
- data/lib/mongoid/observer.rb +27 -36
- data/lib/mongoid/persistence.rb +42 -17
- data/lib/mongoid/persistence/atomic.rb +10 -5
- data/lib/mongoid/persistence/atomic/operation.rb +26 -9
- data/lib/mongoid/persistence/atomic/unset.rb +1 -1
- data/lib/mongoid/persistence/operations/embedded/insert.rb +5 -2
- data/lib/mongoid/persistence/operations/embedded/remove.rb +5 -2
- data/lib/mongoid/persistence/operations/update.rb +7 -3
- data/lib/mongoid/railties/database.rake +12 -19
- data/lib/mongoid/relations.rb +2 -0
- data/lib/mongoid/relations/accessors.rb +30 -8
- data/lib/mongoid/relations/binding.rb +5 -1
- data/lib/mongoid/relations/bindings/referenced/in.rb +1 -1
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +3 -3
- data/lib/mongoid/relations/counter_cache.rb +107 -0
- data/lib/mongoid/relations/embedded/batchable.rb +13 -4
- data/lib/mongoid/relations/embedded/many.rb +30 -1
- data/lib/mongoid/relations/macros.rb +2 -0
- data/lib/mongoid/relations/marshalable.rb +0 -1
- data/lib/mongoid/relations/metadata.rb +63 -11
- data/lib/mongoid/relations/options.rb +1 -0
- data/lib/mongoid/relations/proxy.rb +45 -2
- data/lib/mongoid/relations/referenced/in.rb +11 -2
- data/lib/mongoid/relations/referenced/many.rb +31 -3
- data/lib/mongoid/relations/referenced/many_to_many.rb +31 -3
- data/lib/mongoid/relations/referenced/one.rb +1 -1
- data/lib/mongoid/relations/targets/enumerable.rb +5 -1
- data/lib/mongoid/relations/touchable.rb +35 -6
- data/lib/mongoid/reloading.rb +5 -3
- data/lib/mongoid/scoping.rb +2 -2
- data/lib/mongoid/sessions.rb +57 -7
- data/lib/mongoid/sessions/factory.rb +22 -1
- data/lib/mongoid/threaded.rb +4 -30
- data/lib/mongoid/threaded/lifecycle.rb +12 -12
- data/lib/mongoid/timestamps.rb +1 -0
- data/lib/mongoid/timestamps/created.rb +2 -0
- data/lib/mongoid/timestamps/created/short.rb +19 -0
- data/lib/mongoid/timestamps/short.rb +10 -0
- data/lib/mongoid/timestamps/updated.rb +2 -0
- data/lib/mongoid/timestamps/updated/short.rb +19 -0
- data/lib/mongoid/validations.rb +2 -0
- data/lib/mongoid/validations/queryable.rb +2 -2
- data/lib/mongoid/validations/uniqueness.rb +1 -18
- data/lib/mongoid/version.rb +1 -1
- data/lib/rails/generators/mongoid/model/model_generator.rb +1 -0
- data/lib/rails/generators/mongoid/model/templates/model.rb.tt +3 -0
- data/lib/rails/mongoid.rb +53 -29
- data/lib/support/ruby_version.rb +26 -0
- metadata +18 -7
data/lib/mongoid/contextual.rb
CHANGED
@@ -24,8 +24,12 @@ module Mongoid
|
|
24
24
|
# @since 3.0.0
|
25
25
|
def aggregates(field)
|
26
26
|
if query.count > 0
|
27
|
-
|
28
|
-
|
27
|
+
result = collection.aggregate(pipeline(field)).to_a
|
28
|
+
if result.empty?
|
29
|
+
{ "count" => query.count, "avg" => 0, "sum" => 0 }
|
30
|
+
else
|
31
|
+
result.first
|
32
|
+
end
|
29
33
|
else
|
30
34
|
{ "count" => 0 }
|
31
35
|
end
|
@@ -109,73 +113,33 @@ module Mongoid
|
|
109
113
|
|
110
114
|
private
|
111
115
|
|
112
|
-
# Get the
|
116
|
+
# Get the aggregation pipeline for provided field.
|
113
117
|
#
|
114
118
|
# @api private
|
115
119
|
#
|
116
|
-
# @example Get the
|
117
|
-
# aggregable.
|
118
|
-
#
|
119
|
-
# @return [ String ] The finalize JS function.
|
120
|
-
#
|
121
|
-
# @since 3.0.0
|
122
|
-
def finalizer
|
123
|
-
%Q{
|
124
|
-
function(key, agg) {
|
125
|
-
agg.avg = agg.sum / agg.count;
|
126
|
-
return agg;
|
127
|
-
}}
|
128
|
-
end
|
129
|
-
|
130
|
-
# Get the map function for the provided field.
|
131
|
-
#
|
132
|
-
# @api private
|
133
|
-
#
|
134
|
-
# @example Get the map function.
|
135
|
-
# aggregable.mapper(:likes)
|
120
|
+
# @example Get the pipeline.
|
121
|
+
# aggregable.pipeline(:likes)
|
136
122
|
#
|
137
123
|
# @param [ String, Symbol ] field The name of the field.
|
138
124
|
#
|
139
|
-
# @return [
|
140
|
-
#
|
141
|
-
# @since 3.
|
142
|
-
def
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
# @api private
|
158
|
-
#
|
159
|
-
# @example Get the reduce function.
|
160
|
-
# aggregable.reducer(:likes)
|
161
|
-
#
|
162
|
-
# @return [ String ] The reduce JS function.
|
163
|
-
#
|
164
|
-
# @since 3.0.0
|
165
|
-
def reducer
|
166
|
-
%Q{
|
167
|
-
function(key, values) {
|
168
|
-
var agg = { count: 0, max: null, min: null, sum: 0 };
|
169
|
-
values.forEach(function(val) {
|
170
|
-
if (val.max !== null) {
|
171
|
-
if (agg.max == null || val.max > agg.max) agg.max = val.max;
|
172
|
-
if (agg.min == null || val.max < agg.min) agg.min = val.max;
|
173
|
-
agg.sum += val.sum;
|
174
|
-
}
|
175
|
-
agg.count += val.count;
|
176
|
-
});
|
177
|
-
return agg;
|
178
|
-
}}
|
125
|
+
# @return [ Array ] The array of pipeline operators.
|
126
|
+
#
|
127
|
+
# @since 3.1.0
|
128
|
+
def pipeline(field)
|
129
|
+
db_field = "$#{database_field_name(field)}"
|
130
|
+
pipeline = []
|
131
|
+
pipeline << { "$match" => criteria.nin(field => nil).selector }
|
132
|
+
pipeline << { "$limit" => criteria.options[:limit] } if criteria.options[:limit]
|
133
|
+
pipeline << {
|
134
|
+
"$group" => {
|
135
|
+
"_id" => field.to_s,
|
136
|
+
"count" => { "$sum" => 1 },
|
137
|
+
"max" => { "$max" => db_field },
|
138
|
+
"min" => { "$min" => db_field },
|
139
|
+
"sum" => { "$sum" => db_field },
|
140
|
+
"avg" => { "$avg" => db_field }
|
141
|
+
}
|
142
|
+
}
|
179
143
|
end
|
180
144
|
end
|
181
145
|
end
|
@@ -166,13 +166,14 @@ module Mongoid
|
|
166
166
|
# @example Unset the field on the matches.
|
167
167
|
# context.unset(:name)
|
168
168
|
#
|
169
|
-
# @param [ String, Symbol ]
|
169
|
+
# @param [ String, Symbol, Array ] fields The name of the fields.
|
170
170
|
#
|
171
171
|
# @return [ nil ] Nil.
|
172
172
|
#
|
173
173
|
# @since 3.0.0
|
174
|
-
def unset(
|
175
|
-
|
174
|
+
def unset(*args)
|
175
|
+
fields = args.__find_args__.collect { |f| [database_field_name(f), true] }
|
176
|
+
query.update_all("$unset" => Hash[fields])
|
176
177
|
end
|
177
178
|
end
|
178
179
|
end
|
@@ -0,0 +1,238 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Mongoid
|
3
|
+
module Contextual
|
4
|
+
class GeoNear
|
5
|
+
include Enumerable
|
6
|
+
include Command
|
7
|
+
|
8
|
+
delegate :[], to: :results
|
9
|
+
delegate :==, :empty?, to: :entries
|
10
|
+
|
11
|
+
# Get the average distance for all documents from the point in the
|
12
|
+
# command.
|
13
|
+
#
|
14
|
+
# @example Get the average distance.
|
15
|
+
# geo_near.average_distance
|
16
|
+
#
|
17
|
+
# @return [ Float, nil ] The average distance.
|
18
|
+
#
|
19
|
+
# @since 3.1.0
|
20
|
+
def average_distance
|
21
|
+
average = stats["avgDistance"]
|
22
|
+
average.nan? ? nil : average
|
23
|
+
end
|
24
|
+
|
25
|
+
# Iterates over each of the documents in the $geoNear, excluding the
|
26
|
+
# extra information that was passed back from the database.
|
27
|
+
#
|
28
|
+
# @example Iterate over the results.
|
29
|
+
# geo_near.each do |doc|
|
30
|
+
# p doc
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
# @return [ Enumerator ] The enumerator.
|
34
|
+
#
|
35
|
+
# @since 3.1.0
|
36
|
+
def each
|
37
|
+
if block_given?
|
38
|
+
documents.each do |doc|
|
39
|
+
yield doc
|
40
|
+
end
|
41
|
+
else
|
42
|
+
to_enum
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
# Provide a distance multiplier to be used for each returned distance.
|
47
|
+
#
|
48
|
+
# @example Provide the distance multiplier.
|
49
|
+
# geo_near.distance_multiplier(13113.1)
|
50
|
+
#
|
51
|
+
# @param [ Integer, Float ] value The distance multiplier.
|
52
|
+
#
|
53
|
+
# @return [ GeoNear ] The GeoNear wrapper.
|
54
|
+
#
|
55
|
+
# @since 3.1.0
|
56
|
+
def distance_multiplier(value)
|
57
|
+
command[:distanceMultiplier] = value
|
58
|
+
self
|
59
|
+
end
|
60
|
+
|
61
|
+
# Initialize the new map/reduce directive.
|
62
|
+
#
|
63
|
+
# @example Initialize the new map/reduce.
|
64
|
+
# MapReduce.new(criteria, map, reduce)
|
65
|
+
#
|
66
|
+
# @param [ Criteria ] criteria The Mongoid criteria.
|
67
|
+
# @param [ String ] map The map js function.
|
68
|
+
# @param [ String ] reduce The reduce js function.
|
69
|
+
#
|
70
|
+
# @since 3.0.0
|
71
|
+
def initialize(collection, criteria, near)
|
72
|
+
@collection, @criteria = collection, criteria
|
73
|
+
command[:geoNear] = collection.name.to_s
|
74
|
+
command[:near] = near
|
75
|
+
apply_criteria_options
|
76
|
+
end
|
77
|
+
|
78
|
+
# Get a pretty string representation of the command.
|
79
|
+
#
|
80
|
+
# @example Inspect the geoNear.
|
81
|
+
# geo_near.inspect
|
82
|
+
#
|
83
|
+
# @return [ String ] The inspection string.
|
84
|
+
#
|
85
|
+
# @since 3.1.0
|
86
|
+
def inspect
|
87
|
+
%Q{#<Mongoid::Contextual::GeoNear
|
88
|
+
selector: #{criteria.selector.inspect}
|
89
|
+
class: #{criteria.klass}
|
90
|
+
near: #{command[:near]}
|
91
|
+
multiplier: #{command[:distanceMultiplier] || "N/A"}
|
92
|
+
max: #{command[:maxDistance] || "N/A"}
|
93
|
+
unique: #{command[:unique].nil? ? true : command[:unique]}
|
94
|
+
spherical: #{command[:spherical] || false}>
|
95
|
+
}
|
96
|
+
end
|
97
|
+
|
98
|
+
# Specify the maximum distance to find documents for, or get the value of
|
99
|
+
# the document with the furthest distance.
|
100
|
+
#
|
101
|
+
# @example Set the max distance.
|
102
|
+
# geo_near.max_distance(0.5)
|
103
|
+
#
|
104
|
+
# @example Get the max distance.
|
105
|
+
# geo_near.max_distance
|
106
|
+
#
|
107
|
+
# @param [ Integer, Float ] value The maximum distance.
|
108
|
+
#
|
109
|
+
# @return [ GeoNear, Float ] The GeoNear command or the value.
|
110
|
+
#
|
111
|
+
# @since 3.1.0
|
112
|
+
def max_distance(value = nil)
|
113
|
+
if value
|
114
|
+
command[:maxDistance] = value
|
115
|
+
self
|
116
|
+
else
|
117
|
+
stats["maxDistance"]
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
# Tell the command to calculate based on spherical distances.
|
122
|
+
#
|
123
|
+
# @example Add the spherical flag.
|
124
|
+
# geo_near.spherical
|
125
|
+
#
|
126
|
+
# @return [ GeoNear ] The command.
|
127
|
+
#
|
128
|
+
# @since 3.1.0
|
129
|
+
def spherical
|
130
|
+
command[:spherical] = true
|
131
|
+
self
|
132
|
+
end
|
133
|
+
|
134
|
+
# Tell the command whether or not the retured results should be unique.
|
135
|
+
#
|
136
|
+
# @example Set the unique flag.
|
137
|
+
# geo_near.unique(false)
|
138
|
+
#
|
139
|
+
# @param [ true, false ] value Whether to return unique documents.
|
140
|
+
#
|
141
|
+
# @return [ GeoNear ] The command.
|
142
|
+
#
|
143
|
+
# @since 3.1.0
|
144
|
+
def unique(value = true)
|
145
|
+
command[:unique] = value
|
146
|
+
self
|
147
|
+
end
|
148
|
+
|
149
|
+
# Execute the $geoNear, returning the raw output.
|
150
|
+
#
|
151
|
+
# @example Run the $geoNear
|
152
|
+
# geo_near.execute
|
153
|
+
#
|
154
|
+
# @return [ Hash ] The raw output
|
155
|
+
#
|
156
|
+
# @since 3.1.0
|
157
|
+
def execute
|
158
|
+
results
|
159
|
+
end
|
160
|
+
|
161
|
+
# Get the stats for the command run.
|
162
|
+
#
|
163
|
+
# @example Get the stats.
|
164
|
+
# geo_near.stats
|
165
|
+
#
|
166
|
+
# @return [ Hash ] The stats from the command run.
|
167
|
+
#
|
168
|
+
# @since 3.1.0
|
169
|
+
def stats
|
170
|
+
results["stats"]
|
171
|
+
end
|
172
|
+
|
173
|
+
# Get the execution time of the command.
|
174
|
+
#
|
175
|
+
# @example Get the execution time.
|
176
|
+
# geo_near.time
|
177
|
+
#
|
178
|
+
# @return [ Float ] The execution time.
|
179
|
+
#
|
180
|
+
# @since 3.1.0
|
181
|
+
def time
|
182
|
+
stats["time"]
|
183
|
+
end
|
184
|
+
|
185
|
+
private
|
186
|
+
|
187
|
+
# Apply criteria specific options - query, limit.
|
188
|
+
#
|
189
|
+
# @api private
|
190
|
+
#
|
191
|
+
# @example Apply the criteria options
|
192
|
+
# geo_near.apply_criteria_options
|
193
|
+
#
|
194
|
+
# @return [ nil ] Nothing.
|
195
|
+
#
|
196
|
+
# @since 3.0.0
|
197
|
+
def apply_criteria_options
|
198
|
+
command[:query] = criteria.selector
|
199
|
+
if limit = criteria.options[:limit]
|
200
|
+
command[:num] = limit
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
# Get the result documents from the $geoNear.
|
205
|
+
#
|
206
|
+
# @api private
|
207
|
+
#
|
208
|
+
# @example Get the documents.
|
209
|
+
# geo_near.documents
|
210
|
+
#
|
211
|
+
# @return [ Array, Cursor ] The documents.
|
212
|
+
#
|
213
|
+
# @since 3.0.0
|
214
|
+
def documents
|
215
|
+
results["results"].map do |attributes|
|
216
|
+
doc = Factory.from_db(criteria.klass, attributes["obj"], criteria.object_id)
|
217
|
+
doc.attributes["geo_near_distance"] = attributes["dis"]
|
218
|
+
doc
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
# Execute the $geoNear command and get the results.
|
223
|
+
#
|
224
|
+
# @api private
|
225
|
+
#
|
226
|
+
# @example Get the results.
|
227
|
+
# geo_near.results
|
228
|
+
#
|
229
|
+
# @return [ Hash ] The results of the command.
|
230
|
+
#
|
231
|
+
# @since 3.0.0
|
232
|
+
def results
|
233
|
+
@results ||= session.command(command)
|
234
|
+
end
|
235
|
+
end
|
236
|
+
end
|
237
|
+
end
|
238
|
+
|
@@ -6,7 +6,7 @@ module Mongoid
|
|
6
6
|
include Command
|
7
7
|
|
8
8
|
delegate :[], to: :results
|
9
|
-
delegate :==, :empty?,
|
9
|
+
delegate :==, :empty?, to: :entries
|
10
10
|
|
11
11
|
# Get all the counts returned by the map/reduce.
|
12
12
|
#
|
@@ -162,6 +162,17 @@ module Mongoid
|
|
162
162
|
results
|
163
163
|
end
|
164
164
|
|
165
|
+
# Execute the map/reduce, returning the raw output.
|
166
|
+
# Useful when you don't care about map/reduce's ouptut.
|
167
|
+
#
|
168
|
+
# @example Run the map reduce
|
169
|
+
# map_reduce.execute
|
170
|
+
#
|
171
|
+
# @return [ Hash ] The raw output
|
172
|
+
#
|
173
|
+
# @since 3.1.0
|
174
|
+
alias :execute :raw
|
175
|
+
|
165
176
|
# Get the number of documents reduced by the map/reduce.
|
166
177
|
#
|
167
178
|
# @example Get the reduced document count.
|
@@ -6,22 +6,15 @@ module Mongoid
|
|
6
6
|
class Memory
|
7
7
|
include Enumerable
|
8
8
|
include Aggregable::Memory
|
9
|
+
include Eager
|
10
|
+
include Queryable
|
11
|
+
include Mongoid::Atomic::Positionable
|
9
12
|
|
10
|
-
# @attribute [r] collection The root collection.
|
11
|
-
# @attribute [r] criteria The criteria for the context.
|
12
|
-
# @attribute [r] klass The criteria class.
|
13
13
|
# @attribute [r] root The root document.
|
14
14
|
# @attribute [r] path The atomic path.
|
15
15
|
# @attribute [r] selector The root document selector.
|
16
16
|
# @attribute [r] matching The in memory documents that match the selector.
|
17
|
-
attr_reader
|
18
|
-
:collection,
|
19
|
-
:criteria,
|
20
|
-
:documents,
|
21
|
-
:klass,
|
22
|
-
:path,
|
23
|
-
:root,
|
24
|
-
:selector
|
17
|
+
attr_reader :documents, :path, :root, :selector
|
25
18
|
|
26
19
|
# Check if the context is equal to the other object.
|
27
20
|
#
|
@@ -38,19 +31,6 @@ module Mongoid
|
|
38
31
|
entries == other.entries
|
39
32
|
end
|
40
33
|
|
41
|
-
# Is the enumerable of matching documents empty?
|
42
|
-
#
|
43
|
-
# @example Is the context empty?
|
44
|
-
# context.blank?
|
45
|
-
#
|
46
|
-
# @return [ true, false ] If the context is empty.
|
47
|
-
#
|
48
|
-
# @since 3.0.0
|
49
|
-
def blank?
|
50
|
-
count == 0
|
51
|
-
end
|
52
|
-
alias :empty? :blank?
|
53
|
-
|
54
34
|
# Delete all documents in the database that match the selector.
|
55
35
|
#
|
56
36
|
# @example Delete all the documents.
|
@@ -66,7 +46,9 @@ module Mongoid
|
|
66
46
|
doc.as_document
|
67
47
|
end
|
68
48
|
unless removed.empty?
|
69
|
-
collection.find(selector).update(
|
49
|
+
collection.find(selector).update(
|
50
|
+
positionally(selector, "$pullAll" => { path => removed })
|
51
|
+
)
|
70
52
|
end
|
71
53
|
deleted
|
72
54
|
end
|
@@ -117,9 +99,10 @@ module Mongoid
|
|
117
99
|
# @since 3.0.0
|
118
100
|
def each
|
119
101
|
if block_given?
|
120
|
-
|
121
|
-
yield
|
102
|
+
documents_for_iteration.each do |doc|
|
103
|
+
yield(doc)
|
122
104
|
end
|
105
|
+
# eager_loadable? ? docs : self
|
123
106
|
else
|
124
107
|
to_enum
|
125
108
|
end
|
@@ -146,7 +129,9 @@ module Mongoid
|
|
146
129
|
#
|
147
130
|
# @since 3.0.0
|
148
131
|
def first
|
149
|
-
documents.first
|
132
|
+
doc = documents.first
|
133
|
+
eager_load_one(doc) if eager_loadable?(doc)
|
134
|
+
doc
|
150
135
|
end
|
151
136
|
alias :one :first
|
152
137
|
|
@@ -178,7 +163,9 @@ module Mongoid
|
|
178
163
|
#
|
179
164
|
# @since 3.0.0
|
180
165
|
def last
|
181
|
-
documents.last
|
166
|
+
doc = documents.last
|
167
|
+
eager_load_one(doc) if eager_loadable?(doc)
|
168
|
+
doc
|
182
169
|
end
|
183
170
|
|
184
171
|
# Get the length of matching documents in the context.
|
@@ -269,6 +256,24 @@ module Mongoid
|
|
269
256
|
|
270
257
|
private
|
271
258
|
|
259
|
+
# Get the documents the context should iterate. This follows 3 rules:
|
260
|
+
#
|
261
|
+
# @api private
|
262
|
+
#
|
263
|
+
# @example Get the documents for iteration.
|
264
|
+
# context.documents_for_iteration
|
265
|
+
#
|
266
|
+
# @return [ Array<Document> ] The docs to iterate.
|
267
|
+
#
|
268
|
+
# @since 3.1.0
|
269
|
+
def documents_for_iteration
|
270
|
+
docs = documents[skipping || 0, limiting || documents.length] || []
|
271
|
+
if eager_loadable?
|
272
|
+
eager_load(docs)
|
273
|
+
end
|
274
|
+
docs
|
275
|
+
end
|
276
|
+
|
272
277
|
# Update the provided documents with the attributes.
|
273
278
|
#
|
274
279
|
# @api private
|
@@ -404,11 +409,11 @@ module Mongoid
|
|
404
409
|
#
|
405
410
|
# @since 3.0.0
|
406
411
|
def in_place_sort(values)
|
407
|
-
values.
|
412
|
+
values.keys.reverse.each do |field|
|
408
413
|
documents.sort! do |a, b|
|
409
414
|
a_value, b_value = a[field], b[field]
|
410
415
|
value = compare(a_value.__sortable__, b_value.__sortable__)
|
411
|
-
|
416
|
+
values[field] < 0 ? value * -1 : value
|
412
417
|
end
|
413
418
|
end
|
414
419
|
end
|