mongoid 2.0.0.alpha → 2.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (216) hide show
  1. data/lib/mongoid.rb +11 -5
  2. data/lib/mongoid/associations.rb +112 -107
  3. data/lib/mongoid/associations/belongs_to_related.rb +2 -3
  4. data/lib/mongoid/associations/embedded_in.rb +12 -4
  5. data/lib/mongoid/associations/{embed_many.rb → embeds_many.rb} +101 -32
  6. data/lib/mongoid/associations/{embed_one.rb → embeds_one.rb} +10 -10
  7. data/lib/mongoid/associations/has_many_related.rb +51 -5
  8. data/lib/mongoid/associations/has_one_related.rb +9 -5
  9. data/lib/mongoid/associations/meta_data.rb +2 -1
  10. data/lib/mongoid/associations/options.rb +15 -6
  11. data/lib/mongoid/associations/proxy.rb +14 -21
  12. data/lib/mongoid/attributes.rb +34 -13
  13. data/lib/mongoid/callbacks.rb +1 -2
  14. data/lib/mongoid/collection.rb +4 -3
  15. data/lib/mongoid/collections.rb +41 -0
  16. data/lib/mongoid/collections/master.rb +3 -2
  17. data/lib/mongoid/collections/slaves.rb +3 -2
  18. data/lib/mongoid/components.rb +4 -1
  19. data/lib/mongoid/config.rb +163 -13
  20. data/lib/mongoid/contexts.rb +1 -2
  21. data/lib/mongoid/contexts/enumerable.rb +1 -1
  22. data/lib/mongoid/contexts/mongo.rb +1 -1
  23. data/lib/mongoid/contexts/paging.rb +10 -2
  24. data/lib/mongoid/criteria.rb +13 -22
  25. data/lib/mongoid/criterion/exclusion.rb +3 -3
  26. data/lib/mongoid/criterion/inclusion.rb +17 -0
  27. data/lib/mongoid/criterion/optional.rb +1 -1
  28. data/lib/mongoid/dirty.rb +253 -0
  29. data/lib/mongoid/document.rb +40 -85
  30. data/lib/mongoid/errors.rb +48 -1
  31. data/lib/mongoid/extensions.rb +11 -9
  32. data/lib/mongoid/extensions/big_decimal/conversions.rb +2 -2
  33. data/lib/mongoid/extensions/boolean/conversions.rb +8 -2
  34. data/lib/mongoid/extensions/date/conversions.rb +13 -4
  35. data/lib/mongoid/extensions/datetime/conversions.rb +1 -6
  36. data/lib/mongoid/extensions/float/conversions.rb +5 -1
  37. data/lib/mongoid/extensions/hash/assimilation.rb +12 -3
  38. data/lib/mongoid/extensions/hash/conversions.rb +34 -4
  39. data/lib/mongoid/extensions/integer/conversions.rb +5 -1
  40. data/lib/mongoid/extensions/nil/assimilation.rb +4 -0
  41. data/lib/mongoid/extensions/object/conversions.rb +3 -3
  42. data/lib/mongoid/extensions/string/conversions.rb +1 -1
  43. data/lib/mongoid/extensions/symbol/inflections.rb +5 -2
  44. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  45. data/lib/mongoid/factory.rb +2 -1
  46. data/lib/mongoid/field.rb +15 -2
  47. data/lib/mongoid/fields.rb +1 -1
  48. data/lib/mongoid/identity.rb +3 -3
  49. data/lib/mongoid/indexes.rb +3 -3
  50. data/lib/mongoid/matchers.rb +1 -2
  51. data/lib/mongoid/memoization.rb +8 -2
  52. data/lib/mongoid/named_scope.rb +0 -5
  53. data/lib/mongoid/observable.rb +1 -1
  54. data/lib/mongoid/paths.rb +30 -22
  55. data/lib/mongoid/persistence.rb +218 -0
  56. data/lib/mongoid/persistence/command.rb +39 -0
  57. data/lib/mongoid/persistence/insert.rb +47 -0
  58. data/lib/mongoid/persistence/insert_embedded.rb +38 -0
  59. data/lib/mongoid/persistence/remove.rb +39 -0
  60. data/lib/mongoid/persistence/remove_all.rb +37 -0
  61. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  62. data/lib/mongoid/persistence/update.rb +63 -0
  63. data/lib/mongoid/railtie.rb +53 -0
  64. data/lib/mongoid/railties/database.rake +37 -0
  65. data/lib/mongoid/timestamps.rb +2 -2
  66. data/lib/mongoid/validations.rb +2 -2
  67. data/lib/mongoid/validations/associated.rb +2 -2
  68. data/lib/mongoid/validations/uniqueness.rb +13 -2
  69. data/lib/mongoid/version.rb +4 -0
  70. data/lib/mongoid/versioning.rb +3 -2
  71. data/lib/rails/generators/mongoid/config/config_generator.rb +41 -0
  72. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
  73. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  74. data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
  75. data/lib/rails/generators/mongoid_generator.rb +61 -0
  76. metadata +76 -301
  77. data/.gitignore +0 -6
  78. data/.watchr +0 -29
  79. data/Rakefile +0 -52
  80. data/VERSION +0 -1
  81. data/caliper.yml +0 -4
  82. data/lib/mongoid/collections/mimic.rb +0 -46
  83. data/lib/mongoid/commands.rb +0 -161
  84. data/lib/mongoid/commands/create.rb +0 -19
  85. data/lib/mongoid/commands/delete.rb +0 -16
  86. data/lib/mongoid/commands/delete_all.rb +0 -23
  87. data/lib/mongoid/commands/deletion.rb +0 -18
  88. data/lib/mongoid/commands/destroy.rb +0 -17
  89. data/lib/mongoid/commands/destroy_all.rb +0 -23
  90. data/lib/mongoid/commands/save.rb +0 -29
  91. data/lib/mongoid/extensions/time/conversions.rb +0 -18
  92. data/mongoid.gemspec +0 -408
  93. data/perf/benchmark.rb +0 -77
  94. data/spec/integration/mongoid/associations_spec.rb +0 -340
  95. data/spec/integration/mongoid/attributes_spec.rb +0 -22
  96. data/spec/integration/mongoid/commands_spec.rb +0 -227
  97. data/spec/integration/mongoid/contexts/enumerable_spec.rb +0 -33
  98. data/spec/integration/mongoid/criteria_spec.rb +0 -272
  99. data/spec/integration/mongoid/document_spec.rb +0 -650
  100. data/spec/integration/mongoid/extensions_spec.rb +0 -22
  101. data/spec/integration/mongoid/finders_spec.rb +0 -119
  102. data/spec/integration/mongoid/inheritance_spec.rb +0 -137
  103. data/spec/integration/mongoid/named_scope_spec.rb +0 -46
  104. data/spec/models/address.rb +0 -39
  105. data/spec/models/animal.rb +0 -6
  106. data/spec/models/callbacks.rb +0 -18
  107. data/spec/models/comment.rb +0 -8
  108. data/spec/models/country_code.rb +0 -6
  109. data/spec/models/employer.rb +0 -5
  110. data/spec/models/game.rb +0 -7
  111. data/spec/models/inheritance.rb +0 -56
  112. data/spec/models/location.rb +0 -5
  113. data/spec/models/mixed_drink.rb +0 -4
  114. data/spec/models/name.rb +0 -13
  115. data/spec/models/namespacing.rb +0 -11
  116. data/spec/models/patient.rb +0 -4
  117. data/spec/models/person.rb +0 -99
  118. data/spec/models/pet.rb +0 -7
  119. data/spec/models/pet_owner.rb +0 -6
  120. data/spec/models/phone.rb +0 -7
  121. data/spec/models/post.rb +0 -15
  122. data/spec/models/translation.rb +0 -5
  123. data/spec/models/vet_visit.rb +0 -5
  124. data/spec/spec.opts +0 -3
  125. data/spec/spec_helper.rb +0 -31
  126. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +0 -145
  127. data/spec/unit/mongoid/associations/embed_many_spec.rb +0 -516
  128. data/spec/unit/mongoid/associations/embed_one_spec.rb +0 -282
  129. data/spec/unit/mongoid/associations/embedded_in_spec.rb +0 -193
  130. data/spec/unit/mongoid/associations/has_many_related_spec.rb +0 -418
  131. data/spec/unit/mongoid/associations/has_one_related_spec.rb +0 -179
  132. data/spec/unit/mongoid/associations/meta_data_spec.rb +0 -88
  133. data/spec/unit/mongoid/associations/options_spec.rb +0 -192
  134. data/spec/unit/mongoid/associations_spec.rb +0 -595
  135. data/spec/unit/mongoid/attributes_spec.rb +0 -507
  136. data/spec/unit/mongoid/callbacks_spec.rb +0 -55
  137. data/spec/unit/mongoid/collection_spec.rb +0 -187
  138. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +0 -75
  139. data/spec/unit/mongoid/collections/master_spec.rb +0 -41
  140. data/spec/unit/mongoid/collections/mimic_spec.rb +0 -43
  141. data/spec/unit/mongoid/collections/slaves_spec.rb +0 -81
  142. data/spec/unit/mongoid/commands/create_spec.rb +0 -31
  143. data/spec/unit/mongoid/commands/delete_all_spec.rb +0 -58
  144. data/spec/unit/mongoid/commands/delete_spec.rb +0 -38
  145. data/spec/unit/mongoid/commands/destroy_all_spec.rb +0 -21
  146. data/spec/unit/mongoid/commands/destroy_spec.rb +0 -51
  147. data/spec/unit/mongoid/commands/save_spec.rb +0 -107
  148. data/spec/unit/mongoid/commands_spec.rb +0 -270
  149. data/spec/unit/mongoid/config_spec.rb +0 -172
  150. data/spec/unit/mongoid/contexts/enumerable_spec.rb +0 -421
  151. data/spec/unit/mongoid/contexts/mongo_spec.rb +0 -682
  152. data/spec/unit/mongoid/contexts_spec.rb +0 -25
  153. data/spec/unit/mongoid/criteria_spec.rb +0 -824
  154. data/spec/unit/mongoid/criterion/complex_spec.rb +0 -19
  155. data/spec/unit/mongoid/criterion/exclusion_spec.rb +0 -91
  156. data/spec/unit/mongoid/criterion/inclusion_spec.rb +0 -219
  157. data/spec/unit/mongoid/criterion/optional_spec.rb +0 -319
  158. data/spec/unit/mongoid/cursor_spec.rb +0 -74
  159. data/spec/unit/mongoid/deprecation_spec.rb +0 -24
  160. data/spec/unit/mongoid/document_spec.rb +0 -818
  161. data/spec/unit/mongoid/errors_spec.rb +0 -103
  162. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +0 -50
  163. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +0 -24
  164. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +0 -35
  165. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +0 -20
  166. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +0 -22
  167. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +0 -22
  168. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +0 -49
  169. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +0 -102
  170. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +0 -67
  171. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +0 -61
  172. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +0 -184
  173. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +0 -46
  174. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +0 -21
  175. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +0 -17
  176. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +0 -14
  177. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +0 -61
  178. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +0 -24
  179. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +0 -57
  180. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +0 -34
  181. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +0 -17
  182. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +0 -208
  183. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +0 -91
  184. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +0 -70
  185. data/spec/unit/mongoid/extras_spec.rb +0 -102
  186. data/spec/unit/mongoid/factory_spec.rb +0 -31
  187. data/spec/unit/mongoid/field_spec.rb +0 -143
  188. data/spec/unit/mongoid/fields_spec.rb +0 -181
  189. data/spec/unit/mongoid/finders_spec.rb +0 -404
  190. data/spec/unit/mongoid/identity_spec.rb +0 -109
  191. data/spec/unit/mongoid/indexes_spec.rb +0 -93
  192. data/spec/unit/mongoid/javascript_spec.rb +0 -48
  193. data/spec/unit/mongoid/matchers/all_spec.rb +0 -27
  194. data/spec/unit/mongoid/matchers/default_spec.rb +0 -27
  195. data/spec/unit/mongoid/matchers/exists_spec.rb +0 -56
  196. data/spec/unit/mongoid/matchers/gt_spec.rb +0 -39
  197. data/spec/unit/mongoid/matchers/gte_spec.rb +0 -49
  198. data/spec/unit/mongoid/matchers/in_spec.rb +0 -27
  199. data/spec/unit/mongoid/matchers/lt_spec.rb +0 -39
  200. data/spec/unit/mongoid/matchers/lte_spec.rb +0 -49
  201. data/spec/unit/mongoid/matchers/ne_spec.rb +0 -27
  202. data/spec/unit/mongoid/matchers/nin_spec.rb +0 -27
  203. data/spec/unit/mongoid/matchers/size_spec.rb +0 -27
  204. data/spec/unit/mongoid/matchers_spec.rb +0 -329
  205. data/spec/unit/mongoid/memoization_spec.rb +0 -75
  206. data/spec/unit/mongoid/named_scope_spec.rb +0 -123
  207. data/spec/unit/mongoid/observable_spec.rb +0 -46
  208. data/spec/unit/mongoid/paths_spec.rb +0 -124
  209. data/spec/unit/mongoid/scope_spec.rb +0 -240
  210. data/spec/unit/mongoid/state_spec.rb +0 -83
  211. data/spec/unit/mongoid/timestamps_spec.rb +0 -25
  212. data/spec/unit/mongoid/validations/associated_spec.rb +0 -103
  213. data/spec/unit/mongoid/validations/uniqueness_spec.rb +0 -47
  214. data/spec/unit/mongoid/validations_spec.rb +0 -190
  215. data/spec/unit/mongoid/versioning_spec.rb +0 -41
  216. data/spec/unit/mongoid_spec.rb +0 -46
@@ -1,30 +1,23 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
3
  module Associations #:nodoc
4
- module Proxy #:nodoc
5
- def self.included(base)
6
- base.class_eval do
7
- instance_methods.each do |method|
8
- undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$)/
9
- end
10
- include InstanceMethods
11
- end
4
+ class Proxy #:nodoc
5
+ instance_methods.each do |method|
6
+ undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$)/
12
7
  end
13
- module InstanceMethods #:nodoc:
14
- attr_reader \
15
- :options,
16
- :target
8
+ attr_reader \
9
+ :options,
10
+ :target
17
11
 
18
- # Default behavior of method missing should be to delegate all calls
19
- # to the target of the proxy. This can be overridden in special cases.
20
- def method_missing(name, *args, &block)
21
- @target.send(name, *args, &block)
22
- end
12
+ # Default behavior of method missing should be to delegate all calls
13
+ # to the target of the proxy. This can be overridden in special cases.
14
+ def method_missing(name, *args, &block)
15
+ @target.send(name, *args, &block)
16
+ end
23
17
 
24
- # If anonymous extensions are added this will take care of them.
25
- def extends(options)
26
- extend Module.new(&options.extension) if options.extension?
27
- end
18
+ # If anonymous extensions are added this will take care of them.
19
+ def extends(options)
20
+ extend Module.new(&options.extension) if options.extension?
28
21
  end
29
22
  end
30
23
  end
@@ -41,6 +41,7 @@ module Mongoid #:nodoc:
41
41
  send("#{key}=", value)
42
42
  end
43
43
  end
44
+ setup_modifications
44
45
  end
45
46
 
46
47
  # Read a value from the +Document+ attributes. If the value does not exist
@@ -55,7 +56,7 @@ module Mongoid #:nodoc:
55
56
  # <tt>person.read_attribute(:title)</tt>
56
57
  def read_attribute(name)
57
58
  access = name.to_s
58
- fields[access].get(@attributes[access])
59
+ accessed(access, fields[access].get(@attributes[access]))
59
60
  end
60
61
 
61
62
  # Remove a value from the +Document+ attributes. If the value does not exist
@@ -69,7 +70,8 @@ module Mongoid #:nodoc:
69
70
  #
70
71
  # <tt>person.remove_attribute(:title)</tt>
71
72
  def remove_attribute(name)
72
- @attributes.delete(name.to_s)
73
+ access = name.to_s
74
+ modify(access, @attributes.delete(name.to_s), nil)
73
75
  end
74
76
 
75
77
  # Returns the object type. This corresponds to the name of the class that
@@ -101,8 +103,8 @@ module Mongoid #:nodoc:
101
103
  # there is any.
102
104
  def write_attribute(name, value)
103
105
  access = name.to_s
104
- @attributes[access] = fields[access].set(value)
105
- notify unless id.blank?
106
+ modify(access, @attributes[access], fields[access].set(value))
107
+ notify if !id.blank? && new_record?
106
108
  end
107
109
 
108
110
  # Writes the supplied attributes +Hash+ to the +Document+. This will only
@@ -121,12 +123,23 @@ module Mongoid #:nodoc:
121
123
  # there is any.
122
124
  def write_attributes(attrs = nil)
123
125
  process(attrs || {})
124
- identify if id.blank?
125
- notify
126
+ identified = !id.blank?
127
+ if new_record? && !identified
128
+ identify; notify
129
+ end
126
130
  end
127
131
  alias :attributes= :write_attributes
128
132
 
129
133
  protected
134
+ # apply default values to attributes - calling procs as required
135
+ def default_attributes
136
+ default_values = defaults
137
+ default_values.each_pair do |key, val|
138
+ default_values[key] = val.call if val.respond_to?(:call)
139
+ end
140
+ default_values || {}
141
+ end
142
+
130
143
  # Return true if dynamic field setting is enabled.
131
144
  def set_allowed?(key)
132
145
  Mongoid.allow_dynamic_fields && !respond_to?("#{key}=")
@@ -143,10 +156,17 @@ module Mongoid #:nodoc:
143
156
  end
144
157
  end
145
158
 
159
+ # Used when supplying a :limit as an option to accepts_nested_attributes_for
160
+ def limit(attributes, name, options)
161
+ raise Mongoid::Errors::TooManyNestedAttributeRecords.new(name, options[:limit]) if options[:limit] && attributes.size > options[:limit]
162
+ end
163
+
146
164
  # Return true if writing to the given field is allowed
147
165
  def write_allowed?(key)
148
- return true unless fields[key.to_s]
149
- fields[key.to_s].accessible?
166
+ name = key.to_s
167
+ existing = fields[name]
168
+ return true unless existing
169
+ existing.accessible?
150
170
  end
151
171
  end
152
172
 
@@ -158,8 +178,8 @@ module Mongoid #:nodoc:
158
178
  #
159
179
  # class Person
160
180
  # include Mongoid::Document
161
- # embed_one :name
162
- # embed_many :addresses
181
+ # embeds_one :name
182
+ # embeds_many :addresses
163
183
  #
164
184
  # accepts_nested_attributes_for :name, :addresses
165
185
  # end
@@ -169,12 +189,13 @@ module Mongoid #:nodoc:
169
189
  associations.each do |name|
170
190
  define_method("#{name}_attributes=") do |attrs|
171
191
  reject(attrs, options)
192
+ limit(attrs, name, options)
172
193
  association = send(name)
173
194
  if association
174
- update(association, true)
175
- association.nested_build(attrs)
195
+ # observe(association, true)
196
+ association.nested_build(attrs, options)
176
197
  else
177
- send("build_#{name}", attrs)
198
+ send("build_#{name}", attrs, options)
178
199
  end
179
200
  end
180
201
  end
@@ -11,8 +11,7 @@ module Mongoid #:nodoc:
11
11
  :destroy,
12
12
  :save,
13
13
  :update,
14
- :validate,
15
- :terminator => false
14
+ :validate
16
15
  end
17
16
  end
18
17
  end
@@ -1,13 +1,12 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/collections/operations"
3
3
  require "mongoid/collections/cyclic_iterator"
4
- require "mongoid/collections/mimic"
5
4
  require "mongoid/collections/master"
6
5
  require "mongoid/collections/slaves"
7
6
 
8
7
  module Mongoid #:nodoc
8
+ # The Mongoid wrapper to the Mongo Ruby driver's collection object.
9
9
  class Collection
10
- include Collections::Mimic
11
10
  attr_reader :counter, :name
12
11
 
13
12
  # All write operations should delegate to the master connection. These
@@ -16,7 +15,9 @@ module Mongoid #:nodoc
16
15
  # Example:
17
16
  #
18
17
  # <tt>collection.save({ :name => "Al" })</tt>
19
- proxy(:master, Collections::Operations::PROXIED)
18
+ Collections::Operations::PROXIED.each do |name|
19
+ define_method(name) { |*args| master.send(name, *args) }
20
+ end
20
21
 
21
22
  # Determines where to send the next read query. If the slaves are not
22
23
  # defined then send to master. If the read counter is under the configured
@@ -0,0 +1,41 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc
3
+ # The collections module is used for providing functionality around setting
4
+ # up and updating collections.
5
+ module Collections
6
+ extend ActiveSupport::Concern
7
+ included do
8
+ cattr_accessor :_collection, :collection_name
9
+ self.collection_name = self.name.collectionize
10
+ delegate :collection, :to => "self.class"
11
+ end
12
+
13
+ module ClassMethods #:nodoc:
14
+ # Returns the collection associated with this +Document+. If the
15
+ # document is embedded, there will be no collection associated
16
+ # with it.
17
+ #
18
+ # Returns: <tt>Mongo::Collection</tt>
19
+ def collection
20
+ raise Errors::InvalidCollection.new(self) if embedded?
21
+ self._collection || set_collection
22
+ add_indexes; self._collection
23
+ end
24
+
25
+ # Macro for setting the collection name to store in.
26
+ #
27
+ # Example:
28
+ #
29
+ # <tt>Person.store_in :populdation</tt>
30
+ def store_in(name)
31
+ self.collection_name = name.to_s
32
+ set_collection
33
+ end
34
+
35
+ protected
36
+ def set_collection
37
+ self._collection = Mongoid::Collection.new(self, self.collection_name)
38
+ end
39
+ end
40
+ end
41
+ end
@@ -2,7 +2,6 @@
2
2
  module Mongoid #:nodoc:
3
3
  module Collections #:nodoc:
4
4
  class Master
5
- include Mimic
6
5
 
7
6
  attr_reader :collection
8
7
 
@@ -12,7 +11,9 @@ module Mongoid #:nodoc:
12
11
  # Example:
13
12
  #
14
13
  # <tt>collection.save({ :name => "Al" })</tt>
15
- proxy(:collection, Operations::ALL)
14
+ Operations::ALL.each do |name|
15
+ define_method(name) { |*args| collection.send(name, *args) }
16
+ end
16
17
 
17
18
  # Create the new database writer. Will create a collection from the
18
19
  # master database.
@@ -2,7 +2,6 @@
2
2
  module Mongoid #:nodoc:
3
3
  module Collections #:nodoc:
4
4
  class Slaves
5
- include Mimic
6
5
 
7
6
  attr_reader :iterator
8
7
 
@@ -12,7 +11,9 @@ module Mongoid #:nodoc:
12
11
  # Example:
13
12
  #
14
13
  # <tt>collection.save({ :name => "Al" })</tt>
15
- proxy(:collection, Operations::READ)
14
+ Operations::READ.each do |name|
15
+ define_method(name) { |*args| collection.send(name, *args) }
16
+ end
16
17
 
17
18
  # Is the collection of slaves empty or not?
18
19
  #
@@ -8,10 +8,12 @@ module Mongoid #:nodoc
8
8
  include ActiveModel::Conversion
9
9
  include ActiveModel::Naming
10
10
  include ActiveModel::Serialization
11
+ include ActiveModel::Serializers::JSON
11
12
  include Mongoid::Associations
12
13
  include Mongoid::Attributes
13
14
  include Mongoid::Callbacks
14
- include Mongoid::Commands
15
+ include Mongoid::Collections
16
+ include Mongoid::Dirty
15
17
  include Mongoid::Extras
16
18
  include Mongoid::Fields
17
19
  include Mongoid::Indexes
@@ -19,6 +21,7 @@ module Mongoid #:nodoc
19
21
  include Mongoid::Memoization
20
22
  include Mongoid::Observable
21
23
  include Mongoid::Paths
24
+ include Mongoid::Persistence
22
25
  include Mongoid::State
23
26
  include Mongoid::Validations
24
27
  extend ActiveModel::Translation
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
+ require "uri"
3
+
2
4
  module Mongoid #:nodoc
3
5
  class Config #:nodoc
4
6
  include Singleton
@@ -8,23 +10,45 @@ module Mongoid #:nodoc
8
10
  :reconnect_time,
9
11
  :parameterize_keys,
10
12
  :persist_in_safe_mode,
11
- :persist_types,
12
13
  :raise_not_found_error,
13
- :use_object_ids
14
+ :use_object_ids,
15
+ :skip_version_check
14
16
 
15
17
  # Defaults the configuration options to true.
16
18
  def initialize
17
- @allow_dynamic_fields = true
18
- @parameterize_keys = true
19
- @persist_in_safe_mode = true
20
- @persist_types = true
21
- @raise_not_found_error = true
22
- @reconnect_time = 3
23
- @use_object_ids = false
19
+ reset
20
+ end
21
+
22
+ # Sets whether the times returned from the database are in UTC or local time.
23
+ # If you omit this setting, then times will be returned in
24
+ # the local time zone.
25
+ #
26
+ # Example:
27
+ #
28
+ # <tt>Config.use_utc = true</tt>
29
+ #
30
+ # Returns:
31
+ #
32
+ # A boolean
33
+ def use_utc=(value)
34
+ @use_utc = value || false
24
35
  end
25
36
 
26
- # Sets the Mongo::DB master database to be used. If the object trying to me
27
- # set is not a valid +Mongo::DB+, then an error will be raise.
37
+ # Returns whether times are return from the database in UTC. If
38
+ # this setting is false, then times will be returned in the local time zone.
39
+ #
40
+ # Example:
41
+ #
42
+ # <tt>Config.use_utc</tt>
43
+ #
44
+ # Returns:
45
+ #
46
+ # A boolean
47
+ attr_reader :use_utc
48
+ alias_method :use_utc?, :use_utc
49
+
50
+ # Sets the Mongo::DB master database to be used. If the object trying to be
51
+ # set is not a valid +Mongo::DB+, then an error will be raised.
28
52
  #
29
53
  # Example:
30
54
  #
@@ -34,7 +58,7 @@ module Mongoid #:nodoc
34
58
  #
35
59
  # The Master DB instance.
36
60
  def master=(db)
37
- raise Errors::InvalidDatabase.new(db) unless db.kind_of?(Mongo::DB)
61
+ check_database!(db)
38
62
  @master = db
39
63
  end
40
64
 
@@ -66,7 +90,10 @@ module Mongoid #:nodoc
66
90
  #
67
91
  # The slaves DB instances.
68
92
  def slaves=(dbs)
69
- dbs.each { |db| raise Errors::InvalidDatabase.new(db) unless db.kind_of?(Mongo::DB) }
93
+ return unless dbs
94
+ dbs.each do |db|
95
+ check_database!(db)
96
+ end
70
97
  @slaves = dbs
71
98
  end
72
99
 
@@ -82,5 +109,128 @@ module Mongoid #:nodoc
82
109
  def slaves
83
110
  @slaves
84
111
  end
112
+
113
+ # Return field names that could cause destructive things to happen if
114
+ # defined in a Mongoid::Document
115
+ #
116
+ # Example:
117
+ #
118
+ # <tt>Config.destructive_fields</tt>
119
+ #
120
+ # Returns:
121
+ #
122
+ # An array of bad field names.
123
+ def destructive_fields
124
+ @destructive_fields ||= lambda {
125
+ klass = Class.new do
126
+ include Mongoid::Document
127
+ end
128
+ klass.instance_methods(true).collect { |method| method.to_s }
129
+ }.call
130
+ end
131
+
132
+ # Configure mongoid from a hash that was usually parsed out of yml.
133
+ #
134
+ # Example:
135
+ #
136
+ # <tt>Mongoid::Config.instance.from_hash({})</tt>
137
+ def from_hash(settings)
138
+ _master(settings)
139
+ _slaves(settings)
140
+ settings.except("database").each_pair do |name, value|
141
+ send("#{name}=", value) if respond_to?(name)
142
+ end
143
+ end
144
+
145
+ # Reset the configuration options to the defaults.
146
+ #
147
+ # Example:
148
+ #
149
+ # <tt>config.reset</tt>
150
+ def reset
151
+ @allow_dynamic_fields = true
152
+ @parameterize_keys = true
153
+ @persist_in_safe_mode = true
154
+ @raise_not_found_error = true
155
+ @reconnect_time = 3
156
+ @use_object_ids = false
157
+ @skip_version_check = false
158
+ @time_zone = nil
159
+ end
160
+
161
+ protected
162
+
163
+ # Check if the database is valid and the correct version.
164
+ #
165
+ # Example:
166
+ #
167
+ # <tt>config.check_database!</tt>
168
+ def check_database!(database)
169
+ raise Errors::InvalidDatabase.new(database) unless database.kind_of?(Mongo::DB)
170
+ unless Mongoid.skip_version_check
171
+ version = database.connection.server_version
172
+ raise Errors::UnsupportedVersion.new(version) if version < Mongoid::MONGODB_VERSION
173
+ end
174
+ end
175
+
176
+ # Get a Rails logger or stdout logger.
177
+ #
178
+ # Example:
179
+ #
180
+ # <tt>config.logger</tt>
181
+ def logger
182
+ defined?(Rails) ? Rails.logger : Logger.new($stdout)
183
+ end
184
+
185
+ # Get a master database from settings.
186
+ #
187
+ # Example:
188
+ #
189
+ # <tt>config._master({}, "test")</tt>
190
+ def _master(settings)
191
+ mongo_uri = settings["uri"].present? ? URI.parse(settings["uri"]) : OpenStruct.new
192
+
193
+ name = settings["database"] || mongo_uri.path.to_s.sub("/", "")
194
+ host = settings["host"] || mongo_uri.host || "localhost"
195
+ port = settings["port"] || mongo_uri.port || 27017
196
+ username = settings["username"] || mongo_uri.user
197
+ password = settings["password"] || mongo_uri.password
198
+
199
+ connection = Mongo::Connection.new(host, port, :logger => logger)
200
+ if username || password
201
+ connection.add_auth(name, username, password)
202
+ connection.apply_saved_authentication
203
+ end
204
+ self.master = connection.db(name)
205
+ end
206
+
207
+ # Get a bunch-o-slaves from settings and names.
208
+ #
209
+ # Example:
210
+ #
211
+ # <tt>config._slaves({}, "test")</tt>
212
+ def _slaves(settings)
213
+ mongo_uri = settings["uri"].present? ? URI.parse(settings["uri"]) : OpenStruct.new
214
+ name = settings["database"] || mongo_uri.path.to_s.sub("/", "")
215
+ self.slaves = []
216
+ slaves = settings["slaves"]
217
+ slaves.to_a.each do |slave|
218
+ slave_uri = slave["uri"].present? ? URI.parse(slave["uri"]) : OpenStruct.new
219
+ slave_username = slave["username"] || slave_uri.user
220
+ slave_password = slave["password"] || slave_uri.password
221
+
222
+ slave_connection = Mongo::Connection.new(
223
+ slave["host"] || slave_uri.host || "localhost",
224
+ slave["port"] || slave_uri.port,
225
+ :slave_ok => true
226
+ )
227
+
228
+ if slave_username || slave_password
229
+ slave_connection.add_auth(name, slave_username, slave_password)
230
+ slave_connection.apply_saved_authentication
231
+ end
232
+ self.slaves << slave_connection.db(name)
233
+ end
234
+ end
85
235
  end
86
236
  end