mongoid-braxton 2.0.2

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.
Files changed (226) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +50 -0
  3. data/Rakefile +51 -0
  4. data/lib/config/locales/bg.yml +41 -0
  5. data/lib/config/locales/de.yml +41 -0
  6. data/lib/config/locales/en.yml +45 -0
  7. data/lib/config/locales/es.yml +41 -0
  8. data/lib/config/locales/fr.yml +42 -0
  9. data/lib/config/locales/hu.yml +44 -0
  10. data/lib/config/locales/id.yml +46 -0
  11. data/lib/config/locales/it.yml +39 -0
  12. data/lib/config/locales/ja.yml +40 -0
  13. data/lib/config/locales/kr.yml +65 -0
  14. data/lib/config/locales/nl.yml +39 -0
  15. data/lib/config/locales/pl.yml +39 -0
  16. data/lib/config/locales/pt-BR.yml +40 -0
  17. data/lib/config/locales/pt.yml +40 -0
  18. data/lib/config/locales/ro.yml +46 -0
  19. data/lib/config/locales/ru.yml +41 -0
  20. data/lib/config/locales/sv.yml +40 -0
  21. data/lib/config/locales/vi.yml +45 -0
  22. data/lib/config/locales/zh-CN.yml +33 -0
  23. data/lib/mongoid.rb +140 -0
  24. data/lib/mongoid/atomicity.rb +111 -0
  25. data/lib/mongoid/attributes.rb +185 -0
  26. data/lib/mongoid/attributes/processing.rb +145 -0
  27. data/lib/mongoid/callbacks.rb +23 -0
  28. data/lib/mongoid/collection.rb +137 -0
  29. data/lib/mongoid/collections.rb +71 -0
  30. data/lib/mongoid/collections/master.rb +37 -0
  31. data/lib/mongoid/collections/operations.rb +42 -0
  32. data/lib/mongoid/collections/retry.rb +39 -0
  33. data/lib/mongoid/components.rb +45 -0
  34. data/lib/mongoid/config.rb +349 -0
  35. data/lib/mongoid/config/database.rb +167 -0
  36. data/lib/mongoid/config/replset_database.rb +78 -0
  37. data/lib/mongoid/contexts.rb +19 -0
  38. data/lib/mongoid/contexts/enumerable.rb +275 -0
  39. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  40. data/lib/mongoid/contexts/mongo.rb +345 -0
  41. data/lib/mongoid/copyable.rb +46 -0
  42. data/lib/mongoid/criteria.rb +357 -0
  43. data/lib/mongoid/criterion/builder.rb +34 -0
  44. data/lib/mongoid/criterion/complex.rb +34 -0
  45. data/lib/mongoid/criterion/creational.rb +34 -0
  46. data/lib/mongoid/criterion/exclusion.rb +108 -0
  47. data/lib/mongoid/criterion/inclusion.rb +198 -0
  48. data/lib/mongoid/criterion/inspection.rb +22 -0
  49. data/lib/mongoid/criterion/optional.rb +193 -0
  50. data/lib/mongoid/criterion/selector.rb +143 -0
  51. data/lib/mongoid/criterion/unconvertable.rb +20 -0
  52. data/lib/mongoid/cursor.rb +86 -0
  53. data/lib/mongoid/default_scope.rb +36 -0
  54. data/lib/mongoid/dirty.rb +253 -0
  55. data/lib/mongoid/document.rb +284 -0
  56. data/lib/mongoid/errors.rb +13 -0
  57. data/lib/mongoid/errors/document_not_found.rb +29 -0
  58. data/lib/mongoid/errors/invalid_collection.rb +19 -0
  59. data/lib/mongoid/errors/invalid_database.rb +20 -0
  60. data/lib/mongoid/errors/invalid_field.rb +19 -0
  61. data/lib/mongoid/errors/invalid_options.rb +16 -0
  62. data/lib/mongoid/errors/invalid_type.rb +26 -0
  63. data/lib/mongoid/errors/mixed_relations.rb +37 -0
  64. data/lib/mongoid/errors/mongoid_error.rb +27 -0
  65. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +21 -0
  66. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  67. data/lib/mongoid/errors/unsupported_version.rb +21 -0
  68. data/lib/mongoid/errors/validations.rb +24 -0
  69. data/lib/mongoid/extensions.rb +123 -0
  70. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  71. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  72. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  73. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  74. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  75. data/lib/mongoid/extensions/date/conversions.rb +25 -0
  76. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  77. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  78. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  79. data/lib/mongoid/extensions/hash/conversions.rb +19 -0
  80. data/lib/mongoid/extensions/hash/criteria_helpers.rb +22 -0
  81. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  82. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  83. data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
  84. data/lib/mongoid/extensions/object/checks.rb +32 -0
  85. data/lib/mongoid/extensions/object/conversions.rb +25 -0
  86. data/lib/mongoid/extensions/object/reflections.rb +17 -0
  87. data/lib/mongoid/extensions/object/yoda.rb +27 -0
  88. data/lib/mongoid/extensions/object_id/conversions.rb +96 -0
  89. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  90. data/lib/mongoid/extensions/range/conversions.rb +25 -0
  91. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  92. data/lib/mongoid/extensions/string/conversions.rb +34 -0
  93. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  94. data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
  95. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  96. data/lib/mongoid/extensions/time_conversions.rb +38 -0
  97. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  98. data/lib/mongoid/extras.rb +42 -0
  99. data/lib/mongoid/factory.rb +37 -0
  100. data/lib/mongoid/field.rb +162 -0
  101. data/lib/mongoid/fields.rb +183 -0
  102. data/lib/mongoid/finders.rb +127 -0
  103. data/lib/mongoid/hierarchy.rb +85 -0
  104. data/lib/mongoid/identity.rb +92 -0
  105. data/lib/mongoid/indexes.rb +38 -0
  106. data/lib/mongoid/inspection.rb +54 -0
  107. data/lib/mongoid/javascript.rb +21 -0
  108. data/lib/mongoid/javascript/functions.yml +37 -0
  109. data/lib/mongoid/json.rb +16 -0
  110. data/lib/mongoid/keys.rb +131 -0
  111. data/lib/mongoid/logger.rb +18 -0
  112. data/lib/mongoid/matchers.rb +32 -0
  113. data/lib/mongoid/matchers/all.rb +11 -0
  114. data/lib/mongoid/matchers/default.rb +70 -0
  115. data/lib/mongoid/matchers/exists.rb +13 -0
  116. data/lib/mongoid/matchers/gt.rb +11 -0
  117. data/lib/mongoid/matchers/gte.rb +11 -0
  118. data/lib/mongoid/matchers/in.rb +11 -0
  119. data/lib/mongoid/matchers/lt.rb +11 -0
  120. data/lib/mongoid/matchers/lte.rb +11 -0
  121. data/lib/mongoid/matchers/ne.rb +11 -0
  122. data/lib/mongoid/matchers/nin.rb +11 -0
  123. data/lib/mongoid/matchers/or.rb +30 -0
  124. data/lib/mongoid/matchers/size.rb +11 -0
  125. data/lib/mongoid/matchers/strategies.rb +63 -0
  126. data/lib/mongoid/multi_database.rb +11 -0
  127. data/lib/mongoid/multi_parameter_attributes.rb +82 -0
  128. data/lib/mongoid/named_scope.rb +137 -0
  129. data/lib/mongoid/nested_attributes.rb +51 -0
  130. data/lib/mongoid/observer.rb +67 -0
  131. data/lib/mongoid/paranoia.rb +103 -0
  132. data/lib/mongoid/paths.rb +61 -0
  133. data/lib/mongoid/persistence.rb +240 -0
  134. data/lib/mongoid/persistence/atomic.rb +88 -0
  135. data/lib/mongoid/persistence/atomic/add_to_set.rb +32 -0
  136. data/lib/mongoid/persistence/atomic/inc.rb +28 -0
  137. data/lib/mongoid/persistence/atomic/operation.rb +44 -0
  138. data/lib/mongoid/persistence/atomic/pull_all.rb +33 -0
  139. data/lib/mongoid/persistence/atomic/push.rb +28 -0
  140. data/lib/mongoid/persistence/command.rb +71 -0
  141. data/lib/mongoid/persistence/insert.rb +53 -0
  142. data/lib/mongoid/persistence/insert_embedded.rb +43 -0
  143. data/lib/mongoid/persistence/remove.rb +44 -0
  144. data/lib/mongoid/persistence/remove_all.rb +40 -0
  145. data/lib/mongoid/persistence/remove_embedded.rb +48 -0
  146. data/lib/mongoid/persistence/update.rb +77 -0
  147. data/lib/mongoid/railtie.rb +139 -0
  148. data/lib/mongoid/railties/database.rake +171 -0
  149. data/lib/mongoid/railties/document.rb +12 -0
  150. data/lib/mongoid/relations.rb +107 -0
  151. data/lib/mongoid/relations/accessors.rb +175 -0
  152. data/lib/mongoid/relations/auto_save.rb +34 -0
  153. data/lib/mongoid/relations/binding.rb +26 -0
  154. data/lib/mongoid/relations/bindings.rb +9 -0
  155. data/lib/mongoid/relations/bindings/embedded/in.rb +82 -0
  156. data/lib/mongoid/relations/bindings/embedded/many.rb +98 -0
  157. data/lib/mongoid/relations/bindings/embedded/one.rb +66 -0
  158. data/lib/mongoid/relations/bindings/referenced/in.rb +74 -0
  159. data/lib/mongoid/relations/bindings/referenced/many.rb +96 -0
  160. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +103 -0
  161. data/lib/mongoid/relations/bindings/referenced/one.rb +66 -0
  162. data/lib/mongoid/relations/builder.rb +42 -0
  163. data/lib/mongoid/relations/builders.rb +79 -0
  164. data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
  165. data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
  166. data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
  167. data/lib/mongoid/relations/builders/nested_attributes/many.rb +126 -0
  168. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  169. data/lib/mongoid/relations/builders/referenced/in.rb +29 -0
  170. data/lib/mongoid/relations/builders/referenced/many.rb +47 -0
  171. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
  172. data/lib/mongoid/relations/builders/referenced/one.rb +27 -0
  173. data/lib/mongoid/relations/cascading.rb +55 -0
  174. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  175. data/lib/mongoid/relations/cascading/destroy.rb +19 -0
  176. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  177. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  178. data/lib/mongoid/relations/constraint.rb +42 -0
  179. data/lib/mongoid/relations/cyclic.rb +103 -0
  180. data/lib/mongoid/relations/embedded/atomic.rb +86 -0
  181. data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
  182. data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
  183. data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
  184. data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
  185. data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
  186. data/lib/mongoid/relations/embedded/in.rb +173 -0
  187. data/lib/mongoid/relations/embedded/many.rb +499 -0
  188. data/lib/mongoid/relations/embedded/one.rb +170 -0
  189. data/lib/mongoid/relations/macros.rb +310 -0
  190. data/lib/mongoid/relations/many.rb +215 -0
  191. data/lib/mongoid/relations/metadata.rb +539 -0
  192. data/lib/mongoid/relations/nested_builder.rb +68 -0
  193. data/lib/mongoid/relations/one.rb +47 -0
  194. data/lib/mongoid/relations/polymorphic.rb +54 -0
  195. data/lib/mongoid/relations/proxy.rb +143 -0
  196. data/lib/mongoid/relations/referenced/batch.rb +71 -0
  197. data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
  198. data/lib/mongoid/relations/referenced/in.rb +216 -0
  199. data/lib/mongoid/relations/referenced/many.rb +516 -0
  200. data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
  201. data/lib/mongoid/relations/referenced/one.rb +222 -0
  202. data/lib/mongoid/relations/reflections.rb +45 -0
  203. data/lib/mongoid/safe.rb +23 -0
  204. data/lib/mongoid/safety.rb +207 -0
  205. data/lib/mongoid/scope.rb +31 -0
  206. data/lib/mongoid/serialization.rb +99 -0
  207. data/lib/mongoid/sharding.rb +51 -0
  208. data/lib/mongoid/state.rb +67 -0
  209. data/lib/mongoid/timestamps.rb +14 -0
  210. data/lib/mongoid/timestamps/created.rb +31 -0
  211. data/lib/mongoid/timestamps/updated.rb +33 -0
  212. data/lib/mongoid/validations.rb +124 -0
  213. data/lib/mongoid/validations/associated.rb +44 -0
  214. data/lib/mongoid/validations/referenced.rb +58 -0
  215. data/lib/mongoid/validations/uniqueness.rb +85 -0
  216. data/lib/mongoid/version.rb +4 -0
  217. data/lib/mongoid/versioning.rb +113 -0
  218. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  219. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
  220. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  221. data/lib/rails/generators/mongoid/model/templates/model.rb +19 -0
  222. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  223. data/lib/rails/generators/mongoid/observer/templates/observer.rb +4 -0
  224. data/lib/rails/generators/mongoid_generator.rb +70 -0
  225. data/lib/rails/mongoid.rb +58 -0
  226. metadata +406 -0
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+
4
+ # This module contains the behaviour of Mongoid's clone/dup of documents.
5
+ module Copyable
6
+ extend ActiveSupport::Concern
7
+
8
+ COPYABLES = [
9
+ :@accessed,
10
+ :@attributes,
11
+ :@metadata,
12
+ :@modifications,
13
+ :@previous_modifications
14
+ ]
15
+
16
+ protected
17
+
18
+ # Clone or dup the current +Document+. This will return all attributes with
19
+ # the exception of the document's id and versions, and will reset all the
20
+ # instance variables.
21
+ #
22
+ # This clone also includes embedded documents.
23
+ #
24
+ # @example Clone the document.
25
+ # document.clone
26
+ #
27
+ # @example Dup the document.
28
+ # document.dup
29
+ #
30
+ # @param [ Document ] other The document getting cloned.
31
+ #
32
+ # @return [ Document ] The new document.
33
+ def initialize_copy(other)
34
+ @attributes = other.as_document
35
+ instance_variables.each { |name| remove_instance_variable(name) }
36
+ COPYABLES.each do |name|
37
+ value = other.instance_variable_get(name)
38
+ instance_variable_set(name, value ? value.dup : nil)
39
+ end
40
+ attributes.delete("_id")
41
+ attributes.delete("versions")
42
+ @new_record = true
43
+ identify
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,357 @@
1
+ # encoding: utf-8
2
+ require "mongoid/criterion/builder"
3
+ require "mongoid/criterion/creational"
4
+ require "mongoid/criterion/complex"
5
+ require "mongoid/criterion/exclusion"
6
+ require "mongoid/criterion/inclusion"
7
+ require "mongoid/criterion/inspection"
8
+ require "mongoid/criterion/optional"
9
+ require "mongoid/criterion/selector"
10
+ require "mongoid/criterion/unconvertable"
11
+
12
+ module Mongoid #:nodoc:
13
+
14
+ # The +Criteria+ class is the core object needed in Mongoid to retrieve
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 <tt>Mongo::Collection</tt>
17
+ # in the Ruby driver. Each method on the +Criteria+ returns self to they
18
+ # can be chained in order to create a readable criterion to be executed
19
+ # against the database.
20
+ #
21
+ # Example setup:
22
+ #
23
+ # <tt>criteria = Criteria.new</tt>
24
+ #
25
+ # <tt>criteria.only(:field).where(:field => "value").skip(20).limit(20)</tt>
26
+ #
27
+ # <tt>criteria.execute</tt>
28
+ class Criteria
29
+ include Enumerable
30
+ include Criterion::Builder
31
+ include Criterion::Creational
32
+ include Criterion::Exclusion
33
+ include Criterion::Inclusion
34
+ include Criterion::Inspection
35
+ include Criterion::Optional
36
+
37
+ attr_accessor \
38
+ :collection,
39
+ :documents,
40
+ :embedded,
41
+ :ids,
42
+ :klass,
43
+ :options,
44
+ :selector,
45
+ :field_list
46
+
47
+ delegate \
48
+ :aggregate,
49
+ :avg,
50
+ :blank?,
51
+ :count,
52
+ :delete,
53
+ :delete_all,
54
+ :destroy,
55
+ :destroy_all,
56
+ :distinct,
57
+ :empty?,
58
+ :execute,
59
+ :first,
60
+ :group,
61
+ :last,
62
+ :max,
63
+ :min,
64
+ :one,
65
+ :shift,
66
+ :sum,
67
+ :update,
68
+ :update_all, :to => :context
69
+
70
+ # Concatinate the criteria with another enumerable. If the other is a
71
+ # +Criteria+ then it needs to get the collection from it.
72
+ def +(other)
73
+ entries + comparable(other)
74
+ end
75
+
76
+ # Returns the difference between the criteria and another enumerable. If
77
+ # the other is a +Criteria+ then it needs to get the collection from it.
78
+ def -(other)
79
+ entries - comparable(other)
80
+ end
81
+
82
+ # Returns true if the supplied +Enumerable+ or +Criteria+ is equal to the results
83
+ # of this +Criteria+ or the criteria itself.
84
+ #
85
+ # This will force a database load when called if an enumerable is passed.
86
+ #
87
+ # Options:
88
+ #
89
+ # other: The other +Enumerable+ or +Criteria+ to compare to.
90
+ def ==(other)
91
+ case other
92
+ when Criteria
93
+ self.selector == other.selector && self.options == other.options
94
+ when Enumerable
95
+ return (execute.entries == other)
96
+ else
97
+ return false
98
+ end
99
+ end
100
+
101
+ # Return or create the context in which this criteria should be executed.
102
+ #
103
+ # This will return an Enumerable context if the class is embedded,
104
+ # otherwise it will return a Mongo context for root classes.
105
+ def context
106
+ @context ||= Contexts.context_for(self, embedded)
107
+ end
108
+
109
+ # Iterate over each +Document+ in the results. This can take an optional
110
+ # block to pass to each argument in the results.
111
+ #
112
+ # Example:
113
+ #
114
+ # <tt>criteria.each { |doc| p doc }</tt>
115
+ def each(&block)
116
+ tap { context.iterate(&block) }
117
+ end
118
+
119
+ # Return true if the criteria has some Document or not
120
+ #
121
+ # Example:
122
+ #
123
+ # <tt>criteria.exists?</tt>
124
+ def exists?
125
+ context.count > 0
126
+ end
127
+
128
+ # When freezing a criteria we need to initialize the context first
129
+ # otherwise the setting of the context on attempted iteration will raise a
130
+ # runtime error.
131
+ #
132
+ # @example Freeze the criteria.
133
+ # criteria.freeze
134
+ #
135
+ # @return [ Criteria ] The frozen criteria.
136
+ #
137
+ # @since 2.0.0
138
+ def freeze
139
+ context and super
140
+ end
141
+
142
+ # Merges the supplied argument hash into a single criteria
143
+ #
144
+ # Options:
145
+ #
146
+ # criteria_conditions: Hash of criteria keys, and parameter values
147
+ #
148
+ # Example:
149
+ #
150
+ # <tt>criteria.fuse(:where => { :field => "value"}, :limit => 20)</tt>
151
+ #
152
+ # Returns <tt>self</tt>
153
+ def fuse(criteria_conditions = {})
154
+ criteria_conditions.inject(self) do |criteria, (key, value)|
155
+ criteria.send(key, value)
156
+ end
157
+ end
158
+
159
+ # Create the new +Criteria+ object. This will initialize the selector
160
+ # and options hashes, as well as the type of criteria.
161
+ #
162
+ # Options:
163
+ #
164
+ # type: One of :all, :first:, or :last
165
+ # klass: The class to execute on.
166
+ def initialize(klass, embedded = false)
167
+ @selector = Criterion::Selector.new(klass)
168
+ @options, @klass, @documents, @embedded = {}, klass, [], embedded
169
+ end
170
+
171
+ # Merges another object into this +Criteria+. The other object may be a
172
+ # +Criteria+ or a +Hash+. This is used to combine multiple scopes together,
173
+ # where a chained scope situation may be desired.
174
+ #
175
+ # Options:
176
+ #
177
+ # other: The +Criteria+ or +Hash+ to merge with.
178
+ #
179
+ # Example:
180
+ #
181
+ # <tt>criteria.merge({ :conditions => { :title => "Sir" } })</tt>
182
+ def merge(other)
183
+ clone.tap do |crit|
184
+ if other.is_a?(Criteria)
185
+ crit.selector.update(other.selector)
186
+ crit.options.update(other.options)
187
+ crit.documents = other.documents
188
+ else
189
+ duped = other.dup
190
+ crit.selector.update(duped.delete(:conditions) || {})
191
+ crit.options.update(duped)
192
+ end
193
+ end
194
+ end
195
+
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
+ # Returns true if criteria responds to the given method.
217
+ #
218
+ # Options:
219
+ #
220
+ # name: The name of the class method on the +Document+.
221
+ # include_private: The arguments passed to the method.
222
+ #
223
+ # Example:
224
+ #
225
+ # <tt>criteria.respond_to?(:batch_update)</tt>
226
+ def respond_to?(name, include_private = false)
227
+ # don't include klass private methods because method_missing won't call them
228
+ super || @klass.respond_to?(name) || entries.respond_to?(name, include_private)
229
+ end
230
+
231
+ # Returns the selector and options as a +Hash+ that would be passed to a
232
+ # scope for use with named scopes.
233
+ def scoped
234
+ scope_options = @options.dup
235
+ sorting = scope_options.delete(:sort)
236
+ scope_options[:order_by] = sorting if sorting
237
+ { :where => @selector }.merge(scope_options)
238
+ end
239
+ alias :to_ary :to_a
240
+
241
+ # Needed to properly get a criteria back as json
242
+ #
243
+ # @example Get the criteria as json.
244
+ # Person.where(:title => "Sir").as_json
245
+ #
246
+ # @param [ Hash ] options Options to pass through to the serializer.
247
+ #
248
+ # @return [ String ] The JSON string.
249
+ def as_json(options = nil)
250
+ entries.as_json(options)
251
+ end
252
+
253
+ # Search for documents based on a variety of args.
254
+ #
255
+ # @example Find by an id.
256
+ # criteria.search(BSON::ObjectId.new)
257
+ #
258
+ # @example Find by multiple ids.
259
+ # criteria.search([ BSON::ObjectId.new, BSON::ObjectId.new ])
260
+ #
261
+ # @example Conditionally find all matching documents.
262
+ # criteria.search(:all, :conditions => { :title => "Sir" })
263
+ #
264
+ # @example Conditionally find the first document.
265
+ # criteria.search(:first, :conditions => { :title => "Sir" })
266
+ #
267
+ # @example Conditionally find the last document.
268
+ # criteria.search(:last, :conditions => { :title => "Sir" })
269
+ #
270
+ # @param [ Symbol, BSON::ObjectId, Array<BSON::ObjectId> ] arg The
271
+ # argument to search with.
272
+ # @param [ Hash ] options The options to search with.
273
+ #
274
+ # @return [ Array<Symbol, Criteria> ] The type and criteria.
275
+ #
276
+ # @since 2.0.0
277
+ def search(*args)
278
+ raise_invalid if args[0].nil?
279
+ type = args[0]
280
+ params = args[1] || {}
281
+ return [ :ids, for_ids(type) ] unless type.is_a?(Symbol)
282
+ conditions = params.delete(:conditions) || {}
283
+ if conditions.include?(:id)
284
+ conditions[:_id] = conditions[:id]
285
+ conditions.delete(:id)
286
+ end
287
+ return [ type, where(conditions).extras(params) ]
288
+ end
289
+
290
+ # Convenience method of raising an invalid options error.
291
+ #
292
+ # @example Raise the error.
293
+ # criteria.raise_invalid
294
+ #
295
+ # @raise [ Errors::InvalidOptions ] The error.
296
+ #
297
+ # @since 2.0.0
298
+ def raise_invalid
299
+ raise Errors::InvalidOptions.new(:calling_document_find_with_nil_is_invalid, {})
300
+ end
301
+
302
+ protected
303
+
304
+ # Return the entries of the other criteria or the object. Used for
305
+ # comparing criteria or an enumerable.
306
+ def comparable(other)
307
+ other.is_a?(Criteria) ? other.entries : other
308
+ end
309
+
310
+ # Clone or dup the current +Criteria+. This will return a new criteria with
311
+ # the selector, options, klass, embedded options, etc intact.
312
+ #
313
+ # Example:
314
+ #
315
+ # <tt>criteria.clone</tt>
316
+ # <tt>criteria.dup</tt>
317
+ #
318
+ # Options:
319
+ #
320
+ # other: The criteria getting cloned.
321
+ #
322
+ # Returns:
323
+ #
324
+ # A new identical criteria
325
+ def initialize_copy(other)
326
+ @selector = other.selector.dup
327
+ @options = other.options.dup
328
+ @context = nil
329
+ end
330
+
331
+ # Update the selector setting the operator on the value for each key in the
332
+ # supplied attributes +Hash+.
333
+ #
334
+ # Example:
335
+ #
336
+ # <tt>criteria.update_selector({ :field => "value" }, "$in")</tt>
337
+ #
338
+ # @param [ Symbol ] combine The operator to use when combining sets.
339
+ def update_selector(attributes, operator, combine = :+)
340
+ clone.tap do |crit|
341
+ converted = BSON::ObjectId.convert(klass, attributes || {})
342
+ converted.each do |key, value|
343
+ unless crit.selector[key]
344
+ crit.selector[key] = { operator => value }
345
+ else
346
+ if crit.selector[key].has_key?(operator)
347
+ new_value = crit.selector[key].values.first.send(combine, value)
348
+ crit.selector[key] = { operator => new_value }
349
+ else
350
+ crit.selector[key][operator] = value
351
+ end
352
+ end
353
+ end
354
+ end
355
+ end
356
+ end
357
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Criterion #:nodoc:
4
+
5
+ # This module defines criteria behavior for building documents for
6
+ # specified conditions.
7
+ module Builder
8
+
9
+ # Build a document given the selector and return it.
10
+ # Complex criteria, such as $in and $or operations will get ignored.
11
+ #
12
+ # @example build the document.
13
+ # Person.where(:title => "Sir").build
14
+ #
15
+ # @example Build with selectors getting ignored.
16
+ # Person.where(:age.gt => 5).build
17
+ #
18
+ # @return [ Document ] A non-persisted document.
19
+ #
20
+ # @since 2.0.0
21
+ def build(attrs = {})
22
+ klass.new(
23
+ selector.inject(attrs) do |hash, (key, value)|
24
+ hash.tap do |attrs|
25
+ unless key.to_s =~ /\$/ || value.is_a?(Hash)
26
+ attrs[key] = value
27
+ end
28
+ end
29
+ end
30
+ )
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,34 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Criterion #:nodoc:
4
+ # Complex criterion are used when performing operations on symbols to get
5
+ # get a shorthand syntax for where clauses.
6
+ #
7
+ # Example:
8
+ #
9
+ # <tt>{ :field => { "$lt" => "value" } }</tt>
10
+ # becomes:
11
+ # <tt> { :field.lt => "value }</tt>
12
+ class Complex
13
+ attr_accessor :key, :operator
14
+
15
+ # Create the new complex criterion.
16
+ def initialize(opts = {})
17
+ @key, @operator = opts[:key], opts[:operator]
18
+ end
19
+
20
+ def hash
21
+ [@key, @operator].hash
22
+ end
23
+
24
+ def eql?(other)
25
+ self == (other)
26
+ end
27
+
28
+ def ==(other)
29
+ return false unless other.is_a?(self.class)
30
+ self.key == other.key && self.operator == other.operator
31
+ end
32
+ end
33
+ end
34
+ end