stonegao-mongoid 2.0.0.rc.6

Sign up to get free protection for your applications and to get access to all the features.
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,343 @@
1
+ # encoding: utf-8
2
+ require "uri"
3
+ require "mongoid/config/database"
4
+ require "mongoid/config/replset_database"
5
+
6
+ module Mongoid #:nodoc
7
+
8
+ # This module defines all the configuration options for Mongoid, including the
9
+ # database connections.
10
+ #
11
+ # @todo Durran: This module needs an overhaul, remove singleton, etc.
12
+ module Config
13
+ extend self
14
+
15
+ attr_accessor :master, :slaves, :settings
16
+ @settings = {}
17
+
18
+ # Define a configuration option with a default.
19
+ #
20
+ # @example Define the option.
21
+ # Config.option(:persist_in_safe_mode, :default => false)
22
+ #
23
+ # @param [ Symbol ] name The name of the configuration option.
24
+ # @param [ Hash ] options Extras for the option.
25
+ #
26
+ # @option options [ Object ] :default The default value.
27
+ #
28
+ # @since 2.0.0.rc.1
29
+ def option(name, options = {})
30
+ define_method(name) do
31
+ settings.has_key?(name) ? settings[name] : options[:default]
32
+ end
33
+ define_method("#{name}=") { |value| settings[name] = value }
34
+ define_method("#{name}?") { send(name) }
35
+ end
36
+
37
+ option :allow_dynamic_fields, :default => true
38
+ option :include_root_in_json, :default => false
39
+ option :parameterize_keys, :default => true
40
+ option :persist_in_safe_mode, :default => false
41
+ option :raise_not_found_error, :default => true
42
+ option :reconnect_time, :default => 3
43
+ option :autocreate_indexes, :default => false
44
+ option :skip_version_check, :default => false
45
+ option :time_zone, :default => nil
46
+ option :binding_defaults, :default => { :binding => false, :continue => true }
47
+
48
+ # Adds a new I18n locale file to the load path.
49
+ #
50
+ # @example Add a portuguese locale.
51
+ # Mongoid::Config.add_language('pt')
52
+ #
53
+ # @example Add all available languages.
54
+ # Mongoid::Config.add_language('*')
55
+ #
56
+ # @param [ String ] language_code The language to add.
57
+ def add_language(language_code = nil)
58
+ Dir[
59
+ File.join(
60
+ File.dirname(__FILE__), "..", "config", "locales", "#{language_code}.yml"
61
+ )
62
+ ].each do |file|
63
+ I18n.load_path << File.expand_path(file)
64
+ end
65
+ end
66
+
67
+ # Get any extra databases that have been configured.
68
+ #
69
+ # @example Get the extras.
70
+ # config.databases
71
+ #
72
+ # @return [ Hash ] A hash of secondary databases.
73
+ def databases
74
+ configure_extras(@settings["databases"]) unless @databases || !@settings
75
+ @databases || {}
76
+ end
77
+
78
+ # @todo Durran: There were no tests around the databases setter, not sure
79
+ # what the exact expectation was. Set with a hash?
80
+ def databases=(databases)
81
+ end
82
+
83
+ # Return field names that could cause destructive things to happen if
84
+ # defined in a Mongoid::Document.
85
+ #
86
+ # @example Get the destructive fields.
87
+ # config.destructive_fields
88
+ #
89
+ # @return [ Array<String> ] An array of bad field names.
90
+ def destructive_fields
91
+ @destructive_fields ||= lambda {
92
+ klass = Class.new do
93
+ include Mongoid::Document
94
+ end
95
+ klass.instance_methods(true).collect { |method| method.to_s }
96
+ }.call
97
+ end
98
+
99
+ # Configure mongoid from a hash. This is usually called after parsing a
100
+ # yaml config file such as mongoid.yml.
101
+ #
102
+ # @example Configure Mongoid.
103
+ # config.from_hash({})
104
+ #
105
+ # @param [ Hash ] options The settings to use.
106
+ def from_hash(options = {})
107
+ options.except("database", "slaves", "databases").each_pair do |name, value|
108
+ send("#{name}=", value) if respond_to?("#{name}=")
109
+ end
110
+ configure_databases(options)
111
+ configure_extras(options["databases"])
112
+ end
113
+
114
+ # Returns the logger, or defaults to Rails logger or stdout logger.
115
+ #
116
+ # @example Get the logger.
117
+ # config.logger
118
+ #
119
+ # @return [ Logger ] The desired logger.
120
+ def logger
121
+ @logger ||= defined?(Rails) ? Rails.logger : ::Logger.new($stdout)
122
+ end
123
+
124
+ # Sets the logger for Mongoid to use.
125
+ #
126
+ # @example Set the logger.
127
+ # config.logger = Logger.new($stdout, :warn)
128
+ #
129
+ # @return [ Logger ] The newly set logger.
130
+ def logger=(logger)
131
+ @logger = logger
132
+ @master.connection.instance_variable_set(:@logger, logger)
133
+ end
134
+
135
+ # Sets whether the times returned from the database use the ruby or
136
+ # the ActiveSupport time zone.
137
+ # If you omit this setting, then times will use the ruby time zone.
138
+ #
139
+ # Example:
140
+ #
141
+ # <tt>Config.use_activesupport_time_zone = true</tt>
142
+ #
143
+ # Returns:
144
+ #
145
+ # A boolean
146
+ def use_activesupport_time_zone=(value)
147
+ @use_activesupport_time_zone = value || false
148
+ end
149
+
150
+ # Sets whether the times returned from the database use the ruby or
151
+ # the ActiveSupport time zone.
152
+ # If the setting is false, then times will use the ruby time zone.
153
+ #
154
+ # Example:
155
+ #
156
+ # <tt>Config.use_activesupport_time_zone</tt>
157
+ #
158
+ # Returns:
159
+ #
160
+ # A boolean
161
+ attr_reader :use_activesupport_time_zone
162
+ alias_method :use_activesupport_time_zone?, :use_activesupport_time_zone
163
+
164
+ # Sets the Mongo::DB master database to be used. If the object trying to be
165
+ # set is not a valid +Mongo::DB+, then an error will be raised.
166
+ #
167
+ # @example Set the master database.
168
+ # config.master = Mongo::Connection.db("test")
169
+ #
170
+ # @param [ Mongo::DB ] db The master database.
171
+ #
172
+ # @raise [ Errors::InvalidDatabase ] If the master isnt a valid object.
173
+ #
174
+ # @return [ Mongo::DB ] The master instance.
175
+ def master=(db)
176
+ check_database!(db)
177
+ @master = db
178
+ end
179
+ alias :database= :master=
180
+
181
+ # Returns the master database, or if none has been set it will raise an
182
+ # error.
183
+ #
184
+ # @example Get the master database.
185
+ # config.master
186
+ #
187
+ # @raise [ Errors::InvalidDatabase ] If the database was not set.
188
+ #
189
+ # @return [ Mongo::DB ] The master database.
190
+ def master
191
+ unless @master
192
+ configure_databases(@settings) unless @settings.blank?
193
+ raise Errors::InvalidDatabase.new(nil) unless @master
194
+ end
195
+ if @reconnect
196
+ @reconnect = false
197
+ reconnect!
198
+ end
199
+ @master
200
+ end
201
+ alias :database :master
202
+
203
+ # Convenience method for connecting to the master database after forking a
204
+ # new process.
205
+ #
206
+ # @example Reconnect to the master.
207
+ # Mongoid.reconnect!
208
+ #
209
+ # @param [ true, false ] now Perform the reconnection immediately?
210
+ def reconnect!(now = true)
211
+ if now
212
+ master.connection.connect
213
+ else
214
+ # We set a @reconnect flag so that #master knows to reconnect the next
215
+ # time the connection is accessed.
216
+ @reconnect = true
217
+ end
218
+ end
219
+
220
+ # Reset the configuration options to the defaults.
221
+ #
222
+ # @example Reset the configuration options.
223
+ # config.reset
224
+ def reset
225
+ settings.clear
226
+ end
227
+
228
+ # Sets the Mongo::DB slave databases to be used. If the objects provided
229
+ # are not valid +Mongo::DBs+ an error will be raised.
230
+ #
231
+ # @example Set the slaves.
232
+ # config.slaves = [ Mongo::Connection.db("test") ]
233
+ #
234
+ # @param [ Array<Mongo::DB> ] dbs The slave databases.
235
+ #
236
+ # @raise [ Errors::InvalidDatabase ] If the slaves arent valid objects.
237
+ #
238
+ # @return [ Array<Mongo::DB> ] The slave DB instances.
239
+ def slaves=(dbs)
240
+ return unless dbs
241
+ dbs.each do |db|
242
+ check_database!(db)
243
+ end
244
+ @slaves = dbs
245
+ end
246
+
247
+ # Returns the slave databases or nil if none have been set.
248
+ #
249
+ # @example Get the slaves.
250
+ # config.slaves
251
+ #
252
+ # @return [ Array<Mongo::DB>, nil ] The slave databases.
253
+ def slaves
254
+ unless @slaves
255
+ configure_databases(@settings) if @settings && @settings[:database]
256
+ end
257
+ @slaves
258
+ end
259
+
260
+ # Sets whether the times returned from the database are in UTC or local time.
261
+ # If you omit this setting, then times will be returned in
262
+ # the local time zone.
263
+ #
264
+ # @example Set the use of UTC.
265
+ # config.use_utc = true
266
+ #
267
+ # @param [ true, false ] value Whether to use UTC or not.
268
+ #
269
+ # @return [ true, false ] Are we using UTC?
270
+ def use_utc=(value)
271
+ @use_utc = value || false
272
+ end
273
+
274
+ # Returns whether times are return from the database in UTC. If
275
+ # this setting is false, then times will be returned in the local time zone.
276
+ #
277
+ # @example Are we using UTC?
278
+ # config.use_utc
279
+ #
280
+ # @return [ true, false ] True if UTC, false if not.
281
+ attr_reader :use_utc
282
+ alias :use_utc? :use_utc
283
+
284
+ protected
285
+
286
+ # Check if the database is valid and the correct version.
287
+ #
288
+ # @example Check if the database is valid.
289
+ # config.check_database!
290
+ #
291
+ # @param [ Mongo::DB ] database The db to check.
292
+ #
293
+ # @raise [ Errors::InvalidDatabase ] If the object is not valid.
294
+ # @raise [ Errors::UnsupportedVersion ] If the db version is too old.
295
+ def check_database!(database)
296
+ raise Errors::InvalidDatabase.new(database) unless database.kind_of?(Mongo::DB)
297
+ unless skip_version_check
298
+ version = database.connection.server_version
299
+ raise Errors::UnsupportedVersion.new(version) if version < Mongoid::MONGODB_VERSION
300
+ end
301
+ end
302
+
303
+ # Get a database from settings.
304
+ #
305
+ # @example Configure the master and slave dbs.
306
+ # config.configure_databases("database" => "mongoid")
307
+ #
308
+ # @param [ Hash ] options The options to use.
309
+ #
310
+ # @option options [ String ] :database The database name.
311
+ # @option options [ String ] :host The database host.
312
+ # @option options [ String ] :password The password for authentication.
313
+ # @option options [ Integer ] :port The port for the database.
314
+ # @option options [ Array<Hash> ] :slaves The slave db options.
315
+ # @option options [ String ] :uri The uri for the database.
316
+ # @option options [ String ] :username The user for authentication.
317
+ #
318
+ # @since 2.0.0.rc.1
319
+ def configure_databases(options)
320
+ if options.has_key?('hosts')
321
+ @master, @slaves = ReplsetDatabase.new(options).configure
322
+ else
323
+ @master, @slaves = Database.new(options).configure
324
+ end
325
+ end
326
+
327
+ # Get the secondary databases from settings.
328
+ #
329
+ # @example Configure the master and slave dbs.
330
+ # config.configure_extras("databases" => settings)
331
+ #
332
+ # @param [ Hash ] options The options to use.
333
+ #
334
+ # @since 2.0.0.rc.1
335
+ def configure_extras(extras)
336
+ @databases = (extras || []).inject({}) do |dbs, (name, options)|
337
+ dbs.tap do |extra|
338
+ dbs[name], dbs["#{name}_slaves"] = Database.new(options).configure
339
+ end
340
+ end
341
+ end
342
+ end
343
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Contexts #:nodoc:
4
+ class Enumerable
5
+ class Sort
6
+ attr_reader :value, :direction
7
+
8
+ # Create a new sorting object. This requires a value and a sort
9
+ # direction of +:asc+ or +:desc+.
10
+ def initialize(value, direction)
11
+ @value = value
12
+ @direction = direction
13
+ end
14
+
15
+ # Return +true+ if the direction is +:asc+, otherwise false.
16
+ def ascending?
17
+ direction == :asc
18
+ end
19
+
20
+ # Compare two +Sort+ objects against each other, taking into
21
+ # consideration the direction of the sorting.
22
+ def <=>(other)
23
+ cmp = compare(value, other.value)
24
+ ascending? ? cmp : cmp * -1
25
+ end
26
+
27
+ private
28
+
29
+ # Compare two values allowing for nil values.
30
+ def compare(a, b)
31
+ case
32
+ when a.nil?
33
+ b.nil? ? 0 : 1
34
+ when b.nil?
35
+ -1
36
+ else
37
+ a <=> b
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,226 @@
1
+ # encoding: utf-8
2
+
3
+ require 'mongoid/contexts/enumerable/sort'
4
+
5
+ module Mongoid #:nodoc:
6
+ module Contexts #:nodoc:
7
+ class Enumerable
8
+ include Ids, Paging
9
+ attr_accessor :criteria
10
+
11
+ delegate :blank?, :empty?, :first, :last, :to => :execute
12
+ delegate :klass, :documents, :options, :selector, :to => :criteria
13
+
14
+ # Return aggregation counts of the grouped documents. This will count by
15
+ # the first field provided in the fields array.
16
+ #
17
+ # Returns:
18
+ #
19
+ # A +Hash+ with field values as keys, count as values
20
+ def aggregate
21
+ counts = {}
22
+ group.each_pair { |key, value| counts[key] = value.size }
23
+ counts
24
+ end
25
+
26
+ # Get the average value for the supplied field.
27
+ #
28
+ # Example:
29
+ #
30
+ # <tt>context.avg(:age)</tt>
31
+ #
32
+ # Returns:
33
+ #
34
+ # A numeric value that is the average.
35
+ def avg(field)
36
+ total = sum(field)
37
+ total ? (total.to_f / count) : nil
38
+ end
39
+
40
+ # Gets the number of documents in the array. Delegates to size.
41
+ def count
42
+ @count ||= filter.size
43
+ end
44
+
45
+ # Delete all the documents in the database matching the selector.
46
+ #
47
+ # @example Delete the documents.
48
+ # context.delete_all
49
+ #
50
+ # @return [ Integer ] The number of documents deleted.
51
+ #
52
+ # @since 2.0.0.rc.1
53
+ def delete_all
54
+ count.tap { filter.each(&:delete) }
55
+ end
56
+ alias :delete :delete_all
57
+
58
+ # Destroy all the documents in the database matching the selector.
59
+ #
60
+ # @example Destroy the documents.
61
+ # context.destroy_all
62
+ #
63
+ # @return [ Integer ] The number of documents destroyed.
64
+ #
65
+ # @since 2.0.0.rc.1
66
+ def destroy_all
67
+ count.tap { filter.each(&:destroy) }
68
+ end
69
+ alias :destroy :destroy_all
70
+
71
+ # Gets an array of distinct values for the supplied field across the
72
+ # entire array or the susbset given the criteria.
73
+ #
74
+ # Example:
75
+ #
76
+ # <tt>context.distinct(:title)</tt>
77
+ def distinct(field)
78
+ execute.collect { |doc| doc.send(field) }.uniq
79
+ end
80
+
81
+ # Enumerable implementation of execute. Returns matching documents for
82
+ # the selector, and adds options if supplied.
83
+ #
84
+ # Returns:
85
+ #
86
+ # An +Array+ of documents that matched the selector.
87
+ def execute(paginating = false)
88
+ limit(sort(filter)) || []
89
+ end
90
+
91
+ # Groups the documents by the first field supplied in the field options.
92
+ #
93
+ # Returns:
94
+ #
95
+ # A +Hash+ with field values as keys, arrays of documents as values.
96
+ def group
97
+ field = options[:fields].first
98
+ execute.group_by { |doc| doc.send(field) }
99
+ end
100
+
101
+ # Create the new enumerable context. This will need the selector and
102
+ # options from a +Criteria+ and a documents array that is the underlying
103
+ # array of embedded documents from a has many association.
104
+ #
105
+ # Example:
106
+ #
107
+ # <tt>Mongoid::Contexts::Enumerable.new(criteria)</tt>
108
+ def initialize(criteria)
109
+ @criteria = criteria
110
+ end
111
+
112
+ # Iterate over each +Document+ in the results. This can take an optional
113
+ # block to pass to each argument in the results.
114
+ #
115
+ # Example:
116
+ #
117
+ # <tt>context.iterate { |doc| p doc }</tt>
118
+ def iterate(&block)
119
+ execute.each(&block)
120
+ end
121
+
122
+ # Get the largest value for the field in all the documents.
123
+ #
124
+ # Returns:
125
+ #
126
+ # The numerical largest value.
127
+ def max(field)
128
+ determine(field, :>=)
129
+ end
130
+
131
+ # Get the smallest value for the field in all the documents.
132
+ #
133
+ # Returns:
134
+ #
135
+ # The numerical smallest value.
136
+ def min(field)
137
+ determine(field, :<=)
138
+ end
139
+
140
+ # Get one document.
141
+ #
142
+ # Returns:
143
+ #
144
+ # The first document in the +Array+
145
+ alias :one :first
146
+
147
+ # Get one document and tell the criteria to skip this record on
148
+ # successive calls.
149
+ #
150
+ # Returns:
151
+ #
152
+ # The first document in the +Array+
153
+ def shift
154
+ first.tap do |document|
155
+ self.criteria = criteria.skip((options[:skip] || 0) + 1)
156
+ end
157
+ end
158
+
159
+ # Get the sum of the field values for all the documents.
160
+ #
161
+ # Returns:
162
+ #
163
+ # The numerical sum of all the document field values.
164
+ def sum(field)
165
+ sum = execute.inject(nil) do |memo, doc|
166
+ value = doc.send(field)
167
+ memo ? memo += value : value
168
+ end
169
+ end
170
+
171
+ # Very basic update that will perform a simple atomic $set of the
172
+ # attributes provided in the hash. Can be expanded to later for more
173
+ # robust functionality.
174
+ #
175
+ # @example Update all matching documents.
176
+ # context.update_all(:title => "Sir")
177
+ #
178
+ # @param [ Hash ] attributes The sets to perform.
179
+ #
180
+ # @since 2.0.0.rc.6
181
+ def update_all(attributes = nil)
182
+ iterate do |doc|
183
+ doc.update_attributes(attributes || {})
184
+ end
185
+ end
186
+ alias :update :update_all
187
+
188
+ protected
189
+ # Filters the documents against the criteria's selector
190
+ def filter
191
+ documents.select { |document| document.matches?(selector) }
192
+ end
193
+
194
+ # If the field exists, perform the comparison and set if true.
195
+ def determine(field, operator)
196
+ matching = documents.inject(nil) do |memo, doc|
197
+ value = doc.send(field)
198
+ (memo && memo.send(operator, value)) ? memo : value
199
+ end
200
+ end
201
+
202
+ # Limits the result set if skip and limit options.
203
+ def limit(documents)
204
+ skip, limit = options[:skip], options[:limit]
205
+ if skip && limit
206
+ return documents.slice(skip, limit)
207
+ elsif limit
208
+ return documents.first(limit)
209
+ elsif skip
210
+ return documents.slice(skip..-1)
211
+ end
212
+ documents
213
+ end
214
+
215
+ # Sorts the result set if sort options have been set.
216
+ def sort(documents)
217
+ return documents if options[:sort].blank?
218
+ documents.sort_by do |document|
219
+ options[:sort].map do |key, direction|
220
+ Sort.new(document.read_attribute(key), direction)
221
+ end
222
+ end
223
+ end
224
+ end
225
+ end
226
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Contexts #:nodoc:
4
+ module Ids
5
+ # Return documents based on an id search. Will handle if a single id has
6
+ # been passed or mulitple ids.
7
+ #
8
+ # Example:
9
+ #
10
+ # context.id_criteria([1, 2, 3])
11
+ #
12
+ # Returns:
13
+ #
14
+ # The single or multiple documents.
15
+ def id_criteria(params)
16
+ self.criteria = criteria.id(params)
17
+ result = params.is_a?(Array) ? criteria.entries : one
18
+ if Mongoid.raise_not_found_error && !params.blank?
19
+ raise Errors::DocumentNotFound.new(klass, params) if result.blank?
20
+ end
21
+ return result
22
+ end
23
+ end
24
+ end
25
+ end