mongoid 2.0.2 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -1
- data/Rakefile +3 -2
- data/lib/config/locales/bg.yml +6 -0
- data/lib/config/locales/de.yml +6 -0
- data/lib/config/locales/en-GB.yml +48 -0
- data/lib/config/locales/en.yml +6 -3
- data/lib/config/locales/es.yml +6 -0
- data/lib/config/locales/fr.yml +6 -0
- data/lib/config/locales/hi.yml +39 -0
- data/lib/config/locales/hu.yml +13 -7
- data/lib/config/locales/id.yml +3 -0
- data/lib/config/locales/it.yml +7 -1
- data/lib/config/locales/ja.yml +4 -1
- data/lib/config/locales/kr.yml +9 -34
- data/lib/config/locales/nl.yml +6 -0
- data/lib/config/locales/pl.yml +6 -0
- data/lib/config/locales/pt-BR.yml +6 -0
- data/lib/config/locales/pt.yml +6 -0
- data/lib/config/locales/ro.yml +6 -0
- data/lib/config/locales/ru.yml +6 -0
- data/lib/config/locales/sv.yml +6 -0
- data/lib/config/locales/vi.yml +3 -0
- data/lib/config/locales/zh-CN.yml +6 -0
- data/lib/mongoid.rb +51 -45
- data/lib/mongoid/atomic.rb +145 -0
- data/lib/mongoid/atomic/modifiers.rb +109 -0
- data/lib/mongoid/atomic/paths.rb +3 -0
- data/lib/mongoid/atomic/paths/embedded.rb +43 -0
- data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
- data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
- data/lib/mongoid/atomic/paths/root.rb +40 -0
- data/lib/mongoid/attributes.rb +12 -23
- data/lib/mongoid/attributes/processing.rb +5 -5
- data/lib/mongoid/callbacks.rb +2 -0
- data/lib/mongoid/collection.rb +12 -59
- data/lib/mongoid/collections.rb +23 -20
- data/lib/mongoid/collections/master.rb +6 -4
- data/lib/mongoid/collections/operations.rb +1 -0
- data/lib/mongoid/collections/retry.rb +7 -0
- data/lib/mongoid/components.rb +2 -2
- data/lib/mongoid/config.rb +42 -55
- data/lib/mongoid/config/database.rb +6 -2
- data/lib/mongoid/config/replset_database.rb +7 -3
- data/lib/mongoid/contexts.rb +9 -3
- data/lib/mongoid/contexts/enumerable.rb +7 -3
- data/lib/mongoid/contexts/mongo.rb +139 -101
- data/lib/mongoid/criteria.rb +86 -69
- data/lib/mongoid/criterion/complex.rb +32 -5
- data/lib/mongoid/criterion/inclusion.rb +4 -2
- data/lib/mongoid/criterion/optional.rb +111 -86
- data/lib/mongoid/criterion/selector.rb +8 -4
- data/lib/mongoid/cursor.rb +27 -27
- data/lib/mongoid/dirty.rb +54 -214
- data/lib/mongoid/document.rb +37 -39
- data/lib/mongoid/errors/document_not_found.rb +3 -4
- data/lib/mongoid/errors/invalid_collection.rb +2 -3
- data/lib/mongoid/errors/invalid_database.rb +2 -3
- data/lib/mongoid/errors/invalid_field.rb +2 -3
- data/lib/mongoid/errors/invalid_options.rb +19 -7
- data/lib/mongoid/errors/invalid_type.rb +2 -3
- data/lib/mongoid/errors/mongoid_error.rb +5 -6
- data/lib/mongoid/errors/too_many_nested_attribute_records.rb +2 -3
- data/lib/mongoid/errors/unsupported_version.rb +2 -3
- data/lib/mongoid/errors/validations.rb +2 -3
- data/lib/mongoid/extensions.rb +8 -62
- data/lib/mongoid/extensions/array/deletion.rb +29 -0
- data/lib/mongoid/extensions/false_class/equality.rb +14 -1
- data/lib/mongoid/extensions/hash/criteria_helpers.rb +21 -10
- data/lib/mongoid/extensions/hash/scoping.rb +14 -1
- data/lib/mongoid/extensions/nil/collectionization.rb +12 -1
- data/lib/mongoid/extensions/object/reflections.rb +33 -2
- data/lib/mongoid/extensions/object_id/conversions.rb +2 -36
- data/lib/mongoid/extensions/proc/scoping.rb +14 -1
- data/lib/mongoid/extensions/string/conversions.rb +4 -16
- data/lib/mongoid/extensions/string/inflections.rb +35 -14
- data/lib/mongoid/extensions/symbol/inflections.rb +38 -12
- data/lib/mongoid/extensions/true_class/equality.rb +14 -1
- data/lib/mongoid/extras.rb +11 -30
- data/lib/mongoid/factory.rb +1 -1
- data/lib/mongoid/fields.rb +121 -29
- data/lib/mongoid/fields/mappings.rb +36 -0
- data/lib/mongoid/fields/serializable.rb +131 -0
- data/lib/mongoid/fields/serializable/array.rb +64 -0
- data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
- data/lib/mongoid/fields/serializable/bignum.rb +10 -0
- data/lib/mongoid/fields/serializable/binary.rb +11 -0
- data/lib/mongoid/fields/serializable/boolean.rb +44 -0
- data/lib/mongoid/fields/serializable/date.rb +51 -0
- data/lib/mongoid/fields/serializable/date_time.rb +28 -0
- data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
- data/lib/mongoid/fields/serializable/float.rb +33 -0
- data/lib/mongoid/fields/serializable/foreign_keys/array.rb +56 -0
- data/lib/mongoid/fields/serializable/foreign_keys/object.rb +43 -0
- data/lib/mongoid/fields/serializable/hash.rb +25 -0
- data/lib/mongoid/fields/serializable/integer.rb +33 -0
- data/lib/mongoid/fields/serializable/object.rb +11 -0
- data/lib/mongoid/fields/serializable/object_id.rb +32 -0
- data/lib/mongoid/fields/serializable/range.rb +42 -0
- data/lib/mongoid/fields/serializable/set.rb +42 -0
- data/lib/mongoid/fields/serializable/string.rb +28 -0
- data/lib/mongoid/fields/serializable/symbol.rb +28 -0
- data/lib/mongoid/fields/serializable/time.rb +12 -0
- data/lib/mongoid/fields/serializable/time_with_zone.rb +12 -0
- data/lib/mongoid/fields/serializable/timekeeping.rb +102 -0
- data/lib/mongoid/finders.rb +61 -37
- data/lib/mongoid/hierarchy.rb +43 -8
- data/lib/mongoid/identity_map.rb +106 -0
- data/lib/mongoid/indexes.rb +17 -1
- data/lib/mongoid/javascript.rb +2 -3
- data/lib/mongoid/keys.rb +10 -21
- data/lib/mongoid/logger.rb +22 -1
- data/lib/mongoid/matchers/all.rb +10 -0
- data/lib/mongoid/matchers/default.rb +1 -1
- data/lib/mongoid/matchers/exists.rb +10 -0
- data/lib/mongoid/matchers/gt.rb +10 -0
- data/lib/mongoid/matchers/gte.rb +10 -0
- data/lib/mongoid/matchers/in.rb +10 -0
- data/lib/mongoid/matchers/lt.rb +10 -0
- data/lib/mongoid/matchers/lte.rb +10 -0
- data/lib/mongoid/matchers/ne.rb +10 -0
- data/lib/mongoid/matchers/nin.rb +10 -0
- data/lib/mongoid/matchers/or.rb +7 -4
- data/lib/mongoid/matchers/size.rb +10 -0
- data/lib/mongoid/multi_database.rb +26 -6
- data/lib/mongoid/multi_parameter_attributes.rb +40 -17
- data/lib/mongoid/named_scope.rb +1 -2
- data/lib/mongoid/nested_attributes.rb +4 -1
- data/lib/mongoid/observer.rb +108 -5
- data/lib/mongoid/paranoia.rb +26 -26
- data/lib/mongoid/persistence.rb +15 -21
- data/lib/mongoid/persistence/atomic.rb +135 -0
- data/lib/mongoid/persistence/atomic/add_to_set.rb +11 -8
- data/lib/mongoid/persistence/atomic/bit.rb +37 -0
- data/lib/mongoid/persistence/atomic/inc.rb +9 -6
- data/lib/mongoid/persistence/atomic/operation.rb +48 -7
- data/lib/mongoid/persistence/atomic/pop.rb +34 -0
- data/lib/mongoid/persistence/atomic/pull.rb +34 -0
- data/lib/mongoid/persistence/atomic/pull_all.rb +10 -9
- data/lib/mongoid/persistence/atomic/push.rb +8 -5
- data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
- data/lib/mongoid/persistence/atomic/rename.rb +31 -0
- data/lib/mongoid/persistence/atomic/set.rb +30 -0
- data/lib/mongoid/persistence/atomic/unset.rb +28 -0
- data/lib/mongoid/persistence/deletion.rb +32 -0
- data/lib/mongoid/persistence/insertion.rb +41 -0
- data/lib/mongoid/persistence/modification.rb +37 -0
- data/lib/mongoid/persistence/operations.rb +214 -0
- data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
- data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
- data/lib/mongoid/persistence/operations/insert.rb +34 -0
- data/lib/mongoid/persistence/operations/remove.rb +33 -0
- data/lib/mongoid/persistence/operations/update.rb +53 -0
- data/lib/mongoid/railtie.rb +21 -33
- data/lib/mongoid/railties/database.rake +12 -12
- data/lib/mongoid/relations.rb +9 -5
- data/lib/mongoid/relations/accessors.rb +15 -36
- data/lib/mongoid/relations/auto_save.rb +2 -2
- data/lib/mongoid/relations/binding.rb +28 -1
- data/lib/mongoid/relations/bindings/embedded/in.rb +17 -30
- data/lib/mongoid/relations/bindings/embedded/many.rb +16 -21
- data/lib/mongoid/relations/bindings/embedded/one.rb +11 -16
- data/lib/mongoid/relations/bindings/referenced/in.rb +31 -32
- data/lib/mongoid/relations/bindings/referenced/many.rb +19 -61
- data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -63
- data/lib/mongoid/relations/bindings/referenced/one.rb +18 -26
- data/lib/mongoid/relations/builder.rb +4 -2
- data/lib/mongoid/relations/builders.rb +21 -2
- data/lib/mongoid/relations/builders/embedded/in.rb +5 -1
- data/lib/mongoid/relations/builders/embedded/many.rb +12 -4
- data/lib/mongoid/relations/builders/embedded/one.rb +5 -1
- data/lib/mongoid/relations/builders/nested_attributes/many.rb +2 -2
- data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
- data/lib/mongoid/relations/builders/referenced/in.rb +2 -5
- data/lib/mongoid/relations/builders/referenced/many.rb +2 -3
- data/lib/mongoid/relations/builders/referenced/many_to_many.rb +14 -5
- data/lib/mongoid/relations/builders/referenced/one.rb +2 -3
- data/lib/mongoid/relations/embedded/atomic.rb +2 -2
- data/lib/mongoid/relations/embedded/in.rb +72 -41
- data/lib/mongoid/relations/embedded/many.rb +116 -120
- data/lib/mongoid/relations/embedded/one.rb +59 -41
- data/lib/mongoid/relations/embedded/sort.rb +31 -0
- data/lib/mongoid/relations/macros.rb +28 -24
- data/lib/mongoid/relations/many.rb +10 -103
- data/lib/mongoid/relations/metadata.rb +335 -38
- data/lib/mongoid/relations/one.rb +7 -32
- data/lib/mongoid/relations/options.rb +47 -0
- data/lib/mongoid/relations/proxy.rb +29 -28
- data/lib/mongoid/relations/referenced/batch.rb +2 -3
- data/lib/mongoid/relations/referenced/in.rb +66 -53
- data/lib/mongoid/relations/referenced/many.rb +216 -143
- data/lib/mongoid/relations/referenced/many_to_many.rb +132 -163
- data/lib/mongoid/relations/referenced/one.rb +76 -58
- data/lib/mongoid/relations/synchronization.rb +113 -0
- data/lib/mongoid/relations/targets.rb +2 -0
- data/lib/mongoid/relations/targets/enumerable.rb +329 -0
- data/lib/mongoid/safety.rb +24 -156
- data/lib/mongoid/serialization.rb +21 -0
- data/lib/mongoid/state.rb +34 -0
- data/lib/mongoid/threaded.rb +175 -0
- data/lib/mongoid/timestamps/updated.rb +1 -1
- data/lib/mongoid/validations.rb +3 -7
- data/lib/mongoid/version.rb +1 -1
- data/lib/mongoid/versioning.rb +61 -7
- data/lib/rack/mongoid.rb +2 -0
- data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
- data/lib/rails/generators/mongoid/model/model_generator.rb +1 -1
- data/lib/rails/generators/mongoid/model/templates/{model.rb → model.rb.tt} +0 -0
- data/lib/rails/generators/mongoid/observer/observer_generator.rb +1 -1
- data/lib/rails/generators/mongoid/observer/templates/{observer.rb → observer.rb.tt} +0 -0
- data/lib/rails/mongoid.rb +17 -17
- metadata +136 -102
- data/lib/mongoid/atomicity.rb +0 -111
- data/lib/mongoid/collections/cyclic_iterator.rb +0 -34
- data/lib/mongoid/collections/slaves.rb +0 -61
- data/lib/mongoid/extensions/array/conversions.rb +0 -23
- data/lib/mongoid/extensions/array/parentization.rb +0 -13
- data/lib/mongoid/extensions/big_decimal/conversions.rb +0 -19
- data/lib/mongoid/extensions/binary/conversions.rb +0 -17
- data/lib/mongoid/extensions/boolean/conversions.rb +0 -27
- data/lib/mongoid/extensions/date/conversions.rb +0 -25
- data/lib/mongoid/extensions/datetime/conversions.rb +0 -12
- data/lib/mongoid/extensions/float/conversions.rb +0 -20
- data/lib/mongoid/extensions/hash/conversions.rb +0 -19
- data/lib/mongoid/extensions/integer/conversions.rb +0 -20
- data/lib/mongoid/extensions/object/conversions.rb +0 -25
- data/lib/mongoid/extensions/range/conversions.rb +0 -25
- data/lib/mongoid/extensions/set/conversions.rb +0 -20
- data/lib/mongoid/extensions/symbol/conversions.rb +0 -21
- data/lib/mongoid/extensions/time_conversions.rb +0 -38
- data/lib/mongoid/field.rb +0 -162
- data/lib/mongoid/paths.rb +0 -61
- data/lib/mongoid/persistence/command.rb +0 -71
- data/lib/mongoid/persistence/insert.rb +0 -53
- data/lib/mongoid/persistence/insert_embedded.rb +0 -43
- data/lib/mongoid/persistence/remove.rb +0 -44
- data/lib/mongoid/persistence/remove_all.rb +0 -40
- data/lib/mongoid/persistence/remove_embedded.rb +0 -48
- data/lib/mongoid/persistence/update.rb +0 -77
- data/lib/mongoid/safe.rb +0 -23
- data/lib/mongoid/validations/referenced.rb +0 -58
data/lib/mongoid/criteria.rb
CHANGED
@@ -13,18 +13,15 @@ module Mongoid #:nodoc:
|
|
13
13
|
|
14
14
|
# The +Criteria+ class is the core object needed in Mongoid to retrieve
|
15
15
|
# objects from the database. It is a DSL that essentially sets up the
|
16
|
-
# selector and options arguments that get passed on to a
|
16
|
+
# selector and options arguments that get passed on to a Mongo::Collection
|
17
17
|
# in the Ruby driver. Each method on the +Criteria+ returns self to they
|
18
18
|
# can be chained in order to create a readable criterion to be executed
|
19
19
|
# against the database.
|
20
20
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
# <tt>criteria.only(:field).where(:field => "value").skip(20).limit(20)</tt>
|
26
|
-
#
|
27
|
-
# <tt>criteria.execute</tt>
|
21
|
+
# @example Create and execute a criteria.
|
22
|
+
# criteria = Criteria.new
|
23
|
+
# criteria.only(:field).where(:field => "value").skip(20).limit(20)
|
24
|
+
# criteria.execute
|
28
25
|
class Criteria
|
29
26
|
include Enumerable
|
30
27
|
include Criterion::Builder
|
@@ -45,6 +42,7 @@ module Mongoid #:nodoc:
|
|
45
42
|
:field_list
|
46
43
|
|
47
44
|
delegate \
|
45
|
+
:add_to_set,
|
48
46
|
:aggregate,
|
49
47
|
:avg,
|
50
48
|
:blank?,
|
@@ -62,6 +60,7 @@ module Mongoid #:nodoc:
|
|
62
60
|
:max,
|
63
61
|
:min,
|
64
62
|
:one,
|
63
|
+
:pull,
|
65
64
|
:shift,
|
66
65
|
:sum,
|
67
66
|
:update,
|
@@ -69,12 +68,22 @@ module Mongoid #:nodoc:
|
|
69
68
|
|
70
69
|
# Concatinate the criteria with another enumerable. If the other is a
|
71
70
|
# +Criteria+ then it needs to get the collection from it.
|
71
|
+
#
|
72
|
+
# @example Concat 2 criteria.
|
73
|
+
# criteria + criteria
|
74
|
+
#
|
75
|
+
# @param [ Criteria ] other The other criteria.
|
72
76
|
def +(other)
|
73
77
|
entries + comparable(other)
|
74
78
|
end
|
75
79
|
|
76
80
|
# Returns the difference between the criteria and another enumerable. If
|
77
81
|
# the other is a +Criteria+ then it needs to get the collection from it.
|
82
|
+
#
|
83
|
+
# @example Get the difference of 2 criteria.
|
84
|
+
# criteria - criteria
|
85
|
+
#
|
86
|
+
# @param [ Criteria ] other The other criteria.
|
78
87
|
def -(other)
|
79
88
|
entries - comparable(other)
|
80
89
|
end
|
@@ -82,11 +91,11 @@ module Mongoid #:nodoc:
|
|
82
91
|
# Returns true if the supplied +Enumerable+ or +Criteria+ is equal to the results
|
83
92
|
# of this +Criteria+ or the criteria itself.
|
84
93
|
#
|
85
|
-
# This will force a database load when called if an enumerable is passed.
|
94
|
+
# @note This will force a database load when called if an enumerable is passed.
|
86
95
|
#
|
87
|
-
#
|
96
|
+
# @param [ Object ] other The other +Enumerable+ or +Criteria+ to compare to.
|
88
97
|
#
|
89
|
-
#
|
98
|
+
# @return [ true, false ] If the objects are equal.
|
90
99
|
def ==(other)
|
91
100
|
case other
|
92
101
|
when Criteria
|
@@ -102,6 +111,11 @@ module Mongoid #:nodoc:
|
|
102
111
|
#
|
103
112
|
# This will return an Enumerable context if the class is embedded,
|
104
113
|
# otherwise it will return a Mongo context for root classes.
|
114
|
+
#
|
115
|
+
# @example Get the appropriate context.
|
116
|
+
# criteria.context
|
117
|
+
#
|
118
|
+
# @return [ Mongo, Enumerable ] The appropriate context.
|
105
119
|
def context
|
106
120
|
@context ||= Contexts.context_for(self, embedded)
|
107
121
|
end
|
@@ -109,18 +123,20 @@ module Mongoid #:nodoc:
|
|
109
123
|
# Iterate over each +Document+ in the results. This can take an optional
|
110
124
|
# block to pass to each argument in the results.
|
111
125
|
#
|
112
|
-
#
|
126
|
+
# @example Iterate over the criteria results.
|
127
|
+
# criteria.each { |doc| p doc }
|
113
128
|
#
|
114
|
-
#
|
129
|
+
# @return [ Criteria ] The criteria itself.
|
115
130
|
def each(&block)
|
116
131
|
tap { context.iterate(&block) }
|
117
132
|
end
|
118
133
|
|
119
|
-
# Return true if the criteria has some Document or not
|
134
|
+
# Return true if the criteria has some Document or not.
|
120
135
|
#
|
121
|
-
#
|
136
|
+
# @example Are there any documents for the criteria?
|
137
|
+
# criteria.exists?
|
122
138
|
#
|
123
|
-
#
|
139
|
+
# @return [ true, false ] If documents match.
|
124
140
|
def exists?
|
125
141
|
context.count > 0
|
126
142
|
end
|
@@ -141,15 +157,12 @@ module Mongoid #:nodoc:
|
|
141
157
|
|
142
158
|
# Merges the supplied argument hash into a single criteria
|
143
159
|
#
|
144
|
-
#
|
160
|
+
# @example Fuse the criteria and the object.
|
161
|
+
# criteria.fuse(:where => { :field => "value"}, :limit => 20)
|
145
162
|
#
|
146
|
-
#
|
163
|
+
# @param [ Hash ] criteria_conditions Criteria keys and values.
|
147
164
|
#
|
148
|
-
#
|
149
|
-
#
|
150
|
-
# <tt>criteria.fuse(:where => { :field => "value"}, :limit => 20)</tt>
|
151
|
-
#
|
152
|
-
# Returns <tt>self</tt>
|
165
|
+
# @return [ Criteria ] self.
|
153
166
|
def fuse(criteria_conditions = {})
|
154
167
|
criteria_conditions.inject(self) do |criteria, (key, value)|
|
155
168
|
criteria.send(key, value)
|
@@ -159,10 +172,11 @@ module Mongoid #:nodoc:
|
|
159
172
|
# Create the new +Criteria+ object. This will initialize the selector
|
160
173
|
# and options hashes, as well as the type of criteria.
|
161
174
|
#
|
162
|
-
#
|
175
|
+
# @example Instantiate a new criteria.
|
176
|
+
# Criteria.new(Model, true)
|
163
177
|
#
|
164
|
-
#
|
165
|
-
#
|
178
|
+
# @param [ Class ] klass The model the criteria is for.
|
179
|
+
# @param [ true, false ] embedded Is the criteria for embedded docs.
|
166
180
|
def initialize(klass, embedded = false)
|
167
181
|
@selector = Criterion::Selector.new(klass)
|
168
182
|
@options, @klass, @documents, @embedded = {}, klass, [], embedded
|
@@ -172,13 +186,15 @@ module Mongoid #:nodoc:
|
|
172
186
|
# +Criteria+ or a +Hash+. This is used to combine multiple scopes together,
|
173
187
|
# where a chained scope situation may be desired.
|
174
188
|
#
|
175
|
-
#
|
189
|
+
# @example Merge the criteria with a conditions hash.
|
190
|
+
# criteria.merge({ :conditions => { :title => "Sir" } })
|
176
191
|
#
|
177
|
-
#
|
192
|
+
# @example Merge the criteria with another criteria.
|
193
|
+
# criteri.merge(other_criteria)
|
178
194
|
#
|
179
|
-
#
|
195
|
+
# @param [ Criteria, Hash ] other The other criterion to merge with.
|
180
196
|
#
|
181
|
-
#
|
197
|
+
# @return [ Criteria ] A cloned self.
|
182
198
|
def merge(other)
|
183
199
|
clone.tap do |crit|
|
184
200
|
if other.is_a?(Criteria)
|
@@ -193,36 +209,15 @@ module Mongoid #:nodoc:
|
|
193
209
|
end
|
194
210
|
end
|
195
211
|
|
196
|
-
# Used for chaining +Criteria+ scopes together in the for of class methods
|
197
|
-
# on the +Document+ the criteria is for.
|
198
|
-
#
|
199
|
-
# Options:
|
200
|
-
#
|
201
|
-
# name: The name of the class method on the +Document+ to chain.
|
202
|
-
# args: The arguments passed to the method.
|
203
|
-
# block: Optional block to pass
|
204
|
-
#
|
205
|
-
# Returns: <tt>Criteria</tt>
|
206
|
-
def method_missing(name, *args, &block)
|
207
|
-
if @klass.respond_to?(name)
|
208
|
-
@klass.send(:with_scope, self) do
|
209
|
-
@klass.send(name, *args, &block)
|
210
|
-
end
|
211
|
-
else
|
212
|
-
return entries.send(name, *args)
|
213
|
-
end
|
214
|
-
end
|
215
|
-
|
216
212
|
# Returns true if criteria responds to the given method.
|
217
213
|
#
|
218
|
-
#
|
219
|
-
#
|
220
|
-
# name: The name of the class method on the +Document+.
|
221
|
-
# include_private: The arguments passed to the method.
|
214
|
+
# @example Does the criteria respond to the method?
|
215
|
+
# crtiteria.respond_to?(:each)
|
222
216
|
#
|
223
|
-
#
|
217
|
+
# @param [ Symbol ] name The name of the class method on the +Document+.
|
218
|
+
# @param [ true, false ] include_private Whether to include privates.
|
224
219
|
#
|
225
|
-
#
|
220
|
+
# @return [ true, false ] If the criteria responds to the method.
|
226
221
|
def respond_to?(name, include_private = false)
|
227
222
|
# don't include klass private methods because method_missing won't call them
|
228
223
|
super || @klass.respond_to?(name) || entries.respond_to?(name, include_private)
|
@@ -230,6 +225,11 @@ module Mongoid #:nodoc:
|
|
230
225
|
|
231
226
|
# Returns the selector and options as a +Hash+ that would be passed to a
|
232
227
|
# scope for use with named scopes.
|
228
|
+
#
|
229
|
+
# @example Get the criteria as a scoped hash.
|
230
|
+
# criteria.scoped
|
231
|
+
#
|
232
|
+
# @return [ Hash ] The criteria as a scoped hash.
|
233
233
|
def scoped
|
234
234
|
scope_options = @options.dup
|
235
235
|
sorting = scope_options.delete(:sort)
|
@@ -303,6 +303,13 @@ module Mongoid #:nodoc:
|
|
303
303
|
|
304
304
|
# Return the entries of the other criteria or the object. Used for
|
305
305
|
# comparing criteria or an enumerable.
|
306
|
+
#
|
307
|
+
# @example Get the comparable version.
|
308
|
+
# criteria.comparable(other)
|
309
|
+
#
|
310
|
+
# @param [ Criteria ] other Another criteria.
|
311
|
+
#
|
312
|
+
# @return [ Array ] The array to compare with.
|
306
313
|
def comparable(other)
|
307
314
|
other.is_a?(Criteria) ? other.entries : other
|
308
315
|
end
|
@@ -310,36 +317,46 @@ module Mongoid #:nodoc:
|
|
310
317
|
# Clone or dup the current +Criteria+. This will return a new criteria with
|
311
318
|
# the selector, options, klass, embedded options, etc intact.
|
312
319
|
#
|
313
|
-
#
|
314
|
-
#
|
315
|
-
# <tt>criteria.clone</tt>
|
316
|
-
# <tt>criteria.dup</tt>
|
320
|
+
# @example Clone a criteria.
|
321
|
+
# criteria.clone
|
317
322
|
#
|
318
|
-
#
|
323
|
+
# @example Dup a criteria.
|
324
|
+
# criteria.dup
|
319
325
|
#
|
320
|
-
# other
|
326
|
+
# @param [ Criteria ] other The criteria getting cloned.
|
321
327
|
#
|
322
|
-
#
|
323
|
-
#
|
324
|
-
# A new identical criteria
|
328
|
+
# @return [ nil ] nil.
|
325
329
|
def initialize_copy(other)
|
326
330
|
@selector = other.selector.dup
|
327
331
|
@options = other.options.dup
|
328
332
|
@context = nil
|
329
333
|
end
|
330
334
|
|
335
|
+
# Used for chaining +Criteria+ scopes together in the for of class methods
|
336
|
+
# on the +Document+ the criteria is for.
|
337
|
+
def method_missing(name, *args, &block)
|
338
|
+
if @klass.respond_to?(name)
|
339
|
+
@klass.send(:with_scope, self) do
|
340
|
+
@klass.send(name, *args, &block)
|
341
|
+
end
|
342
|
+
else
|
343
|
+
return entries.send(name, *args)
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
331
347
|
# Update the selector setting the operator on the value for each key in the
|
332
348
|
# supplied attributes +Hash+.
|
333
349
|
#
|
334
|
-
#
|
335
|
-
#
|
336
|
-
# <tt>criteria.update_selector({ :field => "value" }, "$in")</tt>
|
350
|
+
# @example Update the selector.
|
351
|
+
# criteria.update_selector({ :field => "value" }, "$in")
|
337
352
|
#
|
353
|
+
# @param [ Hash, Array ] attributes The values to convert and apply.
|
354
|
+
# @param [ String ] operator The MongoDB operator.
|
338
355
|
# @param [ Symbol ] combine The operator to use when combining sets.
|
339
356
|
def update_selector(attributes, operator, combine = :+)
|
340
357
|
clone.tap do |crit|
|
341
358
|
converted = BSON::ObjectId.convert(klass, attributes || {})
|
342
|
-
converted.
|
359
|
+
converted.each_pair do |key, value|
|
343
360
|
unless crit.selector[key]
|
344
361
|
crit.selector[key] = { operator => value }
|
345
362
|
else
|
@@ -1,30 +1,57 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
module Mongoid #:nodoc:
|
3
3
|
module Criterion #:nodoc:
|
4
|
+
|
4
5
|
# Complex criterion are used when performing operations on symbols to get
|
5
6
|
# get a shorthand syntax for where clauses.
|
6
7
|
#
|
7
|
-
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
# <tt> { :field.lt => "value }</tt>
|
8
|
+
# @example Conversion of a simple to complex criterion.
|
9
|
+
# { :field => { "$lt" => "value" } }
|
10
|
+
# becomes:
|
11
|
+
# { :field.lt => "value }
|
12
12
|
class Complex
|
13
13
|
attr_accessor :key, :operator
|
14
14
|
|
15
15
|
# Create the new complex criterion.
|
16
|
+
#
|
17
|
+
# @example Instantiate a new complex criterion.
|
18
|
+
# Complex.new(:key => :field, :operator => "$gt")
|
19
|
+
#
|
20
|
+
# @param [ Hash ] opts The options to convert.
|
16
21
|
def initialize(opts = {})
|
17
22
|
@key, @operator = opts[:key], opts[:operator]
|
18
23
|
end
|
19
24
|
|
25
|
+
# Get the criterion as a hash.
|
26
|
+
#
|
27
|
+
# @example Get the criterion as a hash.
|
28
|
+
# criterion.hash
|
29
|
+
#
|
30
|
+
# @return [ Hash ] The keys and operators.
|
20
31
|
def hash
|
21
32
|
[@key, @operator].hash
|
22
33
|
end
|
23
34
|
|
35
|
+
# Is the criterion equal to the other?
|
36
|
+
#
|
37
|
+
# @example Check equality.
|
38
|
+
# criterion.eql?(other)
|
39
|
+
#
|
40
|
+
# @param [ Complex ] other The other complex criterion.
|
41
|
+
#
|
42
|
+
# @return [ true, false ] If they are equal.
|
24
43
|
def eql?(other)
|
25
44
|
self == (other)
|
26
45
|
end
|
27
46
|
|
47
|
+
# Is the criterion equal to the other?
|
48
|
+
#
|
49
|
+
# @example Check equality.
|
50
|
+
# criterion == other
|
51
|
+
#
|
52
|
+
# @param [ Complex ] other The other complex criterion.
|
53
|
+
#
|
54
|
+
# @return [ true, false ] If they are equal.
|
28
55
|
def ==(other)
|
29
56
|
return false unless other.is_a?(self.class)
|
30
57
|
self.key == other.key && self.operator == other.operator
|
@@ -67,7 +67,7 @@ module Mongoid #:nodoc:
|
|
67
67
|
clone.tap do |crit|
|
68
68
|
criterion = @selector["$or"] || []
|
69
69
|
converted = BSON::ObjectId.convert(klass, args.flatten)
|
70
|
-
expanded = converted.collect
|
70
|
+
expanded = converted.collect { |hash| hash.expand_complex_criteria }
|
71
71
|
crit.selector["$or"] = criterion.concat(expanded)
|
72
72
|
end
|
73
73
|
end
|
@@ -159,7 +159,9 @@ module Mongoid #:nodoc:
|
|
159
159
|
end
|
160
160
|
|
161
161
|
selector.each_pair do |key, value|
|
162
|
-
if crit.selector.has_key?(key) &&
|
162
|
+
if crit.selector.has_key?(key) &&
|
163
|
+
crit.selector[key].respond_to?(:merge!) &&
|
164
|
+
value.respond_to?(:merge!)
|
163
165
|
crit.selector[key] =
|
164
166
|
crit.selector[key].merge!(value) do |key, old, new|
|
165
167
|
key == '$in' ? old & new : new
|
@@ -6,13 +6,17 @@ module Mongoid #:nodoc:
|
|
6
6
|
# Adds fields to be sorted in ascending order. Will add them in the order
|
7
7
|
# they were passed into the method.
|
8
8
|
#
|
9
|
-
#
|
9
|
+
# @example Sort in ascending order.
|
10
|
+
# criteria.ascending(:title, :dob)
|
11
|
+
# criteria.asc(:title, :dob)
|
10
12
|
#
|
11
|
-
# <
|
13
|
+
# @param [ Array<Symbol> ] fields The fields to sort on.
|
14
|
+
#
|
15
|
+
# @return [ Criteria ] The cloned criteria.
|
12
16
|
def ascending(*fields)
|
13
17
|
clone.tap do |crit|
|
14
18
|
crit.options[:sort] = [] unless options[:sort] || fields.first.nil?
|
15
|
-
fields.flatten.each { |field| crit.options[:sort]
|
19
|
+
fields.flatten.each { |field| merge_options(crit.options[:sort], [ field, :asc ]) }
|
16
20
|
end
|
17
21
|
end
|
18
22
|
alias :asc :ascending
|
@@ -22,18 +26,20 @@ module Mongoid #:nodoc:
|
|
22
26
|
# times, however this is not advisable when working with large data sets
|
23
27
|
# as the entire results will get stored in memory.
|
24
28
|
#
|
25
|
-
#
|
29
|
+
# @example Flag the criteria as cached.
|
30
|
+
# criteria.cache
|
26
31
|
#
|
27
|
-
#
|
32
|
+
# @return [ Criteria ] The cloned criteria.
|
28
33
|
def cache
|
29
34
|
clone.tap { |crit| crit.options.merge!(:cache => true) }
|
30
35
|
end
|
31
36
|
|
32
37
|
# Will return true if the cache option has been set.
|
33
38
|
#
|
34
|
-
#
|
39
|
+
# @example Is the criteria cached?
|
40
|
+
# criteria.cached?
|
35
41
|
#
|
36
|
-
#
|
42
|
+
# @return [ true, false ] If the criteria is flagged as cached.
|
37
43
|
def cached?
|
38
44
|
options[:cache] == true
|
39
45
|
end
|
@@ -41,48 +47,30 @@ module Mongoid #:nodoc:
|
|
41
47
|
# Adds fields to be sorted in descending order. Will add them in the order
|
42
48
|
# they were passed into the method.
|
43
49
|
#
|
44
|
-
#
|
50
|
+
# @example Sort the criteria in descending order.
|
51
|
+
# criteria.descending(:title, :dob)
|
52
|
+
# criteria.desc(:title, :dob)
|
53
|
+
#
|
54
|
+
# @param [ Array<Symbol> ] fields The fields to sort on.
|
45
55
|
#
|
46
|
-
#
|
56
|
+
# @return [ Criteria ] The cloned criteria.
|
47
57
|
def descending(*fields)
|
48
58
|
clone.tap do |crit|
|
49
59
|
crit.options[:sort] = [] unless options[:sort] || fields.first.nil?
|
50
|
-
fields.flatten.each { |field| crit.options[:sort]
|
60
|
+
fields.flatten.each { |field| merge_options(crit.options[:sort], [ field, :desc ]) }
|
51
61
|
end
|
52
62
|
end
|
53
63
|
alias :desc :descending
|
54
64
|
|
55
|
-
# Flags the criteria to execute against a read-only slave in the pool
|
56
|
-
# instead of master.
|
57
|
-
#
|
58
|
-
# Example:
|
59
|
-
#
|
60
|
-
# <tt>criteria.enslave</tt>
|
61
|
-
def enslave
|
62
|
-
clone.tap { |crit| crit.options.merge!(:enslave => true) }
|
63
|
-
end
|
64
|
-
|
65
|
-
# Will return true if the criteria is enslaved.
|
66
|
-
#
|
67
|
-
# Example:
|
68
|
-
#
|
69
|
-
# <tt>criteria.enslaved?</tt>
|
70
|
-
def enslaved?
|
71
|
-
options[:enslave] == true
|
72
|
-
end
|
73
|
-
|
74
65
|
# Adds a criterion to the +Criteria+ that specifies additional options
|
75
66
|
# to be passed to the Ruby driver, in the exact format for the driver.
|
76
67
|
#
|
77
|
-
#
|
78
|
-
#
|
79
|
-
# extras: A +Hash+ that gets set to the driver options.
|
68
|
+
# @example Add extra params to the criteria.
|
69
|
+
# criteria.extras(:limit => 20, :skip => 40)
|
80
70
|
#
|
81
|
-
#
|
71
|
+
# @param [ Hash ] extras The extra driver options.
|
82
72
|
#
|
83
|
-
#
|
84
|
-
#
|
85
|
-
# Returns: <tt>self</tt>
|
73
|
+
# @return [ Criteria ] The cloned criteria.
|
86
74
|
def extras(extras)
|
87
75
|
clone.tap do |crit|
|
88
76
|
crit.options.merge!(extras)
|
@@ -91,16 +79,15 @@ module Mongoid #:nodoc:
|
|
91
79
|
|
92
80
|
# Adds a criterion to the +Criteria+ that specifies an id that must be matched.
|
93
81
|
#
|
94
|
-
#
|
95
|
-
#
|
96
|
-
# object_id: A single id or an array of ids in +String+ or <tt>BSON::ObjectId</tt> format
|
82
|
+
# @example Add a single id criteria.
|
83
|
+
# criteria.for_ids("4ab2bc4b8ad548971900005c")
|
97
84
|
#
|
98
|
-
#
|
85
|
+
# @example Add multiple id criteria.
|
86
|
+
# criteria.for_ids(["4ab2bc4b8ad548971900005c", "4c454e7ebf4b98032d000001"])
|
99
87
|
#
|
100
|
-
#
|
101
|
-
# <tt>criteria.for_ids(["4ab2bc4b8ad548971900005c", "4c454e7ebf4b98032d000001"])</tt>
|
88
|
+
# @param [ Array ] ids: A single id or an array of ids.
|
102
89
|
#
|
103
|
-
#
|
90
|
+
# @return [ Criteria ] The cloned criteria.
|
104
91
|
def for_ids(*ids)
|
105
92
|
ids.flatten!
|
106
93
|
if ids.size > 1
|
@@ -116,18 +103,15 @@ module Mongoid #:nodoc:
|
|
116
103
|
end
|
117
104
|
|
118
105
|
# Adds a criterion to the +Criteria+ that specifies the maximum number of
|
119
|
-
# results to return. This is mostly used in conjunction with
|
106
|
+
# results to return. This is mostly used in conjunction with skip()
|
120
107
|
# to handle paginated results.
|
121
108
|
#
|
122
|
-
#
|
123
|
-
#
|
124
|
-
# value: An +Integer+ specifying the max number of results. Defaults to 20.
|
109
|
+
# @example Limit the result set size.
|
110
|
+
# criteria.limit(100)
|
125
111
|
#
|
126
|
-
#
|
112
|
+
# @param [ Integer ] value The max number of results.
|
127
113
|
#
|
128
|
-
#
|
129
|
-
#
|
130
|
-
# Returns: <tt>self</tt>
|
114
|
+
# @return [ Criteria ] The cloned criteria.
|
131
115
|
def limit(value = 20)
|
132
116
|
clone.tap { |crit| crit.options[:limit] = value }
|
133
117
|
end
|
@@ -135,6 +119,11 @@ module Mongoid #:nodoc:
|
|
135
119
|
# Returns the offset option. If a per_page option is in the list then it
|
136
120
|
# will replace it with a skip parameter and return the same value. Defaults
|
137
121
|
# to 20 if nothing was provided.
|
122
|
+
#
|
123
|
+
# @example Get the offset.
|
124
|
+
# criteria.offset(10)
|
125
|
+
#
|
126
|
+
# @return [ Integer ] The number of documents to skip.
|
138
127
|
def offset(*args)
|
139
128
|
args.size > 0 ? skip(args.first) : options[:skip]
|
140
129
|
end
|
@@ -142,30 +131,25 @@ module Mongoid #:nodoc:
|
|
142
131
|
# Adds a criterion to the +Criteria+ that specifies the sort order of
|
143
132
|
# the returned documents in the database. Similar to a SQL "ORDER BY".
|
144
133
|
#
|
145
|
-
#
|
146
|
-
#
|
147
|
-
# params: An +Array+ of [field, direction] sorting pairs.
|
148
|
-
#
|
149
|
-
# Example:
|
134
|
+
# @example Order by specific fields.
|
135
|
+
# criteria.order_by([[:field1, :asc], [:field2, :desc]])
|
150
136
|
#
|
151
|
-
#
|
137
|
+
# @param [ Array ] params: An +Array+ of [field, direction] sorting pairs.
|
152
138
|
#
|
153
|
-
#
|
139
|
+
# @return [ Criteria ] The cloned criteria.
|
154
140
|
def order_by(*args)
|
155
141
|
clone.tap do |crit|
|
142
|
+
arguments = args.size == 1 ? args.first : args
|
156
143
|
crit.options[:sort] = [] unless options[:sort] || args.first.nil?
|
157
|
-
arguments
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
when Array
|
164
|
-
crit.options[:sort].concat(arguments)
|
165
|
-
when Complex
|
166
|
-
args.flatten.each do |complex|
|
167
|
-
crit.options[:sort] << [ complex.key, complex.operator.to_sym ]
|
144
|
+
if arguments.is_a?(Array)
|
145
|
+
#[:name, :asc]
|
146
|
+
if arguments.size == 2 && (arguments.first.is_a?(Symbol) || arguments.first.is_a?(String))
|
147
|
+
build_order_options(arguments, crit)
|
148
|
+
else
|
149
|
+
arguments.each { |argument| build_order_options(argument, crit) }
|
168
150
|
end
|
151
|
+
else
|
152
|
+
build_order_options(arguments, crit)
|
169
153
|
end
|
170
154
|
end
|
171
155
|
end
|
@@ -173,40 +157,81 @@ module Mongoid #:nodoc:
|
|
173
157
|
|
174
158
|
# Adds a criterion to the +Criteria+ that specifies how many results to skip
|
175
159
|
# when returning Documents. This is mostly used in conjunction with
|
176
|
-
#
|
160
|
+
# limit() to handle paginated results, and is similar to the
|
177
161
|
# traditional "offset" parameter.
|
178
162
|
#
|
179
|
-
#
|
180
|
-
#
|
181
|
-
# value: An +Integer+ specifying the number of results to skip. Defaults to 0.
|
163
|
+
# @example Skip a specified number of documents.
|
164
|
+
# criteria.skip(20)
|
182
165
|
#
|
183
|
-
#
|
166
|
+
# @param [ Integer ] value The number of results to skip.
|
184
167
|
#
|
185
|
-
#
|
186
|
-
#
|
187
|
-
# Returns: <tt>self</tt>
|
168
|
+
# @return [ Criteria ] The cloned criteria.
|
188
169
|
def skip(value = 0)
|
189
170
|
clone.tap { |crit| crit.options[:skip] = value }
|
190
171
|
end
|
191
172
|
|
192
173
|
# Adds a criterion to the +Criteria+ that specifies a type or an Array of
|
193
|
-
#
|
194
|
-
#
|
195
|
-
# Options:
|
196
|
-
#
|
197
|
-
# types : An +Array+ of types of a +String+ representing the Type of you search
|
174
|
+
# types that must be matched.
|
198
175
|
#
|
199
|
-
#
|
176
|
+
# @example Match only specific models.
|
177
|
+
# criteria.type('Browser')
|
178
|
+
# criteria.type(['Firefox', 'Browser'])
|
200
179
|
#
|
201
|
-
# <
|
202
|
-
# <tt>criteria.type(['Firefox', 'Browser'])</tt>
|
180
|
+
# @param [ Array<String> ] types The types to match against.
|
203
181
|
#
|
204
|
-
#
|
182
|
+
# @return [ Criteria ] The cloned criteria.
|
205
183
|
def type(types)
|
206
184
|
types = [types] unless types.is_a?(Array)
|
207
185
|
any_in(:_type => types)
|
208
186
|
end
|
209
187
|
|
188
|
+
private
|
189
|
+
|
190
|
+
# Build ordering options from given arguments on given criteria
|
191
|
+
#
|
192
|
+
# @example build order options
|
193
|
+
# criteria.build_order_options(:name.asc, criteria)
|
194
|
+
#
|
195
|
+
#
|
196
|
+
# @param [ <Hash>, <Array>, <Complex> ] argument to build criteria from
|
197
|
+
# @param [ Criterion ] criterion to change
|
198
|
+
def build_order_options(arguments, crit)
|
199
|
+
case arguments
|
200
|
+
when Hash
|
201
|
+
if arguments.size > 1
|
202
|
+
raise ArgumentError, "Please don't use hash to define multiple orders " +
|
203
|
+
"due to the fact that hash doesn't have order this may cause unpredictable results"
|
204
|
+
end
|
205
|
+
arguments.each_pair do |field, direction|
|
206
|
+
merge_options(crit.options[:sort], [ field, direction ])
|
207
|
+
end
|
208
|
+
when Array
|
209
|
+
merge_options(crit.options[:sort],arguments)
|
210
|
+
when Complex
|
211
|
+
merge_options(crit.options[:sort], [ arguments.key, arguments.operator.to_sym ])
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
215
|
+
# Merge options for order_by criterion
|
216
|
+
# Allow only one order direction for same field
|
217
|
+
#
|
218
|
+
# @example Merge ordering options
|
219
|
+
# criteria.merge_options([[:title, :asc], [:created_at, :asc]], [:title, :desc])
|
220
|
+
#
|
221
|
+
#
|
222
|
+
# @param [ Array<Array> ] Existing options
|
223
|
+
# @param [ Array ] New option for merge.
|
224
|
+
#
|
225
|
+
# @since 2.1.0
|
226
|
+
def merge_options(options, new_option)
|
227
|
+
old_option = options.assoc(new_option.first)
|
228
|
+
|
229
|
+
if old_option
|
230
|
+
options[options.index(old_option)] = new_option.flatten
|
231
|
+
else
|
232
|
+
options << new_option.flatten
|
233
|
+
end
|
234
|
+
end
|
210
235
|
end
|
211
236
|
end
|
212
237
|
end
|