stonegao-mongoid 2.0.0.rc.6

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 (199) 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 +44 -0
  5. data/lib/config/locales/de.yml +44 -0
  6. data/lib/config/locales/en.yml +45 -0
  7. data/lib/config/locales/es.yml +44 -0
  8. data/lib/config/locales/fr.yml +45 -0
  9. data/lib/config/locales/hu.yml +47 -0
  10. data/lib/config/locales/it.yml +42 -0
  11. data/lib/config/locales/kr.yml +68 -0
  12. data/lib/config/locales/nl.yml +42 -0
  13. data/lib/config/locales/pl.yml +42 -0
  14. data/lib/config/locales/pt-br.yml +43 -0
  15. data/lib/config/locales/pt.yml +43 -0
  16. data/lib/config/locales/ro.yml +49 -0
  17. data/lib/config/locales/sv.yml +43 -0
  18. data/lib/config/locales/zh-CN.yml +34 -0
  19. data/lib/mongoid/atomicity.rb +111 -0
  20. data/lib/mongoid/attributes.rb +251 -0
  21. data/lib/mongoid/callbacks.rb +13 -0
  22. data/lib/mongoid/collection.rb +137 -0
  23. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  24. data/lib/mongoid/collections/master.rb +29 -0
  25. data/lib/mongoid/collections/operations.rb +42 -0
  26. data/lib/mongoid/collections/slaves.rb +45 -0
  27. data/lib/mongoid/collections.rb +70 -0
  28. data/lib/mongoid/components.rb +45 -0
  29. data/lib/mongoid/config/database.rb +167 -0
  30. data/lib/mongoid/config/replset_database.rb +48 -0
  31. data/lib/mongoid/config.rb +343 -0
  32. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  33. data/lib/mongoid/contexts/enumerable.rb +226 -0
  34. data/lib/mongoid/contexts/ids.rb +25 -0
  35. data/lib/mongoid/contexts/mongo.rb +345 -0
  36. data/lib/mongoid/contexts/paging.rb +50 -0
  37. data/lib/mongoid/contexts.rb +21 -0
  38. data/lib/mongoid/copyable.rb +44 -0
  39. data/lib/mongoid/criteria.rb +325 -0
  40. data/lib/mongoid/criterion/complex.rb +34 -0
  41. data/lib/mongoid/criterion/creational.rb +34 -0
  42. data/lib/mongoid/criterion/exclusion.rb +67 -0
  43. data/lib/mongoid/criterion/inclusion.rb +134 -0
  44. data/lib/mongoid/criterion/inspection.rb +20 -0
  45. data/lib/mongoid/criterion/optional.rb +213 -0
  46. data/lib/mongoid/criterion/selector.rb +74 -0
  47. data/lib/mongoid/cursor.rb +81 -0
  48. data/lib/mongoid/default_scope.rb +28 -0
  49. data/lib/mongoid/dirty.rb +251 -0
  50. data/lib/mongoid/document.rb +256 -0
  51. data/lib/mongoid/errors/document_not_found.rb +29 -0
  52. data/lib/mongoid/errors/invalid_collection.rb +19 -0
  53. data/lib/mongoid/errors/invalid_database.rb +20 -0
  54. data/lib/mongoid/errors/invalid_field.rb +19 -0
  55. data/lib/mongoid/errors/invalid_options.rb +16 -0
  56. data/lib/mongoid/errors/invalid_type.rb +26 -0
  57. data/lib/mongoid/errors/mongoid_error.rb +27 -0
  58. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +21 -0
  59. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  60. data/lib/mongoid/errors/unsupported_version.rb +21 -0
  61. data/lib/mongoid/errors/validations.rb +24 -0
  62. data/lib/mongoid/errors.rb +12 -0
  63. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  64. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  65. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  66. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  67. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  68. data/lib/mongoid/extensions/date/conversions.rb +25 -0
  69. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  70. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  71. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  72. data/lib/mongoid/extensions/hash/conversions.rb +19 -0
  73. data/lib/mongoid/extensions/hash/criteria_helpers.rb +22 -0
  74. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  75. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  76. data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
  77. data/lib/mongoid/extensions/object/conversions.rb +25 -0
  78. data/lib/mongoid/extensions/object/reflections.rb +17 -0
  79. data/lib/mongoid/extensions/object/yoda.rb +27 -0
  80. data/lib/mongoid/extensions/object_id/conversions.rb +57 -0
  81. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  82. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  83. data/lib/mongoid/extensions/string/conversions.rb +34 -0
  84. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  85. data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
  86. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  87. data/lib/mongoid/extensions/time_conversions.rb +38 -0
  88. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  89. data/lib/mongoid/extensions.rb +116 -0
  90. data/lib/mongoid/extras.rb +61 -0
  91. data/lib/mongoid/factory.rb +20 -0
  92. data/lib/mongoid/field.rb +95 -0
  93. data/lib/mongoid/fields.rb +138 -0
  94. data/lib/mongoid/finders.rb +173 -0
  95. data/lib/mongoid/hierarchy.rb +85 -0
  96. data/lib/mongoid/identity.rb +89 -0
  97. data/lib/mongoid/indexes.rb +38 -0
  98. data/lib/mongoid/inspection.rb +58 -0
  99. data/lib/mongoid/javascript/functions.yml +37 -0
  100. data/lib/mongoid/javascript.rb +21 -0
  101. data/lib/mongoid/json.rb +16 -0
  102. data/lib/mongoid/keys.rb +77 -0
  103. data/lib/mongoid/logger.rb +18 -0
  104. data/lib/mongoid/matchers/all.rb +11 -0
  105. data/lib/mongoid/matchers/default.rb +27 -0
  106. data/lib/mongoid/matchers/exists.rb +13 -0
  107. data/lib/mongoid/matchers/gt.rb +11 -0
  108. data/lib/mongoid/matchers/gte.rb +11 -0
  109. data/lib/mongoid/matchers/in.rb +11 -0
  110. data/lib/mongoid/matchers/lt.rb +11 -0
  111. data/lib/mongoid/matchers/lte.rb +11 -0
  112. data/lib/mongoid/matchers/ne.rb +11 -0
  113. data/lib/mongoid/matchers/nin.rb +11 -0
  114. data/lib/mongoid/matchers/size.rb +11 -0
  115. data/lib/mongoid/matchers.rb +55 -0
  116. data/lib/mongoid/modifiers/command.rb +18 -0
  117. data/lib/mongoid/modifiers/inc.rb +24 -0
  118. data/lib/mongoid/modifiers.rb +24 -0
  119. data/lib/mongoid/multi_database.rb +11 -0
  120. data/lib/mongoid/multi_parameter_attributes.rb +80 -0
  121. data/lib/mongoid/named_scope.rb +36 -0
  122. data/lib/mongoid/nested_attributes.rb +43 -0
  123. data/lib/mongoid/paranoia.rb +103 -0
  124. data/lib/mongoid/paths.rb +61 -0
  125. data/lib/mongoid/persistence/command.rb +59 -0
  126. data/lib/mongoid/persistence/insert.rb +53 -0
  127. data/lib/mongoid/persistence/insert_embedded.rb +42 -0
  128. data/lib/mongoid/persistence/remove.rb +44 -0
  129. data/lib/mongoid/persistence/remove_all.rb +40 -0
  130. data/lib/mongoid/persistence/remove_embedded.rb +48 -0
  131. data/lib/mongoid/persistence/update.rb +76 -0
  132. data/lib/mongoid/persistence.rb +237 -0
  133. data/lib/mongoid/railtie.rb +129 -0
  134. data/lib/mongoid/railties/database.rake +171 -0
  135. data/lib/mongoid/railties/document.rb +12 -0
  136. data/lib/mongoid/relations/accessors.rb +157 -0
  137. data/lib/mongoid/relations/auto_save.rb +34 -0
  138. data/lib/mongoid/relations/binding.rb +26 -0
  139. data/lib/mongoid/relations/bindings/embedded/in.rb +82 -0
  140. data/lib/mongoid/relations/bindings/embedded/many.rb +98 -0
  141. data/lib/mongoid/relations/bindings/embedded/one.rb +66 -0
  142. data/lib/mongoid/relations/bindings/referenced/in.rb +74 -0
  143. data/lib/mongoid/relations/bindings/referenced/many.rb +96 -0
  144. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +99 -0
  145. data/lib/mongoid/relations/bindings/referenced/one.rb +66 -0
  146. data/lib/mongoid/relations/bindings.rb +9 -0
  147. data/lib/mongoid/relations/builder.rb +42 -0
  148. data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
  149. data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
  150. data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
  151. data/lib/mongoid/relations/builders/nested_attributes/many.rb +116 -0
  152. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  153. data/lib/mongoid/relations/builders/referenced/in.rb +32 -0
  154. data/lib/mongoid/relations/builders/referenced/many.rb +26 -0
  155. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
  156. data/lib/mongoid/relations/builders/referenced/one.rb +30 -0
  157. data/lib/mongoid/relations/builders.rb +79 -0
  158. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  159. data/lib/mongoid/relations/cascading/destroy.rb +19 -0
  160. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  161. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  162. data/lib/mongoid/relations/cascading.rb +55 -0
  163. data/lib/mongoid/relations/constraint.rb +45 -0
  164. data/lib/mongoid/relations/cyclic.rb +97 -0
  165. data/lib/mongoid/relations/embedded/in.rb +173 -0
  166. data/lib/mongoid/relations/embedded/many.rb +483 -0
  167. data/lib/mongoid/relations/embedded/one.rb +170 -0
  168. data/lib/mongoid/relations/macros.rb +306 -0
  169. data/lib/mongoid/relations/many.rb +171 -0
  170. data/lib/mongoid/relations/metadata.rb +533 -0
  171. data/lib/mongoid/relations/nested_builder.rb +68 -0
  172. data/lib/mongoid/relations/one.rb +47 -0
  173. data/lib/mongoid/relations/polymorphic.rb +54 -0
  174. data/lib/mongoid/relations/proxy.rb +128 -0
  175. data/lib/mongoid/relations/referenced/in.rb +216 -0
  176. data/lib/mongoid/relations/referenced/many.rb +443 -0
  177. data/lib/mongoid/relations/referenced/many_to_many.rb +344 -0
  178. data/lib/mongoid/relations/referenced/one.rb +206 -0
  179. data/lib/mongoid/relations/reflections.rb +45 -0
  180. data/lib/mongoid/relations.rb +105 -0
  181. data/lib/mongoid/safe.rb +23 -0
  182. data/lib/mongoid/safety.rb +207 -0
  183. data/lib/mongoid/scope.rb +31 -0
  184. data/lib/mongoid/serialization.rb +99 -0
  185. data/lib/mongoid/state.rb +66 -0
  186. data/lib/mongoid/timestamps.rb +38 -0
  187. data/lib/mongoid/validations/associated.rb +42 -0
  188. data/lib/mongoid/validations/uniqueness.rb +85 -0
  189. data/lib/mongoid/validations.rb +117 -0
  190. data/lib/mongoid/version.rb +4 -0
  191. data/lib/mongoid/versioning.rb +51 -0
  192. data/lib/mongoid.rb +139 -0
  193. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  194. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +23 -0
  195. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  196. data/lib/rails/generators/mongoid/model/templates/model.rb +17 -0
  197. data/lib/rails/generators/mongoid_generator.rb +61 -0
  198. data/lib/rails/mongoid.rb +57 -0
  199. metadata +380 -0
@@ -0,0 +1,345 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Contexts #:nodoc:
4
+ class Mongo
5
+ include Ids, Paging
6
+ attr_accessor :criteria
7
+
8
+ delegate :klass, :options, :selector, :to => :criteria
9
+
10
+ # Aggregate the context. This will take the internally built selector and options
11
+ # and pass them on to the Ruby driver's +group()+ method on the collection. The
12
+ # collection itself will be retrieved from the class provided, and once the
13
+ # query has returned it will provided a grouping of keys with counts.
14
+ #
15
+ # Example:
16
+ #
17
+ # <tt>context.aggregate</tt>
18
+ #
19
+ # Returns:
20
+ #
21
+ # A +Hash+ with field values as keys, counts as values
22
+ def aggregate
23
+ klass.collection.group(options[:fields], selector, { :count => 0 }, Javascript.aggregate, true)
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?
53
+ end
54
+ alias :empty? :blank?
55
+
56
+ # Get the count of matching documents in the database for the context.
57
+ #
58
+ # @example Get the count without skip and limit taken into consideration.
59
+ # context.count
60
+ #
61
+ # @example Get the count with skip and limit applied.
62
+ # context.count(true)
63
+ #
64
+ # @param [Boolean] extras True to inclued previous skip/limit
65
+ # statements in the count; false to ignore them. Defaults to `false`.
66
+ #
67
+ # @return [ Integer ] The count of documents.
68
+ def count(extras = false)
69
+ @count ||= klass.collection.find(selector, process_options).count(extras)
70
+ end
71
+
72
+ # Delete all the documents in the database matching the selector.
73
+ #
74
+ # @example Delete the documents.
75
+ # context.delete_all
76
+ #
77
+ # @return [ Integer ] The number of documents deleted.
78
+ #
79
+ # @since 2.0.0.rc.1
80
+ def delete_all
81
+ klass.delete_all(:conditions => selector)
82
+ end
83
+ alias :delete :delete_all
84
+
85
+ # Destroy all the documents in the database matching the selector.
86
+ #
87
+ # @example Destroy the documents.
88
+ # context.destroy_all
89
+ #
90
+ # @return [ Integer ] The number of documents destroyed.
91
+ #
92
+ # @since 2.0.0.rc.1
93
+ def destroy_all
94
+ klass.destroy_all(:conditions => selector)
95
+ end
96
+ alias :destroy :destroy_all
97
+
98
+ # Gets an array of distinct values for the supplied field across the
99
+ # entire collection or the susbset given the criteria.
100
+ #
101
+ # Example:
102
+ #
103
+ # <tt>context.distinct(:title)</tt>
104
+ def distinct(field)
105
+ klass.collection.distinct(field, selector)
106
+ end
107
+
108
+ # Execute the context. This will take the selector and options
109
+ # and pass them on to the Ruby driver's +find()+ method on the collection. The
110
+ # collection itself will be retrieved from the class provided, and once the
111
+ # query has returned new documents of the type of class provided will be instantiated.
112
+ #
113
+ # Example:
114
+ #
115
+ # <tt>context.execute</tt>
116
+ #
117
+ # Returns:
118
+ #
119
+ # An enumerable +Cursor+.
120
+ def execute(paginating = false)
121
+ cursor = klass.collection.find(selector, process_options)
122
+ if cursor
123
+ @count = cursor.count if paginating
124
+ cursor
125
+ else
126
+ []
127
+ end
128
+ end
129
+
130
+ # Groups the context. This will take the internally built selector and options
131
+ # and pass them on to the Ruby driver's +group()+ method on the collection. The
132
+ # collection itself will be retrieved from the class provided, and once the
133
+ # query has returned it will provided a grouping of keys with objects.
134
+ #
135
+ # Example:
136
+ #
137
+ # <tt>context.group</tt>
138
+ #
139
+ # Returns:
140
+ #
141
+ # A +Hash+ with field values as keys, arrays of documents as values.
142
+ def group
143
+ klass.collection.group(
144
+ options[:fields],
145
+ selector,
146
+ { :group => [] },
147
+ Javascript.group
148
+ ).collect do |docs|
149
+ docs["group"] = docs["group"].collect do |attrs|
150
+ Mongoid::Factory.build(klass, attrs)
151
+ end
152
+ docs
153
+ end
154
+ end
155
+
156
+ # Create the new mongo context. This will execute the queries given the
157
+ # selector and options against the database.
158
+ #
159
+ # Example:
160
+ #
161
+ # <tt>Mongoid::Contexts::Mongo.new(criteria)</tt>
162
+ def initialize(criteria)
163
+ @criteria = criteria
164
+ if klass.hereditary? && !criteria.selector.keys.include?(:_type)
165
+ @criteria = criteria.in(:_type => criteria.klass._types)
166
+ end
167
+ @criteria.enslave if klass.enslaved?
168
+ @criteria.cache if klass.cached?
169
+ end
170
+
171
+ # Iterate over each +Document+ in the results. This can take an optional
172
+ # block to pass to each argument in the results.
173
+ #
174
+ # Example:
175
+ #
176
+ # <tt>context.iterate { |doc| p doc }</tt>
177
+ def iterate(&block)
178
+ return caching(&block) if criteria.cached?
179
+ if block_given?
180
+ execute.each { |doc| yield doc }
181
+ end
182
+ end
183
+
184
+ # Return the last result for the +Context+. Essentially does a find_one on
185
+ # the collection with the sorting reversed. If no sorting parameters have
186
+ # been provided it will default to ids.
187
+ #
188
+ # Example:
189
+ #
190
+ # <tt>context.last</tt>
191
+ #
192
+ # Returns:
193
+ #
194
+ # The last document in the collection.
195
+ def last
196
+ opts = process_options
197
+ sorting = opts[:sort]
198
+ sorting = [[:_id, :asc]] unless sorting
199
+ opts[:sort] = sorting.collect { |option| [ option[0], option[1].invert ] }
200
+ attributes = klass.collection.find_one(selector, opts)
201
+ attributes ? Mongoid::Factory.build(klass, attributes) : nil
202
+ end
203
+
204
+ # Return the max value for a field.
205
+ #
206
+ # This will take the internally built selector and options
207
+ # and pass them on to the Ruby driver's +group()+ method on the collection. The
208
+ # collection itself will be retrieved from the class provided, and once the
209
+ # query has returned it will provided a grouping of keys with sums.
210
+ #
211
+ # Example:
212
+ #
213
+ # <tt>context.max(:age)</tt>
214
+ #
215
+ # Returns:
216
+ #
217
+ # A numeric max value.
218
+ def max(field)
219
+ grouped(:max, field.to_s, Javascript.max)
220
+ end
221
+
222
+ # Return the min value for a field.
223
+ #
224
+ # This will take the internally built selector and options
225
+ # and pass them on to the Ruby driver's +group()+ method on the collection. The
226
+ # collection itself will be retrieved from the class provided, and once the
227
+ # query has returned it will provided a grouping of keys with sums.
228
+ #
229
+ # Example:
230
+ #
231
+ # <tt>context.min(:age)</tt>
232
+ #
233
+ # Returns:
234
+ #
235
+ # A numeric minimum value.
236
+ def min(field)
237
+ grouped(:min, field.to_s, Javascript.min)
238
+ end
239
+
240
+ # Return the first result for the +Context+.
241
+ #
242
+ # Example:
243
+ #
244
+ # <tt>context.one</tt>
245
+ #
246
+ # Return:
247
+ #
248
+ # The first document in the collection.
249
+ def one
250
+ attributes = klass.collection.find_one(selector, process_options)
251
+ attributes ? Mongoid::Factory.build(klass, attributes) : nil
252
+ end
253
+
254
+ alias :first :one
255
+
256
+ # Return the first result for the +Context+ and skip it
257
+ # for successive calls.
258
+ #
259
+ # Returns:
260
+ #
261
+ # The first document in the collection.
262
+ def shift
263
+ document = first
264
+ criteria.skip((options[:skip] || 0) + 1)
265
+ document
266
+ end
267
+
268
+ # Sum the context.
269
+ #
270
+ # This will take the internally built selector and options
271
+ # and pass them on to the Ruby driver's +group()+ method on the collection. The
272
+ # collection itself will be retrieved from the class provided, and once the
273
+ # query has returned it will provided a grouping of keys with sums.
274
+ #
275
+ # Example:
276
+ #
277
+ # <tt>context.sum(:age)</tt>
278
+ #
279
+ # Returns:
280
+ #
281
+ # A numeric value that is the sum.
282
+ def sum(field)
283
+ grouped(:sum, field.to_s, Javascript.sum)
284
+ end
285
+
286
+ # Common functionality for grouping operations. Currently used by min, max
287
+ # and sum. Will gsub the field name in the supplied reduce function.
288
+ def grouped(start, field, reduce)
289
+ collection = klass.collection.group(
290
+ nil,
291
+ selector,
292
+ { start => "start" },
293
+ reduce.gsub("[field]", field)
294
+ )
295
+ collection.empty? ? nil : collection.first[start.to_s]
296
+ end
297
+
298
+ # Filters the field list. If no fields have been supplied, then it will be
299
+ # empty. If fields have been defined then _type will be included as well.
300
+ def process_options
301
+ fields = options[:fields]
302
+ if fields && fields.size > 0 && !fields.include?(:_type)
303
+ fields << :_type
304
+ options[:fields] = fields
305
+ end
306
+ options.dup
307
+ end
308
+
309
+ # Very basic update that will perform a simple atomic $set of the
310
+ # attributes provided in the hash. Can be expanded to later for more
311
+ # robust functionality.
312
+ #
313
+ # @example Update all matching documents.
314
+ # context.update_all(:title => "Sir")
315
+ #
316
+ # @param [ Hash ] attributes The sets to perform.
317
+ #
318
+ # @since 2.0.0.rc.4
319
+ def update_all(attributes = {})
320
+ klass.collection.update(
321
+ selector,
322
+ { "$set" => attributes },
323
+ :multi => true,
324
+ :safe => Mongoid.persist_in_safe_mode
325
+ )
326
+ end
327
+ alias :update :update_all
328
+
329
+ protected
330
+
331
+ # Iterate over each +Document+ in the results and cache the collection.
332
+ def caching(&block)
333
+ if defined? @collection
334
+ @collection.each(&block)
335
+ else
336
+ @collection = []
337
+ execute.each do |doc|
338
+ @collection << doc
339
+ yield doc if block_given?
340
+ end
341
+ end
342
+ end
343
+ end
344
+ end
345
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Contexts #:nodoc:
4
+ module Paging
5
+ # Paginates the documents.
6
+ #
7
+ # Example:
8
+ #
9
+ # <tt>context.paginate(:page => 6, :per_page => 25)</tt>
10
+ #
11
+ # Returns:
12
+ #
13
+ # A collection of documents paginated.
14
+ # All previous <tt>limit</tt> and <tt>skip</tt> call will be ignored.
15
+ def paginate(pager_options={})
16
+ if pager_options[:per_page]
17
+ options[:limit] = pager_options[:per_page].to_i
18
+ if pager_options[:page]
19
+ options[:skip] = (pager_options[:page].to_i - 1) * pager_options[:per_page].to_i
20
+ end
21
+ end
22
+
23
+ @collection ||= execute(true)
24
+ WillPaginate::Collection.create(page, per_page, count) do |pager|
25
+ pager.replace(@collection.to_a)
26
+ end
27
+ end
28
+
29
+ # Either returns the page option and removes it from the options, or
30
+ # returns a default value of 1.
31
+ #
32
+ # Returns:
33
+ #
34
+ # An +Integer+ page number.
35
+ def page
36
+ skips, limits = options[:skip], options[:limit]
37
+ (skips && limits) ? (skips + limits) / limits : 1
38
+ end
39
+
40
+ # Get the number of results per page or the default of 20.
41
+ #
42
+ # Returns:
43
+ #
44
+ # The +Integer+ number of documents in each page.
45
+ def per_page
46
+ (options[:limit] || 20).to_i
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,21 @@
1
+ # encoding: utf-8
2
+ require "mongoid/contexts/ids"
3
+ require "mongoid/contexts/paging"
4
+ require "mongoid/contexts/enumerable"
5
+ 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, embedded = false)
18
+ embedded ? Enumerable.new(criteria) : Mongo.new(criteria)
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Copyable
4
+ extend ActiveSupport::Concern
5
+
6
+ COPYABLES = [
7
+ :@accessed,
8
+ :@attributes,
9
+ :@metadata,
10
+ :@modifications,
11
+ :@previous_modifications
12
+ ]
13
+
14
+ protected
15
+
16
+ # Clone or dup the current +Document+. This will return all attributes with
17
+ # the exception of the document's id and versions, and will reset all the
18
+ # instance variables.
19
+ #
20
+ # Example:
21
+ #
22
+ # <tt>document.clone</tt>
23
+ # <tt>document.dup</tt>
24
+ #
25
+ # Options:
26
+ #
27
+ # other: The document getting cloned.
28
+ #
29
+ # Returns:
30
+ #
31
+ # A new document with all the attributes except id and versions
32
+ def initialize_copy(other)
33
+ instance_variables.each { |name| remove_instance_variable(name) }
34
+ COPYABLES.each do |name|
35
+ value = other.instance_variable_get(name)
36
+ instance_variable_set(name, value ? value.dup : nil)
37
+ end
38
+ @attributes.delete("_id")
39
+ @attributes.delete("versions")
40
+ @new_record = true
41
+ identify
42
+ end
43
+ end
44
+ end