mongoid-pre 2.0.0.beta1 → 2.0.0.pre
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/.watchr +15 -10
- data/HISTORY +342 -0
- data/README.rdoc +8 -1
- data/Rakefile +2 -3
- data/VERSION +1 -1
- data/lib/mongoid/associations/{embedded_in.rb → belongs_to.rb} +4 -4
- data/lib/mongoid/associations/belongs_to_related.rb +9 -6
- data/lib/mongoid/associations/{embeds_many.rb → has_many.rb} +20 -33
- data/lib/mongoid/associations/has_many_related.rb +4 -28
- data/lib/mongoid/associations/{embeds_one.rb → has_one.rb} +6 -6
- data/lib/mongoid/associations/options.rb +6 -1
- data/lib/mongoid/associations.rb +32 -41
- data/lib/mongoid/attributes.rb +6 -13
- data/lib/mongoid/collection.rb +1 -2
- data/lib/mongoid/commands/delete.rb +1 -1
- data/lib/mongoid/commands/delete_all.rb +1 -4
- data/lib/mongoid/commands/destroy.rb +1 -1
- data/lib/mongoid/commands/destroy_all.rb +1 -3
- data/lib/mongoid/commands/save.rb +0 -1
- data/lib/mongoid/commands.rb +13 -2
- data/lib/mongoid/components.rb +1 -6
- data/lib/mongoid/config.rb +1 -5
- data/lib/mongoid/contexts/enumerable.rb +17 -54
- data/lib/mongoid/contexts/mongo.rb +38 -101
- data/lib/mongoid/contexts/paging.rb +2 -2
- data/lib/mongoid/contexts.rb +0 -21
- data/lib/mongoid/criteria.rb +73 -15
- data/lib/mongoid/criterion/inclusion.rb +0 -2
- data/lib/mongoid/criterion/optional.rb +2 -10
- data/lib/mongoid/document.rb +30 -41
- data/lib/mongoid/extensions.rb +0 -15
- data/lib/mongoid/field.rb +7 -20
- data/lib/mongoid/fields.rb +10 -15
- data/lib/mongoid/finders.rb +98 -10
- data/lib/mongoid/identity.rb +2 -8
- data/lib/mongoid/named_scope.rb +0 -2
- data/lib/mongoid/validations/associated.rb +8 -3
- data/lib/mongoid/validations/uniqueness.rb +7 -2
- data/lib/mongoid/validations.rb +2 -2
- data/lib/mongoid/versioning.rb +1 -1
- data/lib/mongoid.rb +5 -21
- data/mongoid.gemspec +19 -59
- data/spec/integration/mongoid/associations_spec.rb +3 -42
- data/spec/integration/mongoid/attributes_spec.rb +2 -2
- data/spec/integration/mongoid/commands_spec.rb +13 -27
- data/spec/integration/mongoid/contexts/enumerable_spec.rb +0 -13
- data/spec/integration/mongoid/criteria_spec.rb +3 -50
- data/spec/integration/mongoid/document_spec.rb +5 -72
- data/spec/integration/mongoid/finders_spec.rb +28 -85
- data/spec/models/address.rb +3 -3
- data/spec/models/animal.rb +2 -2
- data/spec/models/country_code.rb +2 -2
- data/spec/models/game.rb +1 -2
- data/spec/models/inheritance.rb +5 -5
- data/spec/models/location.rb +2 -2
- data/spec/models/name.rb +3 -3
- data/spec/models/namespacing.rb +2 -2
- data/spec/models/patient.rb +0 -2
- data/spec/models/person.rb +4 -6
- data/spec/models/pet.rb +3 -3
- data/spec/models/pet_owner.rb +3 -3
- data/spec/models/phone.rb +3 -3
- data/spec/models/post.rb +1 -1
- data/spec/models/translation.rb +2 -2
- data/spec/models/vet_visit.rb +2 -2
- data/spec/spec_helper.rb +2 -2
- data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +0 -4
- data/spec/unit/mongoid/associations/{embedded_in_spec.rb → belongs_to_spec.rb} +11 -11
- data/spec/unit/mongoid/associations/has_many_related_spec.rb +14 -45
- data/spec/unit/mongoid/associations/{embeds_many_spec.rb → has_many_spec.rb} +34 -79
- data/spec/unit/mongoid/associations/{embeds_one_spec.rb → has_one_spec.rb} +18 -18
- data/spec/unit/mongoid/associations/options_spec.rb +19 -20
- data/spec/unit/mongoid/associations_spec.rb +12 -74
- data/spec/unit/mongoid/attributes_spec.rb +51 -83
- data/spec/unit/mongoid/collection_spec.rb +0 -46
- data/spec/unit/mongoid/commands/delete_all_spec.rb +8 -9
- data/spec/unit/mongoid/commands/delete_spec.rb +3 -6
- data/spec/unit/mongoid/commands/destroy_all_spec.rb +2 -0
- data/spec/unit/mongoid/commands/destroy_spec.rb +3 -10
- data/spec/unit/mongoid/commands_spec.rb +11 -20
- data/spec/unit/mongoid/config_spec.rb +0 -18
- data/spec/unit/mongoid/contexts/enumerable_spec.rb +11 -198
- data/spec/unit/mongoid/contexts/mongo_spec.rb +54 -357
- data/spec/unit/mongoid/criteria_spec.rb +78 -107
- data/spec/unit/mongoid/criterion/exclusion_spec.rb +13 -3
- data/spec/unit/mongoid/criterion/inclusion_spec.rb +19 -25
- data/spec/unit/mongoid/criterion/optional_spec.rb +18 -25
- data/spec/unit/mongoid/document_spec.rb +34 -71
- data/spec/unit/mongoid/extensions/array/conversions_spec.rb +2 -2
- data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +3 -0
- data/spec/unit/mongoid/extensions/object/conversions_spec.rb +2 -16
- data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +1 -1
- data/spec/unit/mongoid/field_spec.rb +0 -62
- data/spec/unit/mongoid/fields_spec.rb +0 -33
- data/spec/unit/mongoid/finders_spec.rb +1 -37
- data/spec/unit/mongoid/identity_spec.rb +6 -47
- data/spec/unit/mongoid/named_scope_spec.rb +2 -15
- data/spec/unit/mongoid/scope_spec.rb +1 -1
- data/spec/unit/mongoid/validations/uniqueness_spec.rb +3 -3
- data/spec/unit/mongoid_spec.rb +2 -11
- metadata +14 -64
- data/lib/mongoid/associations/meta_data.rb +0 -28
- data/lib/mongoid/contexts/ids.rb +0 -25
- data/lib/mongoid/deprecation.rb +0 -22
- data/lib/mongoid/dirty.rb +0 -203
- data/lib/mongoid/extensions/big_decimal/conversions.rb +0 -19
- data/lib/mongoid/extensions/binary/conversions.rb +0 -17
- data/lib/mongoid/extensions/objectid/conversions.rb +0 -15
- data/lib/mongoid/extras.rb +0 -61
- data/lib/mongoid/javascript/functions.yml +0 -37
- data/lib/mongoid/javascript.rb +0 -21
- data/lib/mongoid/observable.rb +0 -30
- data/lib/mongoid/paths.rb +0 -54
- data/lib/mongoid/persistence/command.rb +0 -20
- data/lib/mongoid/persistence/insert.rb +0 -71
- data/lib/mongoid/persistence/update.rb +0 -78
- data/lib/mongoid/persistence.rb +0 -27
- data/lib/mongoid/state.rb +0 -32
- data/spec/integration/mongoid/dirty_spec.rb +0 -70
- data/spec/integration/mongoid/persistence/update_spec.rb +0 -46
- data/spec/models/callbacks.rb +0 -18
- data/spec/unit/mongoid/associations/meta_data_spec.rb +0 -88
- data/spec/unit/mongoid/contexts_spec.rb +0 -25
- data/spec/unit/mongoid/deprecation_spec.rb +0 -24
- data/spec/unit/mongoid/dirty_spec.rb +0 -286
- data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +0 -22
- data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +0 -22
- data/spec/unit/mongoid/extras_spec.rb +0 -102
- data/spec/unit/mongoid/javascript_spec.rb +0 -48
- data/spec/unit/mongoid/observable_spec.rb +0 -46
- data/spec/unit/mongoid/paths_spec.rb +0 -124
- data/spec/unit/mongoid/persistence/insert_spec.rb +0 -175
- data/spec/unit/mongoid/persistence/update_spec.rb +0 -148
- data/spec/unit/mongoid/persistence_spec.rb +0 -40
- data/spec/unit/mongoid/state_spec.rb +0 -83
|
@@ -2,11 +2,10 @@
|
|
|
2
2
|
module Mongoid #:nodoc:
|
|
3
3
|
module Contexts #:nodoc:
|
|
4
4
|
class Mongo
|
|
5
|
-
include
|
|
6
|
-
attr_reader :
|
|
7
|
-
|
|
8
|
-
delegate :klass, :options, :selector, :to => :criteria
|
|
5
|
+
include Paging
|
|
6
|
+
attr_reader :selector, :options, :klass
|
|
9
7
|
|
|
8
|
+
AGGREGATE_REDUCE = "function(obj, prev) { prev.count++; }"
|
|
10
9
|
# Aggregate the context. This will take the internally built selector and options
|
|
11
10
|
# and pass them on to the Ruby driver's +group()+ method on the collection. The
|
|
12
11
|
# collection itself will be retrieved from the class provided, and once the
|
|
@@ -20,40 +19,9 @@ module Mongoid #:nodoc:
|
|
|
20
19
|
#
|
|
21
20
|
# A +Hash+ with field values as keys, counts as values
|
|
22
21
|
def aggregate
|
|
23
|
-
klass.collection.group(options[:fields], selector, { :count => 0 },
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Get the average value for the supplied field.
|
|
27
|
-
#
|
|
28
|
-
# This will take the internally built selector and options
|
|
29
|
-
# and pass them on to the Ruby driver's +group()+ method on the collection. The
|
|
30
|
-
# collection itself will be retrieved from the class provided, and once the
|
|
31
|
-
# query has returned it will provided a grouping of keys with averages.
|
|
32
|
-
#
|
|
33
|
-
# Example:
|
|
34
|
-
#
|
|
35
|
-
# <tt>context.avg(:age)</tt>
|
|
36
|
-
#
|
|
37
|
-
# Returns:
|
|
38
|
-
#
|
|
39
|
-
# A numeric value that is the average.
|
|
40
|
-
def avg(field)
|
|
41
|
-
total = sum(field)
|
|
42
|
-
total ? (total / count) : nil
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# Determine if the context is empty or blank given the criteria. Will
|
|
46
|
-
# perform a quick has_one asking only for the id.
|
|
47
|
-
#
|
|
48
|
-
# Example:
|
|
49
|
-
#
|
|
50
|
-
# <tt>context.blank?</tt>
|
|
51
|
-
def blank?
|
|
52
|
-
klass.collection.find_one(selector, { :fields => [ :_id ] }).nil?
|
|
22
|
+
@klass.collection.group(@options[:fields], @selector, { :count => 0 }, AGGREGATE_REDUCE, true)
|
|
53
23
|
end
|
|
54
24
|
|
|
55
|
-
alias :empty? :blank?
|
|
56
|
-
|
|
57
25
|
# Get the count of matching documents in the database for the context.
|
|
58
26
|
#
|
|
59
27
|
# Example:
|
|
@@ -64,17 +32,7 @@ module Mongoid #:nodoc:
|
|
|
64
32
|
#
|
|
65
33
|
# An +Integer+ count of documents.
|
|
66
34
|
def count
|
|
67
|
-
@count ||= klass.collection.find(selector, process_options).count
|
|
68
|
-
end
|
|
69
|
-
|
|
70
|
-
# Gets an array of distinct values for the supplied field across the
|
|
71
|
-
# entire collection or the susbset given the criteria.
|
|
72
|
-
#
|
|
73
|
-
# Example:
|
|
74
|
-
#
|
|
75
|
-
# <tt>context.distinct(:title)</tt>
|
|
76
|
-
def distinct(field)
|
|
77
|
-
klass.collection.distinct(field, selector)
|
|
35
|
+
@count ||= @klass.collection.find(@selector, process_options).count
|
|
78
36
|
end
|
|
79
37
|
|
|
80
38
|
# Execute the context. This will take the selector and options
|
|
@@ -84,13 +42,13 @@ module Mongoid #:nodoc:
|
|
|
84
42
|
#
|
|
85
43
|
# Example:
|
|
86
44
|
#
|
|
87
|
-
# <tt>
|
|
45
|
+
# <tt>mongo.execute</tt>
|
|
88
46
|
#
|
|
89
47
|
# Returns:
|
|
90
48
|
#
|
|
91
49
|
# An enumerable +Cursor+.
|
|
92
50
|
def execute(paginating = false)
|
|
93
|
-
cursor = klass.collection.find(selector, process_options)
|
|
51
|
+
cursor = @klass.collection.find(@selector, process_options)
|
|
94
52
|
if cursor
|
|
95
53
|
@count = cursor.count if paginating
|
|
96
54
|
cursor
|
|
@@ -99,6 +57,7 @@ module Mongoid #:nodoc:
|
|
|
99
57
|
end
|
|
100
58
|
end
|
|
101
59
|
|
|
60
|
+
GROUP_REDUCE = "function(obj, prev) { prev.group.push(obj); }"
|
|
102
61
|
# Groups the context. This will take the internally built selector and options
|
|
103
62
|
# and pass them on to the Ruby driver's +group()+ method on the collection. The
|
|
104
63
|
# collection itself will be retrieved from the class provided, and once the
|
|
@@ -112,14 +71,15 @@ module Mongoid #:nodoc:
|
|
|
112
71
|
#
|
|
113
72
|
# A +Hash+ with field values as keys, arrays of documents as values.
|
|
114
73
|
def group
|
|
115
|
-
klass.collection.group(
|
|
116
|
-
options[:fields],
|
|
117
|
-
selector,
|
|
74
|
+
@klass.collection.group(
|
|
75
|
+
@options[:fields],
|
|
76
|
+
@selector,
|
|
118
77
|
{ :group => [] },
|
|
119
|
-
|
|
78
|
+
GROUP_REDUCE,
|
|
79
|
+
true
|
|
120
80
|
).collect do |docs|
|
|
121
81
|
docs["group"] = docs["group"].collect do |attrs|
|
|
122
|
-
Mongoid::Factory.build(klass, attrs)
|
|
82
|
+
Mongoid::Factory.build(@klass, attrs)
|
|
123
83
|
end
|
|
124
84
|
docs
|
|
125
85
|
end
|
|
@@ -130,26 +90,11 @@ module Mongoid #:nodoc:
|
|
|
130
90
|
#
|
|
131
91
|
# Example:
|
|
132
92
|
#
|
|
133
|
-
# <tt>Mongoid::Contexts::Mongo.new(
|
|
134
|
-
def initialize(
|
|
135
|
-
@
|
|
136
|
-
if klass.hereditary
|
|
137
|
-
|
|
138
|
-
end
|
|
139
|
-
criteria.enslave if klass.enslaved?
|
|
140
|
-
criteria.cache if klass.cached?
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
# Iterate over each +Document+ in the results. This can take an optional
|
|
144
|
-
# block to pass to each argument in the results.
|
|
145
|
-
#
|
|
146
|
-
# Example:
|
|
147
|
-
#
|
|
148
|
-
# <tt>context.iterate { |doc| p doc }</tt>
|
|
149
|
-
def iterate(&block)
|
|
150
|
-
return caching(&block) if criteria.cached?
|
|
151
|
-
if block_given?
|
|
152
|
-
execute.each { |doc| yield doc }
|
|
93
|
+
# <tt>Mongoid::Contexts::Mongo.new(selector, options, klass)</tt>
|
|
94
|
+
def initialize(selector, options, klass)
|
|
95
|
+
@selector, @options, @klass = selector, options, klass
|
|
96
|
+
if klass.hereditary
|
|
97
|
+
@hereditary = true
|
|
153
98
|
end
|
|
154
99
|
end
|
|
155
100
|
|
|
@@ -169,10 +114,12 @@ module Mongoid #:nodoc:
|
|
|
169
114
|
sorting = opts[:sort]
|
|
170
115
|
sorting = [[:_id, :asc]] unless sorting
|
|
171
116
|
opts[:sort] = sorting.collect { |option| [ option[0], option[1].invert ] }
|
|
172
|
-
attributes = klass.collection.find_one(selector, opts)
|
|
173
|
-
attributes ? Mongoid::Factory.build(klass, attributes) : nil
|
|
117
|
+
attributes = @klass.collection.find_one(@selector, opts)
|
|
118
|
+
attributes ? Mongoid::Factory.build(@klass, attributes) : nil
|
|
174
119
|
end
|
|
175
120
|
|
|
121
|
+
MAX_REDUCE = "function(obj, prev) { if (prev.max == 'start') { prev.max = obj.[field]; } " +
|
|
122
|
+
"if (prev.max < obj.[field]) { prev.max = obj.[field]; } }"
|
|
176
123
|
# Return the max value for a field.
|
|
177
124
|
#
|
|
178
125
|
# This will take the internally built selector and options
|
|
@@ -188,9 +135,11 @@ module Mongoid #:nodoc:
|
|
|
188
135
|
#
|
|
189
136
|
# A numeric max value.
|
|
190
137
|
def max(field)
|
|
191
|
-
grouped(:max, field.to_s,
|
|
138
|
+
grouped(:max, field.to_s, MAX_REDUCE)
|
|
192
139
|
end
|
|
193
140
|
|
|
141
|
+
MIN_REDUCE = "function(obj, prev) { if (prev.min == 'start') { prev.min = obj.[field]; } " +
|
|
142
|
+
"if (prev.min > obj.[field]) { prev.min = obj.[field]; } }"
|
|
194
143
|
# Return the min value for a field.
|
|
195
144
|
#
|
|
196
145
|
# This will take the internally built selector and options
|
|
@@ -206,7 +155,7 @@ module Mongoid #:nodoc:
|
|
|
206
155
|
#
|
|
207
156
|
# A numeric minimum value.
|
|
208
157
|
def min(field)
|
|
209
|
-
grouped(:min, field.to_s,
|
|
158
|
+
grouped(:min, field.to_s, MIN_REDUCE)
|
|
210
159
|
end
|
|
211
160
|
|
|
212
161
|
# Return the first result for the +Context+.
|
|
@@ -219,12 +168,13 @@ module Mongoid #:nodoc:
|
|
|
219
168
|
#
|
|
220
169
|
# The first document in the collection.
|
|
221
170
|
def one
|
|
222
|
-
attributes = klass.collection.find_one(selector, process_options)
|
|
223
|
-
attributes ? Mongoid::Factory.build(klass, attributes) : nil
|
|
171
|
+
attributes = @klass.collection.find_one(@selector, process_options)
|
|
172
|
+
attributes ? Mongoid::Factory.build(@klass, attributes) : nil
|
|
224
173
|
end
|
|
225
174
|
|
|
226
175
|
alias :first :one
|
|
227
176
|
|
|
177
|
+
SUM_REDUCE = "function(obj, prev) { if (prev.sum == 'start') { prev.sum = 0; } prev.sum += obj.[field]; }"
|
|
228
178
|
# Sum the context.
|
|
229
179
|
#
|
|
230
180
|
# This will take the internally built selector and options
|
|
@@ -240,17 +190,18 @@ module Mongoid #:nodoc:
|
|
|
240
190
|
#
|
|
241
191
|
# A numeric value that is the sum.
|
|
242
192
|
def sum(field)
|
|
243
|
-
grouped(:sum, field.to_s,
|
|
193
|
+
grouped(:sum, field.to_s, SUM_REDUCE)
|
|
244
194
|
end
|
|
245
195
|
|
|
246
196
|
# Common functionality for grouping operations. Currently used by min, max
|
|
247
197
|
# and sum. Will gsub the field name in the supplied reduce function.
|
|
248
198
|
def grouped(start, field, reduce)
|
|
249
|
-
collection = klass.collection.group(
|
|
199
|
+
collection = @klass.collection.group(
|
|
250
200
|
nil,
|
|
251
|
-
selector,
|
|
201
|
+
@selector,
|
|
252
202
|
{ start => "start" },
|
|
253
|
-
reduce.gsub("[field]", field)
|
|
203
|
+
reduce.gsub("[field]", field),
|
|
204
|
+
true
|
|
254
205
|
)
|
|
255
206
|
collection.empty? ? nil : collection.first[start.to_s]
|
|
256
207
|
end
|
|
@@ -258,28 +209,14 @@ module Mongoid #:nodoc:
|
|
|
258
209
|
# Filters the field list. If no fields have been supplied, then it will be
|
|
259
210
|
# empty. If fields have been defined then _type will be included as well.
|
|
260
211
|
def process_options
|
|
261
|
-
fields = options[:fields]
|
|
212
|
+
fields = @options[:fields]
|
|
262
213
|
if fields && fields.size > 0 && !fields.include?(:_type)
|
|
263
214
|
fields << :_type
|
|
264
|
-
options[:fields] = fields
|
|
215
|
+
@options[:fields] = fields
|
|
265
216
|
end
|
|
266
|
-
options.dup
|
|
217
|
+
@options.dup
|
|
267
218
|
end
|
|
268
219
|
|
|
269
|
-
protected
|
|
270
|
-
|
|
271
|
-
# Iterate over each +Document+ in the results and cache the collection.
|
|
272
|
-
def caching(&block)
|
|
273
|
-
if defined? @collection
|
|
274
|
-
@collection.each(&block)
|
|
275
|
-
else
|
|
276
|
-
@collection = []
|
|
277
|
-
execute.each do |doc|
|
|
278
|
-
@collection << doc
|
|
279
|
-
yield doc if block_given?
|
|
280
|
-
end
|
|
281
|
-
end
|
|
282
|
-
end
|
|
283
220
|
end
|
|
284
221
|
end
|
|
285
222
|
end
|
|
@@ -25,7 +25,7 @@ module Mongoid #:nodoc:
|
|
|
25
25
|
#
|
|
26
26
|
# An +Integer+ page number.
|
|
27
27
|
def page
|
|
28
|
-
skips, limits = options[:skip], options[:limit]
|
|
28
|
+
skips, limits = @options[:skip], @options[:limit]
|
|
29
29
|
(skips && limits) ? (skips + limits) / limits : 1
|
|
30
30
|
end
|
|
31
31
|
|
|
@@ -35,7 +35,7 @@ module Mongoid #:nodoc:
|
|
|
35
35
|
#
|
|
36
36
|
# The +Integer+ number of documents in each page.
|
|
37
37
|
def per_page
|
|
38
|
-
(options[:limit] || 20).to_i
|
|
38
|
+
(@options[:limit] || 20).to_i
|
|
39
39
|
end
|
|
40
40
|
end
|
|
41
41
|
end
|
data/lib/mongoid/contexts.rb
CHANGED
|
@@ -1,25 +1,4 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
|
-
require "mongoid/contexts/ids"
|
|
3
2
|
require "mongoid/contexts/paging"
|
|
4
3
|
require "mongoid/contexts/enumerable"
|
|
5
4
|
require "mongoid/contexts/mongo"
|
|
6
|
-
|
|
7
|
-
module Mongoid
|
|
8
|
-
module Contexts
|
|
9
|
-
# Determines the context to be used for this criteria. If the class is an
|
|
10
|
-
# embedded document, then the context will be the array in the has_many
|
|
11
|
-
# association it is in. If the class is a root, then the database itself
|
|
12
|
-
# will be the context.
|
|
13
|
-
#
|
|
14
|
-
# Example:
|
|
15
|
-
#
|
|
16
|
-
# <tt>Contexts.context_for(criteria)</tt>
|
|
17
|
-
def self.context_for(criteria)
|
|
18
|
-
if criteria.klass.embedded
|
|
19
|
-
return Contexts::Enumerable.new(criteria)
|
|
20
|
-
end
|
|
21
|
-
Contexts::Mongo.new(criteria)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
end
|
|
25
|
-
end
|
data/lib/mongoid/criteria.rb
CHANGED
|
@@ -26,19 +26,15 @@ module Mongoid #:nodoc:
|
|
|
26
26
|
include Enumerable
|
|
27
27
|
|
|
28
28
|
attr_reader :collection, :ids, :klass, :options, :selector
|
|
29
|
+
|
|
29
30
|
attr_accessor :documents
|
|
30
31
|
|
|
31
32
|
delegate \
|
|
32
33
|
:aggregate,
|
|
33
|
-
:avg,
|
|
34
|
-
:blank?,
|
|
35
34
|
:count,
|
|
36
|
-
:distinct,
|
|
37
|
-
:empty?,
|
|
38
35
|
:execute,
|
|
39
36
|
:first,
|
|
40
37
|
:group,
|
|
41
|
-
:id_criteria,
|
|
42
38
|
:last,
|
|
43
39
|
:max,
|
|
44
40
|
:min,
|
|
@@ -79,12 +75,23 @@ module Mongoid #:nodoc:
|
|
|
79
75
|
end
|
|
80
76
|
end
|
|
81
77
|
|
|
78
|
+
# Returns true if the criteria is empty.
|
|
79
|
+
#
|
|
80
|
+
# Example:
|
|
81
|
+
#
|
|
82
|
+
# <tt>criteria.blank?</tt>
|
|
83
|
+
def blank?
|
|
84
|
+
count < 1
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
alias :empty? :blank?
|
|
88
|
+
|
|
82
89
|
# Return or create the context in which this criteria should be executed.
|
|
83
90
|
#
|
|
84
91
|
# This will return an Enumerable context if the class is embedded,
|
|
85
92
|
# otherwise it will return a Mongo context for root classes.
|
|
86
93
|
def context
|
|
87
|
-
@context ||=
|
|
94
|
+
@context ||= determine_context
|
|
88
95
|
end
|
|
89
96
|
|
|
90
97
|
# Iterate over each +Document+ in the results. This can take an optional
|
|
@@ -94,7 +101,10 @@ module Mongoid #:nodoc:
|
|
|
94
101
|
#
|
|
95
102
|
# <tt>criteria.each { |doc| p doc }</tt>
|
|
96
103
|
def each(&block)
|
|
97
|
-
|
|
104
|
+
return each_cached(&block) if cached?
|
|
105
|
+
if block_given?
|
|
106
|
+
execute.each { |doc| yield doc }
|
|
107
|
+
end
|
|
98
108
|
self
|
|
99
109
|
end
|
|
100
110
|
|
|
@@ -124,6 +134,10 @@ module Mongoid #:nodoc:
|
|
|
124
134
|
# klass: The class to execute on.
|
|
125
135
|
def initialize(klass)
|
|
126
136
|
@selector, @options, @klass, @documents = {}, {}, klass, []
|
|
137
|
+
if klass.hereditary
|
|
138
|
+
@selector = { :_type => { "$in" => klass._types } }
|
|
139
|
+
@hereditary = true
|
|
140
|
+
end
|
|
127
141
|
end
|
|
128
142
|
|
|
129
143
|
# Merges another object into this +Criteria+. The other object may be a
|
|
@@ -154,7 +168,7 @@ module Mongoid #:nodoc:
|
|
|
154
168
|
# Returns: <tt>Criteria</tt>
|
|
155
169
|
def method_missing(name, *args)
|
|
156
170
|
if @klass.respond_to?(name)
|
|
157
|
-
new_scope = @klass.send(name
|
|
171
|
+
new_scope = @klass.send(name)
|
|
158
172
|
new_scope.merge(self)
|
|
159
173
|
return new_scope
|
|
160
174
|
else
|
|
@@ -190,17 +204,40 @@ module Mongoid #:nodoc:
|
|
|
190
204
|
klass = args[0]
|
|
191
205
|
params = args[1] || {}
|
|
192
206
|
unless params.is_a?(Hash)
|
|
193
|
-
return
|
|
207
|
+
return id_criteria(klass, params)
|
|
194
208
|
end
|
|
195
|
-
|
|
196
|
-
if conditions.include?(:id)
|
|
197
|
-
conditions[:_id] = conditions[:id]
|
|
198
|
-
conditions.delete(:id)
|
|
199
|
-
end
|
|
200
|
-
return new(klass).where(conditions).extras(params)
|
|
209
|
+
return new(klass).where(params.delete(:conditions) || {}).extras(params)
|
|
201
210
|
end
|
|
202
211
|
|
|
203
212
|
protected
|
|
213
|
+
# Determines the context to be used for this criteria. If the class is an
|
|
214
|
+
# embedded document, then thw context will be the array in the has_many
|
|
215
|
+
# association it is in. If the class is a root, then the database itself
|
|
216
|
+
# will be the context.
|
|
217
|
+
#
|
|
218
|
+
# Example:
|
|
219
|
+
#
|
|
220
|
+
# <tt>criteria#determine_context</tt>
|
|
221
|
+
def determine_context
|
|
222
|
+
if @klass.embedded
|
|
223
|
+
return Contexts::Enumerable.new(@selector, @options, @documents)
|
|
224
|
+
end
|
|
225
|
+
Contexts::Mongo.new(@selector, @options, @klass)
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
# Iterate over each +Document+ in the results and cache the collection.
|
|
229
|
+
def each_cached(&block)
|
|
230
|
+
@collection ||= execute
|
|
231
|
+
if block_given?
|
|
232
|
+
docs = []
|
|
233
|
+
@collection.each do |doc|
|
|
234
|
+
docs << doc
|
|
235
|
+
yield doc
|
|
236
|
+
end
|
|
237
|
+
@collection = docs
|
|
238
|
+
end
|
|
239
|
+
self
|
|
240
|
+
end
|
|
204
241
|
|
|
205
242
|
# Filters the unused options out of the options +Hash+. Currently this
|
|
206
243
|
# takes into account the "page" and "per_page" options that would be passed
|
|
@@ -235,5 +272,26 @@ module Mongoid #:nodoc:
|
|
|
235
272
|
def update_selector(attributes, operator)
|
|
236
273
|
attributes.each { |key, value| @selector[key] = { operator => value } }; self
|
|
237
274
|
end
|
|
275
|
+
|
|
276
|
+
class << self
|
|
277
|
+
# Create a criteria or single document based on an id search. Will handle
|
|
278
|
+
# if a single id has been passed or mulitple ids.
|
|
279
|
+
#
|
|
280
|
+
# Example:
|
|
281
|
+
#
|
|
282
|
+
# Criteria.id_criteria(Person, [1, 2, 3])
|
|
283
|
+
#
|
|
284
|
+
# Returns:
|
|
285
|
+
#
|
|
286
|
+
# The single or multiple documents.
|
|
287
|
+
def id_criteria(klass, params)
|
|
288
|
+
criteria = new(klass).id(params)
|
|
289
|
+
result = params.is_a?(String) ? criteria.one : criteria.entries
|
|
290
|
+
if Mongoid.raise_not_found_error
|
|
291
|
+
raise Errors::DocumentNotFound.new(klass, params) if result.blank?
|
|
292
|
+
end
|
|
293
|
+
return result
|
|
294
|
+
end
|
|
295
|
+
end
|
|
238
296
|
end
|
|
239
297
|
end
|
|
@@ -22,7 +22,6 @@ module Mongoid #:nodoc:
|
|
|
22
22
|
def all(attributes = {})
|
|
23
23
|
update_selector(attributes, "$all")
|
|
24
24
|
end
|
|
25
|
-
alias :all_in :all
|
|
26
25
|
|
|
27
26
|
# Adds a criterion to the +Criteria+ that specifies values that must
|
|
28
27
|
# be matched in order to return results. This is similar to a SQL "WHERE"
|
|
@@ -62,7 +61,6 @@ module Mongoid #:nodoc:
|
|
|
62
61
|
def in(attributes = {})
|
|
63
62
|
update_selector(attributes, "$in")
|
|
64
63
|
end
|
|
65
|
-
alias :any_in :in
|
|
66
64
|
|
|
67
65
|
# Adds a criterion to the +Criteria+ that specifies values that must
|
|
68
66
|
# be matched in order to return results. This is similar to a SQL "WHERE"
|
|
@@ -20,7 +20,8 @@ module Mongoid #:nodoc:
|
|
|
20
20
|
#
|
|
21
21
|
# <tt>criteria.cached?</tt>
|
|
22
22
|
def cached?
|
|
23
|
-
@options
|
|
23
|
+
@cached ||= @options.delete(:cache)
|
|
24
|
+
@cached == true
|
|
24
25
|
end
|
|
25
26
|
|
|
26
27
|
# Flags the criteria to execute against a read-only slave in the pool
|
|
@@ -33,15 +34,6 @@ module Mongoid #:nodoc:
|
|
|
33
34
|
@options.merge!(:enslave => true); self
|
|
34
35
|
end
|
|
35
36
|
|
|
36
|
-
# Will return true if the criteria is enslaved.
|
|
37
|
-
#
|
|
38
|
-
# Example:
|
|
39
|
-
#
|
|
40
|
-
# <tt>criteria.enslaved?</tt>
|
|
41
|
-
def enslaved?
|
|
42
|
-
@options[:enslave] == true
|
|
43
|
-
end
|
|
44
|
-
|
|
45
37
|
# Adds a criterion to the +Criteria+ that specifies additional options
|
|
46
38
|
# to be passed to the Ruby driver, in the exact format for the driver.
|
|
47
39
|
#
|
data/lib/mongoid/document.rb
CHANGED
|
@@ -5,7 +5,12 @@ module Mongoid #:nodoc:
|
|
|
5
5
|
included do
|
|
6
6
|
include Mongoid::Components
|
|
7
7
|
|
|
8
|
-
cattr_accessor
|
|
8
|
+
cattr_accessor \
|
|
9
|
+
:_collection,
|
|
10
|
+
:collection_name,
|
|
11
|
+
:embedded,
|
|
12
|
+
:primary_key,
|
|
13
|
+
:hereditary
|
|
9
14
|
|
|
10
15
|
self.embedded = false
|
|
11
16
|
self.hereditary = false
|
|
@@ -51,7 +56,6 @@ module Mongoid #:nodoc:
|
|
|
51
56
|
if attributes["_id"] || allocating
|
|
52
57
|
document = allocate
|
|
53
58
|
document.instance_variable_set(:@attributes, attributes)
|
|
54
|
-
document.setup_modifications
|
|
55
59
|
return document
|
|
56
60
|
else
|
|
57
61
|
return new(attrs)
|
|
@@ -67,6 +71,8 @@ module Mongoid #:nodoc:
|
|
|
67
71
|
#
|
|
68
72
|
# class Person
|
|
69
73
|
# include Mongoid::Document
|
|
74
|
+
# field :first_name
|
|
75
|
+
# field :last_name
|
|
70
76
|
# key :first_name, :last_name
|
|
71
77
|
# end
|
|
72
78
|
def key(*fields)
|
|
@@ -88,10 +94,11 @@ module Mongoid #:nodoc:
|
|
|
88
94
|
def _types
|
|
89
95
|
@_type ||= (subclasses_of(self).map { |o| o.to_s } + [ self.name ])
|
|
90
96
|
end
|
|
91
|
-
|
|
97
|
+
|
|
92
98
|
# return the list of subclassses for an object
|
|
93
99
|
def subclasses_of(*superclasses) #:nodoc:
|
|
94
100
|
subclasses = []
|
|
101
|
+
|
|
95
102
|
superclasses.each do |sup|
|
|
96
103
|
ObjectSpace.each_object(class << sup; self; end) do |k|
|
|
97
104
|
if k != sup && (k.name.blank? || eval("defined?(::#{k}) && ::#{k}.object_id == k.object_id"))
|
|
@@ -99,6 +106,7 @@ module Mongoid #:nodoc:
|
|
|
99
106
|
end
|
|
100
107
|
end
|
|
101
108
|
end
|
|
109
|
+
|
|
102
110
|
subclasses
|
|
103
111
|
end
|
|
104
112
|
end
|
|
@@ -112,17 +120,6 @@ module Mongoid #:nodoc:
|
|
|
112
120
|
other.attributes.except(:modified_at).except(:created_at)
|
|
113
121
|
end
|
|
114
122
|
|
|
115
|
-
# Delegates to ==
|
|
116
|
-
def eql?(comparison_object)
|
|
117
|
-
self == (comparison_object)
|
|
118
|
-
end
|
|
119
|
-
|
|
120
|
-
# Delegates to id in order to allow two records of the same type and id to work with something like:
|
|
121
|
-
# [ Person.find(1), Person.find(2), Person.find(3) ] & [ Person.find(1), Person.find(4) ] # => [ Person.find(1) ]
|
|
122
|
-
def hash
|
|
123
|
-
id.hash
|
|
124
|
-
end
|
|
125
|
-
|
|
126
123
|
# Introduces a child object into the +Document+ object graph. This will
|
|
127
124
|
# set up the relationships between the parent and child and update the
|
|
128
125
|
# attributes of the parent +Document+.
|
|
@@ -131,6 +128,10 @@ module Mongoid #:nodoc:
|
|
|
131
128
|
#
|
|
132
129
|
# parent: The +Document+ to assimilate with.
|
|
133
130
|
# options: The association +Options+ for the child.
|
|
131
|
+
#
|
|
132
|
+
# Example:
|
|
133
|
+
#
|
|
134
|
+
# <tt>name.assimilate(person, options)</tt>
|
|
134
135
|
def assimilate(parent, options)
|
|
135
136
|
parentize(parent, options.name); notify; self
|
|
136
137
|
end
|
|
@@ -176,12 +177,25 @@ module Mongoid #:nodoc:
|
|
|
176
177
|
"#<#{self.class.name} _id: #{id}, #{attrs}>"
|
|
177
178
|
end
|
|
178
179
|
|
|
179
|
-
#
|
|
180
|
+
# Returns true is the +Document+ has not been persisted to the database,
|
|
181
|
+
# false if it has. This is determined by the variable @new_record
|
|
182
|
+
# and NOT if the object has an id.
|
|
183
|
+
def new_record?
|
|
184
|
+
@new_record == true
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
# Sets the new_record boolean - used after document is saved.
|
|
188
|
+
def new_record=(saved)
|
|
189
|
+
@new_record = saved
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
# Set the changed state of the +Document+ then notify observers that it has changed.
|
|
180
193
|
#
|
|
181
194
|
# Example:
|
|
182
195
|
#
|
|
183
196
|
# <tt>person.notify</tt>
|
|
184
197
|
def notify
|
|
198
|
+
changed(true)
|
|
185
199
|
notify_observers(self)
|
|
186
200
|
end
|
|
187
201
|
|
|
@@ -211,7 +225,6 @@ module Mongoid #:nodoc:
|
|
|
211
225
|
# Reloads the +Document+ attributes from the database.
|
|
212
226
|
def reload
|
|
213
227
|
@attributes = collection.find_one(:_id => id)
|
|
214
|
-
self
|
|
215
228
|
end
|
|
216
229
|
|
|
217
230
|
# Remove a child document from this parent +Document+. Will reset the
|
|
@@ -246,30 +259,6 @@ module Mongoid #:nodoc:
|
|
|
246
259
|
attributes.to_json(options)
|
|
247
260
|
end
|
|
248
261
|
|
|
249
|
-
# Return an object to be encoded into a JSON string.
|
|
250
|
-
# Used by Rails 3's object->JSON chain to create JSON
|
|
251
|
-
# in a backend-agnostic way
|
|
252
|
-
#
|
|
253
|
-
# Example:
|
|
254
|
-
#
|
|
255
|
-
# <tt>person.as_json</tt>
|
|
256
|
-
def as_json(options = nil)
|
|
257
|
-
attributes
|
|
258
|
-
end
|
|
259
|
-
|
|
260
|
-
# Return this document as an object to be encoded as JSON,
|
|
261
|
-
# with any particular items modified on a per-encoder basis.
|
|
262
|
-
# Nothing special is required here since Mongoid bubbles up
|
|
263
|
-
# all the child associations to the parent attribute +Hash+
|
|
264
|
-
# using observers throughout the +Document+ lifecycle.
|
|
265
|
-
#
|
|
266
|
-
# Example:
|
|
267
|
-
#
|
|
268
|
-
# <tt>person.encode_json(encoder)</tt>
|
|
269
|
-
def encode_json(encoder)
|
|
270
|
-
attributes
|
|
271
|
-
end
|
|
272
|
-
|
|
273
262
|
# Returns the id of the Document, used in Rails compatibility.
|
|
274
263
|
def to_param
|
|
275
264
|
id
|
|
@@ -286,7 +275,7 @@ module Mongoid #:nodoc:
|
|
|
286
275
|
#
|
|
287
276
|
# This will also cause the observing +Document+ to notify it's parent if
|
|
288
277
|
# there is any.
|
|
289
|
-
def
|
|
278
|
+
def update(child, clear = false)
|
|
290
279
|
name = child.association_name
|
|
291
280
|
attrs = child.instance_variable_get(:@attributes)
|
|
292
281
|
clear ? @attributes.delete(name) : @attributes.insert(name, attrs)
|
data/lib/mongoid/extensions.rb
CHANGED
|
@@ -4,8 +4,6 @@ require "mongoid/extensions/array/aliasing"
|
|
|
4
4
|
require "mongoid/extensions/array/assimilation"
|
|
5
5
|
require "mongoid/extensions/array/conversions"
|
|
6
6
|
require "mongoid/extensions/array/parentization"
|
|
7
|
-
require "mongoid/extensions/big_decimal/conversions"
|
|
8
|
-
require "mongoid/extensions/binary/conversions"
|
|
9
7
|
require "mongoid/extensions/boolean/conversions"
|
|
10
8
|
require "mongoid/extensions/date/conversions"
|
|
11
9
|
require "mongoid/extensions/datetime/conversions"
|
|
@@ -23,7 +21,6 @@ require "mongoid/extensions/string/conversions"
|
|
|
23
21
|
require "mongoid/extensions/string/inflections"
|
|
24
22
|
require "mongoid/extensions/symbol/inflections"
|
|
25
23
|
require "mongoid/extensions/time/conversions"
|
|
26
|
-
require "mongoid/extensions/objectid/conversions"
|
|
27
24
|
|
|
28
25
|
class Array #:nodoc
|
|
29
26
|
include Mongoid::Extensions::Array::Accessors
|
|
@@ -32,14 +29,6 @@ class Array #:nodoc
|
|
|
32
29
|
include Mongoid::Extensions::Array::Parentization
|
|
33
30
|
end
|
|
34
31
|
|
|
35
|
-
class BigDecimal #:nodoc
|
|
36
|
-
extend Mongoid::Extensions::BigDecimal::Conversions
|
|
37
|
-
end
|
|
38
|
-
|
|
39
|
-
class Binary #:nodoc
|
|
40
|
-
extend Mongoid::Extensions::Binary::Conversions
|
|
41
|
-
end
|
|
42
|
-
|
|
43
32
|
class Boolean #:nodoc
|
|
44
33
|
extend Mongoid::Extensions::Boolean::Conversions
|
|
45
34
|
end
|
|
@@ -93,7 +82,3 @@ end
|
|
|
93
82
|
class Time #:nodoc
|
|
94
83
|
extend Mongoid::Extensions::Time::Conversions
|
|
95
84
|
end
|
|
96
|
-
|
|
97
|
-
class Mongo::ObjectID #:nodoc
|
|
98
|
-
extend Mongoid::Extensions::ObjectID::Conversions
|
|
99
|
-
end
|