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,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