mongoid-multi-db 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (276) hide show
  1. data/CHANGELOG.md +615 -0
  2. data/LICENSE +20 -0
  3. data/README.md +62 -0
  4. data/Rakefile +49 -0
  5. data/lib/config/locales/bg.yml +54 -0
  6. data/lib/config/locales/de.yml +54 -0
  7. data/lib/config/locales/en-GB.yml +55 -0
  8. data/lib/config/locales/en.yml +55 -0
  9. data/lib/config/locales/es.yml +52 -0
  10. data/lib/config/locales/fr.yml +55 -0
  11. data/lib/config/locales/hi.yml +46 -0
  12. data/lib/config/locales/hu.yml +57 -0
  13. data/lib/config/locales/id.yml +55 -0
  14. data/lib/config/locales/it.yml +52 -0
  15. data/lib/config/locales/ja.yml +50 -0
  16. data/lib/config/locales/kr.yml +47 -0
  17. data/lib/config/locales/nl.yml +52 -0
  18. data/lib/config/locales/pl.yml +52 -0
  19. data/lib/config/locales/pt-BR.yml +53 -0
  20. data/lib/config/locales/pt.yml +53 -0
  21. data/lib/config/locales/ro.yml +59 -0
  22. data/lib/config/locales/ru.yml +54 -0
  23. data/lib/config/locales/sv.yml +53 -0
  24. data/lib/config/locales/vi.yml +55 -0
  25. data/lib/config/locales/zh-CN.yml +46 -0
  26. data/lib/mongoid.rb +148 -0
  27. data/lib/mongoid/atomic.rb +230 -0
  28. data/lib/mongoid/atomic/modifiers.rb +243 -0
  29. data/lib/mongoid/atomic/paths.rb +3 -0
  30. data/lib/mongoid/atomic/paths/embedded.rb +43 -0
  31. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  32. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  33. data/lib/mongoid/atomic/paths/root.rb +40 -0
  34. data/lib/mongoid/attributes.rb +234 -0
  35. data/lib/mongoid/attributes/processing.rb +146 -0
  36. data/lib/mongoid/callbacks.rb +135 -0
  37. data/lib/mongoid/collection.rb +153 -0
  38. data/lib/mongoid/collection_proxy.rb +59 -0
  39. data/lib/mongoid/collections.rb +120 -0
  40. data/lib/mongoid/collections/master.rb +45 -0
  41. data/lib/mongoid/collections/operations.rb +44 -0
  42. data/lib/mongoid/collections/retry.rb +46 -0
  43. data/lib/mongoid/components.rb +96 -0
  44. data/lib/mongoid/config.rb +347 -0
  45. data/lib/mongoid/config/database.rb +186 -0
  46. data/lib/mongoid/config/replset_database.rb +82 -0
  47. data/lib/mongoid/connection_proxy.rb +30 -0
  48. data/lib/mongoid/contexts.rb +25 -0
  49. data/lib/mongoid/contexts/enumerable.rb +288 -0
  50. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  51. data/lib/mongoid/contexts/mongo.rb +409 -0
  52. data/lib/mongoid/copyable.rb +48 -0
  53. data/lib/mongoid/criteria.rb +418 -0
  54. data/lib/mongoid/criterion/builder.rb +34 -0
  55. data/lib/mongoid/criterion/complex.rb +84 -0
  56. data/lib/mongoid/criterion/creational.rb +34 -0
  57. data/lib/mongoid/criterion/exclusion.rb +108 -0
  58. data/lib/mongoid/criterion/inclusion.rb +305 -0
  59. data/lib/mongoid/criterion/inspection.rb +22 -0
  60. data/lib/mongoid/criterion/optional.rb +232 -0
  61. data/lib/mongoid/criterion/selector.rb +153 -0
  62. data/lib/mongoid/cursor.rb +86 -0
  63. data/lib/mongoid/database_proxy.rb +97 -0
  64. data/lib/mongoid/default_scope.rb +36 -0
  65. data/lib/mongoid/dirty.rb +110 -0
  66. data/lib/mongoid/document.rb +280 -0
  67. data/lib/mongoid/errors.rb +17 -0
  68. data/lib/mongoid/errors/callback.rb +26 -0
  69. data/lib/mongoid/errors/document_not_found.rb +28 -0
  70. data/lib/mongoid/errors/eager_load.rb +25 -0
  71. data/lib/mongoid/errors/invalid_collection.rb +18 -0
  72. data/lib/mongoid/errors/invalid_database.rb +19 -0
  73. data/lib/mongoid/errors/invalid_field.rb +18 -0
  74. data/lib/mongoid/errors/invalid_find.rb +19 -0
  75. data/lib/mongoid/errors/invalid_options.rb +28 -0
  76. data/lib/mongoid/errors/invalid_time.rb +25 -0
  77. data/lib/mongoid/errors/invalid_type.rb +25 -0
  78. data/lib/mongoid/errors/mixed_relations.rb +37 -0
  79. data/lib/mongoid/errors/mongoid_error.rb +26 -0
  80. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
  81. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  82. data/lib/mongoid/errors/unsupported_version.rb +20 -0
  83. data/lib/mongoid/errors/validations.rb +23 -0
  84. data/lib/mongoid/extensions.rb +82 -0
  85. data/lib/mongoid/extensions/array/deletion.rb +29 -0
  86. data/lib/mongoid/extensions/false_class/equality.rb +26 -0
  87. data/lib/mongoid/extensions/hash/criteria_helpers.rb +45 -0
  88. data/lib/mongoid/extensions/hash/scoping.rb +25 -0
  89. data/lib/mongoid/extensions/integer/checks.rb +23 -0
  90. data/lib/mongoid/extensions/nil/collectionization.rb +23 -0
  91. data/lib/mongoid/extensions/object/checks.rb +29 -0
  92. data/lib/mongoid/extensions/object/reflections.rb +48 -0
  93. data/lib/mongoid/extensions/object/substitutable.rb +15 -0
  94. data/lib/mongoid/extensions/object/yoda.rb +44 -0
  95. data/lib/mongoid/extensions/object_id/conversions.rb +60 -0
  96. data/lib/mongoid/extensions/proc/scoping.rb +25 -0
  97. data/lib/mongoid/extensions/string/checks.rb +36 -0
  98. data/lib/mongoid/extensions/string/conversions.rb +22 -0
  99. data/lib/mongoid/extensions/string/inflections.rb +118 -0
  100. data/lib/mongoid/extensions/symbol/checks.rb +23 -0
  101. data/lib/mongoid/extensions/symbol/inflections.rb +66 -0
  102. data/lib/mongoid/extensions/true_class/equality.rb +26 -0
  103. data/lib/mongoid/extras.rb +31 -0
  104. data/lib/mongoid/factory.rb +46 -0
  105. data/lib/mongoid/fields.rb +332 -0
  106. data/lib/mongoid/fields/mappings.rb +41 -0
  107. data/lib/mongoid/fields/serializable.rb +201 -0
  108. data/lib/mongoid/fields/serializable/array.rb +49 -0
  109. data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
  110. data/lib/mongoid/fields/serializable/bignum.rb +10 -0
  111. data/lib/mongoid/fields/serializable/binary.rb +11 -0
  112. data/lib/mongoid/fields/serializable/boolean.rb +43 -0
  113. data/lib/mongoid/fields/serializable/date.rb +51 -0
  114. data/lib/mongoid/fields/serializable/date_time.rb +28 -0
  115. data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
  116. data/lib/mongoid/fields/serializable/float.rb +32 -0
  117. data/lib/mongoid/fields/serializable/foreign_keys/array.rb +42 -0
  118. data/lib/mongoid/fields/serializable/foreign_keys/object.rb +47 -0
  119. data/lib/mongoid/fields/serializable/hash.rb +11 -0
  120. data/lib/mongoid/fields/serializable/integer.rb +44 -0
  121. data/lib/mongoid/fields/serializable/localized.rb +41 -0
  122. data/lib/mongoid/fields/serializable/nil_class.rb +38 -0
  123. data/lib/mongoid/fields/serializable/object.rb +11 -0
  124. data/lib/mongoid/fields/serializable/object_id.rb +31 -0
  125. data/lib/mongoid/fields/serializable/range.rb +42 -0
  126. data/lib/mongoid/fields/serializable/set.rb +42 -0
  127. data/lib/mongoid/fields/serializable/string.rb +27 -0
  128. data/lib/mongoid/fields/serializable/symbol.rb +27 -0
  129. data/lib/mongoid/fields/serializable/time.rb +23 -0
  130. data/lib/mongoid/fields/serializable/time_with_zone.rb +23 -0
  131. data/lib/mongoid/fields/serializable/timekeeping.rb +106 -0
  132. data/lib/mongoid/finders.rb +152 -0
  133. data/lib/mongoid/hierarchy.rb +120 -0
  134. data/lib/mongoid/identity.rb +92 -0
  135. data/lib/mongoid/identity_map.rb +119 -0
  136. data/lib/mongoid/indexes.rb +54 -0
  137. data/lib/mongoid/inspection.rb +54 -0
  138. data/lib/mongoid/javascript.rb +20 -0
  139. data/lib/mongoid/javascript/functions.yml +63 -0
  140. data/lib/mongoid/json.rb +16 -0
  141. data/lib/mongoid/keys.rb +144 -0
  142. data/lib/mongoid/logger.rb +39 -0
  143. data/lib/mongoid/matchers.rb +32 -0
  144. data/lib/mongoid/matchers/all.rb +21 -0
  145. data/lib/mongoid/matchers/and.rb +30 -0
  146. data/lib/mongoid/matchers/default.rb +70 -0
  147. data/lib/mongoid/matchers/exists.rb +23 -0
  148. data/lib/mongoid/matchers/gt.rb +21 -0
  149. data/lib/mongoid/matchers/gte.rb +21 -0
  150. data/lib/mongoid/matchers/in.rb +21 -0
  151. data/lib/mongoid/matchers/lt.rb +21 -0
  152. data/lib/mongoid/matchers/lte.rb +21 -0
  153. data/lib/mongoid/matchers/ne.rb +21 -0
  154. data/lib/mongoid/matchers/nin.rb +21 -0
  155. data/lib/mongoid/matchers/or.rb +33 -0
  156. data/lib/mongoid/matchers/size.rb +21 -0
  157. data/lib/mongoid/matchers/strategies.rb +93 -0
  158. data/lib/mongoid/multi_database.rb +31 -0
  159. data/lib/mongoid/multi_parameter_attributes.rb +106 -0
  160. data/lib/mongoid/named_scope.rb +146 -0
  161. data/lib/mongoid/nested_attributes.rb +54 -0
  162. data/lib/mongoid/observer.rb +170 -0
  163. data/lib/mongoid/paranoia.rb +158 -0
  164. data/lib/mongoid/persistence.rb +264 -0
  165. data/lib/mongoid/persistence/atomic.rb +223 -0
  166. data/lib/mongoid/persistence/atomic/add_to_set.rb +35 -0
  167. data/lib/mongoid/persistence/atomic/bit.rb +37 -0
  168. data/lib/mongoid/persistence/atomic/inc.rb +31 -0
  169. data/lib/mongoid/persistence/atomic/operation.rb +85 -0
  170. data/lib/mongoid/persistence/atomic/pop.rb +34 -0
  171. data/lib/mongoid/persistence/atomic/pull.rb +34 -0
  172. data/lib/mongoid/persistence/atomic/pull_all.rb +34 -0
  173. data/lib/mongoid/persistence/atomic/push.rb +31 -0
  174. data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
  175. data/lib/mongoid/persistence/atomic/rename.rb +31 -0
  176. data/lib/mongoid/persistence/atomic/sets.rb +30 -0
  177. data/lib/mongoid/persistence/atomic/unset.rb +28 -0
  178. data/lib/mongoid/persistence/deletion.rb +32 -0
  179. data/lib/mongoid/persistence/insertion.rb +41 -0
  180. data/lib/mongoid/persistence/modification.rb +37 -0
  181. data/lib/mongoid/persistence/operations.rb +211 -0
  182. data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
  183. data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
  184. data/lib/mongoid/persistence/operations/insert.rb +34 -0
  185. data/lib/mongoid/persistence/operations/remove.rb +33 -0
  186. data/lib/mongoid/persistence/operations/update.rb +64 -0
  187. data/lib/mongoid/railtie.rb +126 -0
  188. data/lib/mongoid/railties/database.rake +182 -0
  189. data/lib/mongoid/railties/document.rb +12 -0
  190. data/lib/mongoid/relations.rb +144 -0
  191. data/lib/mongoid/relations/accessors.rb +138 -0
  192. data/lib/mongoid/relations/auto_save.rb +38 -0
  193. data/lib/mongoid/relations/binding.rb +26 -0
  194. data/lib/mongoid/relations/bindings.rb +9 -0
  195. data/lib/mongoid/relations/bindings/embedded/in.rb +69 -0
  196. data/lib/mongoid/relations/bindings/embedded/many.rb +93 -0
  197. data/lib/mongoid/relations/bindings/embedded/one.rb +61 -0
  198. data/lib/mongoid/relations/bindings/referenced/in.rb +76 -0
  199. data/lib/mongoid/relations/bindings/referenced/many.rb +54 -0
  200. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +51 -0
  201. data/lib/mongoid/relations/bindings/referenced/one.rb +58 -0
  202. data/lib/mongoid/relations/builder.rb +57 -0
  203. data/lib/mongoid/relations/builders.rb +83 -0
  204. data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
  205. data/lib/mongoid/relations/builders/embedded/many.rb +40 -0
  206. data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
  207. data/lib/mongoid/relations/builders/nested_attributes/many.rb +110 -0
  208. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  209. data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
  210. data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
  211. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +38 -0
  212. data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
  213. data/lib/mongoid/relations/cascading.rb +56 -0
  214. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  215. data/lib/mongoid/relations/cascading/destroy.rb +26 -0
  216. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  217. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  218. data/lib/mongoid/relations/constraint.rb +42 -0
  219. data/lib/mongoid/relations/conversions.rb +35 -0
  220. data/lib/mongoid/relations/cyclic.rb +103 -0
  221. data/lib/mongoid/relations/embedded/atomic.rb +89 -0
  222. data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
  223. data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
  224. data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
  225. data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
  226. data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
  227. data/lib/mongoid/relations/embedded/in.rb +220 -0
  228. data/lib/mongoid/relations/embedded/many.rb +560 -0
  229. data/lib/mongoid/relations/embedded/one.rb +206 -0
  230. data/lib/mongoid/relations/embedded/sort.rb +31 -0
  231. data/lib/mongoid/relations/macros.rb +310 -0
  232. data/lib/mongoid/relations/many.rb +135 -0
  233. data/lib/mongoid/relations/metadata.rb +919 -0
  234. data/lib/mongoid/relations/nested_builder.rb +75 -0
  235. data/lib/mongoid/relations/one.rb +36 -0
  236. data/lib/mongoid/relations/options.rb +47 -0
  237. data/lib/mongoid/relations/polymorphic.rb +40 -0
  238. data/lib/mongoid/relations/proxy.rb +145 -0
  239. data/lib/mongoid/relations/referenced/batch.rb +72 -0
  240. data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
  241. data/lib/mongoid/relations/referenced/in.rb +262 -0
  242. data/lib/mongoid/relations/referenced/many.rb +623 -0
  243. data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
  244. data/lib/mongoid/relations/referenced/one.rb +272 -0
  245. data/lib/mongoid/relations/reflections.rb +62 -0
  246. data/lib/mongoid/relations/synchronization.rb +153 -0
  247. data/lib/mongoid/relations/targets.rb +2 -0
  248. data/lib/mongoid/relations/targets/enumerable.rb +372 -0
  249. data/lib/mongoid/reloading.rb +91 -0
  250. data/lib/mongoid/safety.rb +105 -0
  251. data/lib/mongoid/scope.rb +31 -0
  252. data/lib/mongoid/serialization.rb +134 -0
  253. data/lib/mongoid/sharding.rb +61 -0
  254. data/lib/mongoid/state.rb +97 -0
  255. data/lib/mongoid/threaded.rb +530 -0
  256. data/lib/mongoid/threaded/lifecycle.rb +192 -0
  257. data/lib/mongoid/timestamps.rb +15 -0
  258. data/lib/mongoid/timestamps/created.rb +24 -0
  259. data/lib/mongoid/timestamps/timeless.rb +50 -0
  260. data/lib/mongoid/timestamps/updated.rb +26 -0
  261. data/lib/mongoid/validations.rb +140 -0
  262. data/lib/mongoid/validations/associated.rb +46 -0
  263. data/lib/mongoid/validations/uniqueness.rb +145 -0
  264. data/lib/mongoid/version.rb +4 -0
  265. data/lib/mongoid/versioning.rb +185 -0
  266. data/lib/rack/mongoid.rb +2 -0
  267. data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
  268. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  269. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
  270. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  271. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
  272. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  273. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
  274. data/lib/rails/generators/mongoid_generator.rb +70 -0
  275. data/lib/rails/mongoid.rb +91 -0
  276. metadata +465 -0
@@ -0,0 +1,186 @@
1
+ require 'mongoid/connection_proxy'
2
+
3
+ # encoding: utf-8
4
+ module Mongoid #:nodoc:
5
+ module Config #:nodoc:
6
+
7
+ # This class handles the configuration and initialization of a mongodb
8
+ # database from options.
9
+ class Database < Hash
10
+
11
+ # keys to remove from self to not pass through to Mongo::Connection
12
+ PRIVATE_OPTIONS = %w(uri database username password logger)
13
+
14
+ # Configure the database connections. This will return an array
15
+ # containing the master and an array of slaves.
16
+ #
17
+ # @example Configure the connection.
18
+ # db.configure
19
+ #
20
+ # @return [ Array<Mongo::DB, Array<Mongo:DB>> ] The Mongo databases.
21
+ #
22
+ # @since 2.0.0.rc.1
23
+ def configure
24
+ [ master.db(name), slaves.map { |slave| slave.db(name) } ]
25
+ end
26
+
27
+ # Create the new db configuration class.
28
+ #
29
+ # @example Initialize the class.
30
+ # Config::Database.new(
31
+ # false, "uri" => { "mongodb://durran:password@localhost:27017/mongoid" }
32
+ # )
33
+ #
34
+ # @param [ Hash ] options The configuration options.
35
+ #
36
+ # @option options [ String ] :database The database name.
37
+ # @option options [ String ] :host The database host.
38
+ # @option options [ String ] :password The password for authentication.
39
+ # @option options [ Integer ] :port The port for the database.
40
+ # @option options [ String ] :uri The uri for the database.
41
+ # @option options [ String ] :username The user for authentication.
42
+ #
43
+ # @since 2.0.0.rc.1
44
+ def initialize(options = {})
45
+ merge!(options)
46
+ end
47
+
48
+ private
49
+
50
+ # Do we need to authenticate against the database?
51
+ #
52
+ # @example Are we authenticating?
53
+ # db.authenticating?
54
+ #
55
+ # @return [ true, false ] True if auth is needed, false if not.
56
+ #
57
+ # @since 2.0.0.rc.1
58
+ def authenticating?
59
+ username || password
60
+ end
61
+
62
+ # Takes the supplied options in the hash and created a URI from them to
63
+ # pass to the Mongo connection object.
64
+ #
65
+ # @example Build the URI.
66
+ # db.build_uri
67
+ #
68
+ # @param [ Hash ] options The options to build with.
69
+ #
70
+ # @return [ String ] A mongo compliant URI string.
71
+ #
72
+ # @since 2.0.0.rc.1
73
+ def build_uri(options = {})
74
+ "mongodb://".tap do |base|
75
+ base << "#{username}:#{password}@" if authenticating?
76
+ base << "#{options["host"] || "localhost"}:#{options["port"] || 27017}"
77
+ base << "/#{self["database"]}" if authenticating?
78
+ end
79
+ end
80
+
81
+ # Create the mongo master connection from either the supplied URI
82
+ # or a generated one, while setting pool size and logging.
83
+ #
84
+ # @example Create the connection.
85
+ # db.connection
86
+ #
87
+ # @return [ Mongo::Connection ] The mongo connection.
88
+ #
89
+ # @since 2.0.0.rc.1
90
+ def master
91
+ ConnectionProxy.from_uri(uri(self), optional).tap do |conn|
92
+ conn.apply_saved_authentication
93
+ end
94
+ end
95
+
96
+ # Create the mongo slave connections from either the supplied URI
97
+ # or a generated one, while setting pool size and logging.
98
+ #
99
+ # @example Create the connection.
100
+ # db.connection
101
+ #
102
+ # @return [ Array<Mongo::Connection> ] The mongo slave connections.
103
+ #
104
+ # @since 2.0.0.rc.1
105
+ def slaves
106
+ (self["slaves"] || []).map do |options|
107
+ ConnectionProxy.from_uri(uri(options), optional(true)).tap do |conn|
108
+ conn.apply_saved_authentication
109
+ end
110
+ end
111
+ end
112
+
113
+ # Should we use a logger?
114
+ #
115
+ # @example Should we use a logger?
116
+ # database.logger?
117
+ #
118
+ # @return [ true, false ] Defaults to true, false if specifically
119
+ # defined.
120
+ #
121
+ # @since 2.2.0
122
+ def logger?
123
+ self[:logger].nil? || self[:logger] ? true : false
124
+ end
125
+
126
+ # Convenience for accessing the hash via dot notation.
127
+ #
128
+ # @example Access a value in alternate syntax.
129
+ # db.host
130
+ #
131
+ # @return [ Object ] The value in the hash.
132
+ #
133
+ # @since 2.0.0.rc.1
134
+ def method_missing(name, *args, &block)
135
+ self[name.to_s]
136
+ end
137
+
138
+ # Get the name of the database, from either the URI supplied or the
139
+ # database value in the options.
140
+ #
141
+ # @example Get the database name.
142
+ # db.name
143
+ #
144
+ # @return [ String ] The database name.
145
+ #
146
+ # @since 2.0.0.rc.1
147
+ def name
148
+ db_name = URI.parse(uri(self)).path.to_s.sub("/", "")
149
+ db_name.blank? ? database : db_name
150
+ end
151
+
152
+ # Get the options used in creating the database connection.
153
+ #
154
+ # @example Get the options.
155
+ # db.options
156
+ #
157
+ # @param [ true, false ] slave Are the options for a slave db?
158
+ #
159
+ # @return [ Hash ] The hash of configuration options.
160
+ #
161
+ # @since 2.0.0.rc.1
162
+ def optional(slave = false)
163
+ ({
164
+ :pool_size => pool_size,
165
+ :logger => logger? ? Mongoid::Logger.new : nil,
166
+ :slave_ok => slave
167
+ }).merge(self).reject { |k,v| PRIVATE_OPTIONS.include? k }.
168
+ inject({}) { |memo, (k, v)| memo[k.to_sym] = v; memo} # mongo likes symbols
169
+ end
170
+
171
+ # Get a Mongo compliant URI for the database connection.
172
+ #
173
+ # @example Get the URI.
174
+ # db.uri
175
+ #
176
+ # @param [ Hash ] options The options hash.
177
+ #
178
+ # @return [ String ] The URI for the connection.
179
+ #
180
+ # @since 2.0.0.rc.1
181
+ def uri(options = {})
182
+ options["uri"] || build_uri(options)
183
+ end
184
+ end
185
+ end
186
+ end
@@ -0,0 +1,82 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Config #:nodoc:
4
+ class ReplsetDatabase < Hash
5
+
6
+ # Configure the database connections. This will return an array
7
+ # containing one Mongo::DB and nil (to keep compatibility with Mongoid::Config::Database)
8
+ # If you want the reads to go to a secondary node use the :read_secondary(true): option
9
+ #
10
+ # @example Configure the connection.
11
+ # db.configure
12
+ #
13
+ # @return [ Array<Mongo::DB, nil ] The Mongo databases.
14
+ #
15
+ # @since 2.0.0.rc.5
16
+ def configure
17
+ # yes, construction is weird but the driver wants
18
+ # "A list of host-port pairs ending with a hash containing any options"
19
+ # mongo likes symbols
20
+ options = self.inject({ :logger => Mongoid::Logger.new }) do |memo, (k, v)|
21
+ memo[k.to_sym] = v
22
+ memo
23
+ end
24
+ connection = Mongo::ReplSetConnection.new(*(hosts.clone << options))
25
+
26
+ if authenticating?
27
+ connection.add_auth(database, username, password)
28
+ connection.apply_saved_authentication
29
+ end
30
+
31
+ [ DatabaseProxy.new(connection, database), nil ]
32
+ end
33
+
34
+ # Do we need to authenticate against the database?
35
+ #
36
+ # @example Are we authenticating?
37
+ # db.authenticating?
38
+ #
39
+ # @return [ true, false ] True if auth is needed, false if not.
40
+ #
41
+ # @since 2.0.2
42
+ def authenticating?
43
+ username || password
44
+ end
45
+
46
+ # Convenience for accessing the hash via dot notation.
47
+ #
48
+ # @example Access a value in alternate syntax.
49
+ # db.host
50
+ #
51
+ # @return [ Object ] The value in the hash.
52
+ #
53
+ # @since 2.0.2
54
+ def method_missing(name, *args, &block)
55
+ self[name.to_s]
56
+ end
57
+
58
+ # Create the new db configuration class.
59
+ #
60
+ # @example Initialize the class.
61
+ # Config::ReplsetDatabase.new(
62
+ # "hosts" => [[host1,port1],[host2,port2]]
63
+ # )
64
+ #
65
+ # replSet does not supports auth
66
+ #
67
+ # @param [ Hash ] options The configuration options.
68
+ #
69
+ # @option options [ Array ] :hosts The database host.
70
+ # @option options [ String ] :database The database name.
71
+ # @option options [ Boolean ] :read_secondary Tells the driver to read from secondaries.
72
+ # ...
73
+ #
74
+ # @see Mongo::ReplSetConnection for all options
75
+ #
76
+ # @since 2.0.0.rc.5
77
+ def initialize(options = {})
78
+ merge!(options)
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,30 @@
1
+ require 'mongoid/database_proxy'
2
+
3
+ #
4
+ # Proxy that enables runtime swapping of the MongoDB connection. This is
5
+ # not an ideal-solution, performance-wise, as a quick check shows that
6
+ # method invocation via method_missing is about three times as slow as
7
+ # direct invocation on the object.
8
+ #
9
+ # What this does allow us to do, however, is very transparently swap out
10
+ # Mongo::Connection instances underneath Mongoid, without having to
11
+ # rewrite large portions of the codebase. In theory, this should result
12
+ # in a relatively painless connection-swapping system.
13
+ #
14
+ class ConnectionProxy
15
+ def ConnectionProxy.from_uri(*args)
16
+ new(*args)
17
+ end
18
+
19
+ def initialize(*args)
20
+ @connection = Mongo::Connection.from_uri(*args)
21
+ end
22
+
23
+ def db(name)
24
+ @database ||= DatabaseProxy.new(@connection, name)
25
+ end
26
+
27
+ def method_missing(*args, &block)
28
+ @connection.send(*args, &block)
29
+ end
30
+ end
@@ -0,0 +1,25 @@
1
+ # encoding: utf-8
2
+ require "mongoid/contexts/enumerable"
3
+ require "mongoid/contexts/mongo"
4
+
5
+ module Mongoid
6
+ module Contexts
7
+ extend self
8
+
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 Get the context for the criteria.
15
+ # Contexts.context_for(criteria)
16
+ #
17
+ # @param [ Criteria ] criteria The criteria to use.
18
+ # @param [ true, false ] embedded Whether this is on embedded documents.
19
+ #
20
+ # @return [ Enumerable, Mongo ] The appropriate context.
21
+ def context_for(criteria, embedded = false)
22
+ embedded ? Enumerable.new(criteria) : Mongo.new(criteria)
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,288 @@
1
+ # encoding: utf-8
2
+ require 'mongoid/contexts/enumerable/sort'
3
+
4
+ module Mongoid #:nodoc:
5
+ module Contexts #:nodoc:
6
+ class Enumerable
7
+ include Relations::Embedded::Atomic
8
+
9
+ attr_accessor :collection, :criteria
10
+
11
+ delegate :blank?, :empty?, :first, :last, :to => :execute
12
+ delegate :klass, :documents, :options, :field_list, :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
+ # @example Aggregate on a field.
18
+ # person.addresses.only(:street).aggregate
19
+ #
20
+ # @return [ Hash ] Field values as keys, count as values
21
+ def aggregate
22
+ {}.tap do |counts|
23
+ group.each_pair { |key, value| counts[key] = value.size }
24
+ end
25
+ end
26
+
27
+ # Get the average value for the supplied field.
28
+ #
29
+ # @example Get the average.
30
+ # context.avg(:age)
31
+ #
32
+ # @return [ Numeric ] A numeric value that is the average.
33
+ def avg(field)
34
+ total = sum(field)
35
+ total ? (total.to_f / count) : nil
36
+ end
37
+
38
+ # Gets the number of documents in the array. Delegates to size.
39
+ #
40
+ # @example Get the count.
41
+ # context.count
42
+ #
43
+ # @return [ Integer ] The count of documents.
44
+ def count
45
+ @count ||= execute.size
46
+ end
47
+ alias :length :count
48
+ alias :size :count
49
+
50
+ # Delete all the documents in the database matching the selector.
51
+ #
52
+ # @example Delete the documents.
53
+ # context.delete_all
54
+ #
55
+ # @return [ Integer ] The number of documents deleted.
56
+ #
57
+ # @since 2.0.0.rc.1
58
+ def delete_all
59
+ atomically(:$pull) do
60
+ set_collection
61
+ count.tap do
62
+ filter.each { |doc| doc.delete }
63
+ end
64
+ end
65
+ end
66
+ alias :delete :delete_all
67
+
68
+ # Destroy all the documents in the database matching the selector.
69
+ #
70
+ # @example Destroy the documents.
71
+ # context.destroy_all
72
+ #
73
+ # @return [ Integer ] The number of documents destroyed.
74
+ #
75
+ # @since 2.0.0.rc.1
76
+ def destroy_all
77
+ atomically(:$pull) do
78
+ set_collection
79
+ count.tap do
80
+ filter.each { |doc| doc.destroy }
81
+ end
82
+ end
83
+ end
84
+ alias :destroy :destroy_all
85
+
86
+ # Gets an array of distinct values for the supplied field across the
87
+ # entire array or the susbset given the criteria.
88
+ #
89
+ # @example Get the list of distinct values.
90
+ # context.distinct(:title)
91
+ #
92
+ # @return [ Array<String> ] The distinct values.
93
+ def distinct(field)
94
+ execute.collect { |doc| doc.send(field) }.uniq
95
+ end
96
+
97
+ # Enumerable implementation of execute. Returns matching documents for
98
+ # the selector, and adds options if supplied.
99
+ #
100
+ # @example Execute the context.
101
+ # context.execute
102
+ #
103
+ # @return [ Array<Document> ] Documents that matched the selector.
104
+ def execute
105
+ limit(sort(filter)) || []
106
+ end
107
+
108
+ # Groups the documents by the first field supplied in the field options.
109
+ #
110
+ # @example Group the context.
111
+ # context.group
112
+ #
113
+ # @return [ Hash ] Field values as keys, arrays of documents as values.
114
+ def group
115
+ field = field_list.first
116
+ execute.group_by { |doc| doc.send(field) }
117
+ end
118
+
119
+ # Create the new enumerable context. This will need the selector and
120
+ # options from a +Criteria+ and a documents array that is the underlying
121
+ # array of embedded documents from a has many association.
122
+ #
123
+ # @example Create a new context.
124
+ # Mongoid::Contexts::Enumerable.new(criteria)
125
+ #
126
+ # @param [ Criteria ] criteria The criteria for the context.
127
+ def initialize(criteria)
128
+ @criteria = criteria
129
+ end
130
+
131
+ # Iterate over each +Document+ in the results. This can take an optional
132
+ # block to pass to each argument in the results.
133
+ #
134
+ # @example Iterate over the documents.
135
+ # context.iterate { |doc| p doc }
136
+ def iterate(&block)
137
+ execute.each(&block)
138
+ end
139
+
140
+ # Get the largest value for the field in all the documents.
141
+ #
142
+ # @example Get the max value.
143
+ # context.max(:age)
144
+ #
145
+ # @return [ Numeric ] The numerical largest value.
146
+ def max(field)
147
+ determine(field, :>=)
148
+ end
149
+
150
+ # Get the smallest value for the field in all the documents.
151
+ #
152
+ # @example Get the minimum value.
153
+ # context.min(:age)
154
+ #
155
+ # @return [ Numeric ] The numerical smallest value.
156
+ def min(field)
157
+ determine(field, :<=)
158
+ end
159
+
160
+ # Get one document.
161
+ #
162
+ # @example Get one document.
163
+ # context.one
164
+ #
165
+ # @return [ Document ] The first document in the array.
166
+ alias :one :first
167
+
168
+ # Get one document and tell the criteria to skip this record on
169
+ # successive calls.
170
+ #
171
+ # @example Shift the documents.
172
+ # context.shift
173
+ #
174
+ # @return [ Document ] The first document in the array.
175
+ def shift
176
+ first.tap do |document|
177
+ self.criteria = criteria.skip((options[:skip] || 0) + 1)
178
+ end
179
+ end
180
+
181
+ # Get the sum of the field values for all the documents.
182
+ #
183
+ # @example Get the sum of the field.
184
+ # context.sum(:cost)
185
+ #
186
+ # @return [ Numeric ] The numerical sum of all the document field values.
187
+ def sum(field)
188
+ sum = execute.inject(nil) do |memo, doc|
189
+ value = doc.send(field) || 0
190
+ memo ? memo += value : value
191
+ end
192
+ end
193
+
194
+ # Very basic update that will perform a simple atomic $set of the
195
+ # attributes provided in the hash. Can be expanded to later for more
196
+ # robust functionality.
197
+ #
198
+ # @example Update all matching documents.
199
+ # context.update_all(:title => "Sir")
200
+ #
201
+ # @param [ Hash ] attributes The sets to perform.
202
+ #
203
+ # @since 2.0.0.rc.6
204
+ def update_all(attributes = nil)
205
+ iterate do |doc|
206
+ doc.update_attributes(attributes || {})
207
+ end
208
+ end
209
+ alias :update :update_all
210
+
211
+ protected
212
+
213
+ # Filters the documents against the criteria's selector
214
+ #
215
+ # @example Filter the documents.
216
+ # context.filter
217
+ #
218
+ # @return [ Array ] The documents filtered.
219
+ def filter
220
+ documents.select { |document| document.matches?(selector) }
221
+ end
222
+
223
+ # If the field exists, perform the comparison and set if true.
224
+ #
225
+ # @example Compare.
226
+ # context.determine
227
+ #
228
+ # @return [ Array<Document> ] The matching documents.
229
+ def determine(field, operator)
230
+ matching = documents.inject(nil) do |memo, doc|
231
+ value = doc.send(field) || 0
232
+ (memo && memo.send(operator, value)) ? memo : value
233
+ end
234
+ end
235
+
236
+ # Limits the result set if skip and limit options.
237
+ #
238
+ # @example Limit the results.
239
+ # context.limit(documents)
240
+ #
241
+ # @return [ Array<Document> ] The limited documents.
242
+ def limit(documents)
243
+ skip, limit = options[:skip], options[:limit]
244
+ if skip && limit
245
+ return documents.slice(skip, limit)
246
+ elsif limit
247
+ return documents.first(limit)
248
+ elsif skip
249
+ return documents.slice(skip..-1)
250
+ end
251
+ documents
252
+ end
253
+
254
+ def root
255
+ @root ||= documents.first.try(:_root)
256
+ end
257
+
258
+ def root_class
259
+ @root_class ||= root ? root.class : nil
260
+ end
261
+
262
+ # Set the collection to the collection of the root document.
263
+ #
264
+ # @example Set the collection.
265
+ # context.set_collection
266
+ #
267
+ # @return [ Collection ] The root collection.
268
+ def set_collection
269
+ @collection = root.collection if root && !root.embedded?
270
+ end
271
+
272
+ # Sorts the result set if sort options have been set.
273
+ #
274
+ # @example Sort the documents.
275
+ # context.sort(documents)
276
+ #
277
+ # @return [ Array<Document> ] The sorted documents.
278
+ def sort(documents)
279
+ return documents if options[:sort].blank?
280
+ documents.sort_by do |document|
281
+ options[:sort].map do |key, direction|
282
+ Sort.new(document.read_attribute(key), direction)
283
+ end
284
+ end
285
+ end
286
+ end
287
+ end
288
+ end