mongoid 1.9.5 → 2.0.0.alpha

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 (213) hide show
  1. data/.gitignore +6 -0
  2. data/.watchr +29 -0
  3. data/Rakefile +52 -0
  4. data/VERSION +1 -0
  5. data/caliper.yml +4 -0
  6. data/lib/mongoid.rb +20 -9
  7. data/lib/mongoid/associations.rb +100 -123
  8. data/lib/mongoid/associations/belongs_to_related.rb +3 -2
  9. data/lib/mongoid/associations/{embeds_many.rb → embed_many.rb} +29 -90
  10. data/lib/mongoid/associations/{embeds_one.rb → embed_one.rb} +7 -8
  11. data/lib/mongoid/associations/embedded_in.rb +4 -12
  12. data/lib/mongoid/associations/has_many_related.rb +4 -52
  13. data/lib/mongoid/associations/has_one_related.rb +4 -8
  14. data/lib/mongoid/associations/meta_data.rb +1 -2
  15. data/lib/mongoid/associations/options.rb +1 -6
  16. data/lib/mongoid/associations/proxy.rb +21 -14
  17. data/lib/mongoid/attributes.rb +13 -33
  18. data/lib/mongoid/callbacks.rb +11 -16
  19. data/lib/mongoid/collection.rb +3 -4
  20. data/lib/mongoid/collections/master.rb +2 -3
  21. data/lib/mongoid/collections/mimic.rb +46 -0
  22. data/lib/mongoid/collections/slaves.rb +2 -3
  23. data/lib/mongoid/commands.rb +161 -0
  24. data/lib/mongoid/commands/create.rb +19 -0
  25. data/lib/mongoid/commands/delete.rb +16 -0
  26. data/lib/mongoid/commands/delete_all.rb +23 -0
  27. data/lib/mongoid/commands/deletion.rb +18 -0
  28. data/lib/mongoid/commands/destroy.rb +17 -0
  29. data/lib/mongoid/commands/destroy_all.rb +23 -0
  30. data/lib/mongoid/commands/save.rb +29 -0
  31. data/lib/mongoid/components.rb +6 -4
  32. data/lib/mongoid/config.rb +15 -134
  33. data/lib/mongoid/contexts.rb +1 -1
  34. data/lib/mongoid/contexts/enumerable.rb +1 -1
  35. data/lib/mongoid/contexts/mongo.rb +1 -1
  36. data/lib/mongoid/contexts/paging.rb +2 -10
  37. data/lib/mongoid/criterion/inclusion.rb +0 -17
  38. data/lib/mongoid/criterion/optional.rb +1 -1
  39. data/lib/mongoid/cursor.rb +1 -0
  40. data/lib/mongoid/document.rb +45 -49
  41. data/lib/mongoid/errors.rb +1 -32
  42. data/lib/mongoid/extensions.rb +10 -12
  43. data/lib/mongoid/extensions/array/conversions.rb +6 -8
  44. data/lib/mongoid/extensions/big_decimal/conversions.rb +2 -2
  45. data/lib/mongoid/extensions/boolean/conversions.rb +2 -8
  46. data/lib/mongoid/extensions/date/conversions.rb +4 -13
  47. data/lib/mongoid/extensions/datetime/conversions.rb +6 -1
  48. data/lib/mongoid/extensions/float/conversions.rb +1 -5
  49. data/lib/mongoid/extensions/hash/assimilation.rb +3 -12
  50. data/lib/mongoid/extensions/hash/conversions.rb +4 -34
  51. data/lib/mongoid/extensions/integer/conversions.rb +1 -5
  52. data/lib/mongoid/extensions/nil/assimilation.rb +0 -4
  53. data/lib/mongoid/extensions/object/conversions.rb +2 -8
  54. data/lib/mongoid/extensions/objectid/conversions.rb +1 -1
  55. data/lib/mongoid/extensions/string/conversions.rb +1 -1
  56. data/lib/mongoid/extensions/symbol/inflections.rb +1 -1
  57. data/lib/mongoid/extensions/time/conversions.rb +18 -0
  58. data/lib/mongoid/factory.rb +1 -2
  59. data/lib/mongoid/field.rb +2 -9
  60. data/lib/mongoid/fields.rb +7 -11
  61. data/lib/mongoid/finders.rb +2 -2
  62. data/lib/mongoid/identity.rb +4 -4
  63. data/lib/mongoid/indexes.rb +7 -10
  64. data/lib/mongoid/memoization.rb +2 -8
  65. data/lib/mongoid/named_scope.rb +5 -0
  66. data/lib/mongoid/observable.rb +1 -1
  67. data/lib/mongoid/paths.rb +22 -30
  68. data/lib/mongoid/state.rb +21 -28
  69. data/lib/mongoid/timestamps.rb +1 -1
  70. data/lib/mongoid/validations.rb +51 -0
  71. data/lib/mongoid/validations/associated.rb +32 -0
  72. data/lib/mongoid/validations/locale/en.yml +4 -0
  73. data/lib/mongoid/validations/uniqueness.rb +22 -0
  74. data/lib/mongoid/versioning.rb +1 -2
  75. data/mongoid.gemspec +408 -0
  76. data/perf/benchmark.rb +77 -0
  77. data/spec/integration/mongoid/associations_spec.rb +340 -0
  78. data/spec/integration/mongoid/attributes_spec.rb +22 -0
  79. data/spec/integration/mongoid/commands_spec.rb +227 -0
  80. data/spec/integration/mongoid/contexts/enumerable_spec.rb +33 -0
  81. data/spec/integration/mongoid/criteria_spec.rb +272 -0
  82. data/spec/integration/mongoid/document_spec.rb +650 -0
  83. data/spec/integration/mongoid/extensions_spec.rb +22 -0
  84. data/spec/integration/mongoid/finders_spec.rb +119 -0
  85. data/spec/integration/mongoid/inheritance_spec.rb +137 -0
  86. data/spec/integration/mongoid/named_scope_spec.rb +46 -0
  87. data/spec/models/address.rb +39 -0
  88. data/spec/models/animal.rb +6 -0
  89. data/spec/models/callbacks.rb +18 -0
  90. data/spec/models/comment.rb +8 -0
  91. data/spec/models/country_code.rb +6 -0
  92. data/spec/models/employer.rb +5 -0
  93. data/spec/models/game.rb +7 -0
  94. data/spec/models/inheritance.rb +56 -0
  95. data/spec/models/location.rb +5 -0
  96. data/spec/models/mixed_drink.rb +4 -0
  97. data/spec/models/name.rb +13 -0
  98. data/spec/models/namespacing.rb +11 -0
  99. data/spec/models/patient.rb +4 -0
  100. data/spec/models/person.rb +99 -0
  101. data/spec/models/pet.rb +7 -0
  102. data/spec/models/pet_owner.rb +6 -0
  103. data/spec/models/phone.rb +7 -0
  104. data/spec/models/post.rb +15 -0
  105. data/spec/models/translation.rb +5 -0
  106. data/spec/models/vet_visit.rb +5 -0
  107. data/spec/spec.opts +3 -0
  108. data/spec/spec_helper.rb +31 -0
  109. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +145 -0
  110. data/spec/unit/mongoid/associations/embed_many_spec.rb +516 -0
  111. data/spec/unit/mongoid/associations/embed_one_spec.rb +282 -0
  112. data/spec/unit/mongoid/associations/embedded_in_spec.rb +193 -0
  113. data/spec/unit/mongoid/associations/has_many_related_spec.rb +418 -0
  114. data/spec/unit/mongoid/associations/has_one_related_spec.rb +179 -0
  115. data/spec/unit/mongoid/associations/meta_data_spec.rb +88 -0
  116. data/spec/unit/mongoid/associations/options_spec.rb +192 -0
  117. data/spec/unit/mongoid/associations_spec.rb +595 -0
  118. data/spec/unit/mongoid/attributes_spec.rb +507 -0
  119. data/spec/unit/mongoid/callbacks_spec.rb +55 -0
  120. data/spec/unit/mongoid/collection_spec.rb +187 -0
  121. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +75 -0
  122. data/spec/unit/mongoid/collections/master_spec.rb +41 -0
  123. data/spec/unit/mongoid/collections/mimic_spec.rb +43 -0
  124. data/spec/unit/mongoid/collections/slaves_spec.rb +81 -0
  125. data/spec/unit/mongoid/commands/create_spec.rb +31 -0
  126. data/spec/unit/mongoid/commands/delete_all_spec.rb +58 -0
  127. data/spec/unit/mongoid/commands/delete_spec.rb +38 -0
  128. data/spec/unit/mongoid/commands/destroy_all_spec.rb +21 -0
  129. data/spec/unit/mongoid/commands/destroy_spec.rb +51 -0
  130. data/spec/unit/mongoid/commands/save_spec.rb +107 -0
  131. data/spec/unit/mongoid/commands_spec.rb +270 -0
  132. data/spec/unit/mongoid/config_spec.rb +172 -0
  133. data/spec/unit/mongoid/contexts/enumerable_spec.rb +421 -0
  134. data/spec/unit/mongoid/contexts/mongo_spec.rb +682 -0
  135. data/spec/unit/mongoid/contexts_spec.rb +25 -0
  136. data/spec/unit/mongoid/criteria_spec.rb +824 -0
  137. data/spec/unit/mongoid/criterion/complex_spec.rb +19 -0
  138. data/spec/unit/mongoid/criterion/exclusion_spec.rb +91 -0
  139. data/spec/unit/mongoid/criterion/inclusion_spec.rb +219 -0
  140. data/spec/unit/mongoid/criterion/optional_spec.rb +319 -0
  141. data/spec/unit/mongoid/cursor_spec.rb +74 -0
  142. data/spec/unit/mongoid/deprecation_spec.rb +24 -0
  143. data/spec/unit/mongoid/document_spec.rb +818 -0
  144. data/spec/unit/mongoid/errors_spec.rb +103 -0
  145. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +50 -0
  146. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +24 -0
  147. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +35 -0
  148. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +20 -0
  149. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +22 -0
  150. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +22 -0
  151. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +49 -0
  152. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +102 -0
  153. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +67 -0
  154. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +61 -0
  155. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +184 -0
  156. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +46 -0
  157. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +21 -0
  158. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +17 -0
  159. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +14 -0
  160. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +61 -0
  161. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +24 -0
  162. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +57 -0
  163. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +34 -0
  164. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +17 -0
  165. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +208 -0
  166. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +91 -0
  167. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +70 -0
  168. data/spec/unit/mongoid/extras_spec.rb +102 -0
  169. data/spec/unit/mongoid/factory_spec.rb +31 -0
  170. data/spec/unit/mongoid/field_spec.rb +143 -0
  171. data/spec/unit/mongoid/fields_spec.rb +181 -0
  172. data/spec/unit/mongoid/finders_spec.rb +404 -0
  173. data/spec/unit/mongoid/identity_spec.rb +109 -0
  174. data/spec/unit/mongoid/indexes_spec.rb +93 -0
  175. data/spec/unit/mongoid/javascript_spec.rb +48 -0
  176. data/spec/unit/mongoid/matchers/all_spec.rb +27 -0
  177. data/spec/unit/mongoid/matchers/default_spec.rb +27 -0
  178. data/spec/unit/mongoid/matchers/exists_spec.rb +56 -0
  179. data/spec/unit/mongoid/matchers/gt_spec.rb +39 -0
  180. data/spec/unit/mongoid/matchers/gte_spec.rb +49 -0
  181. data/spec/unit/mongoid/matchers/in_spec.rb +27 -0
  182. data/spec/unit/mongoid/matchers/lt_spec.rb +39 -0
  183. data/spec/unit/mongoid/matchers/lte_spec.rb +49 -0
  184. data/spec/unit/mongoid/matchers/ne_spec.rb +27 -0
  185. data/spec/unit/mongoid/matchers/nin_spec.rb +27 -0
  186. data/spec/unit/mongoid/matchers/size_spec.rb +27 -0
  187. data/spec/unit/mongoid/matchers_spec.rb +329 -0
  188. data/spec/unit/mongoid/memoization_spec.rb +75 -0
  189. data/spec/unit/mongoid/named_scope_spec.rb +123 -0
  190. data/spec/unit/mongoid/observable_spec.rb +46 -0
  191. data/spec/unit/mongoid/paths_spec.rb +124 -0
  192. data/spec/unit/mongoid/scope_spec.rb +240 -0
  193. data/spec/unit/mongoid/state_spec.rb +83 -0
  194. data/spec/unit/mongoid/timestamps_spec.rb +25 -0
  195. data/spec/unit/mongoid/validations/associated_spec.rb +103 -0
  196. data/spec/unit/mongoid/validations/uniqueness_spec.rb +47 -0
  197. data/spec/unit/mongoid/validations_spec.rb +190 -0
  198. data/spec/unit/mongoid/versioning_spec.rb +41 -0
  199. data/spec/unit/mongoid_spec.rb +46 -0
  200. metadata +316 -110
  201. data/lib/mongoid/collections.rb +0 -41
  202. data/lib/mongoid/concern.rb +0 -31
  203. data/lib/mongoid/dirty.rb +0 -253
  204. data/lib/mongoid/extensions/time_conversions.rb +0 -35
  205. data/lib/mongoid/persistence.rb +0 -222
  206. data/lib/mongoid/persistence/command.rb +0 -39
  207. data/lib/mongoid/persistence/insert.rb +0 -50
  208. data/lib/mongoid/persistence/insert_embedded.rb +0 -38
  209. data/lib/mongoid/persistence/remove.rb +0 -39
  210. data/lib/mongoid/persistence/remove_all.rb +0 -37
  211. data/lib/mongoid/persistence/remove_embedded.rb +0 -50
  212. data/lib/mongoid/persistence/update.rb +0 -63
  213. data/lib/mongoid/version.rb +0 -4
@@ -1,23 +1,30 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
3
  module Associations #:nodoc
4
- class Proxy #:nodoc
5
- instance_methods.each do |method|
6
- undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$)/
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
7
12
  end
8
- attr_reader \
9
- :options,
10
- :target
13
+ module InstanceMethods #:nodoc:
14
+ attr_reader \
15
+ :options,
16
+ :target
11
17
 
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
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
17
23
 
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?
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
21
28
  end
22
29
  end
23
30
  end
@@ -1,12 +1,7 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Attributes
4
- def self.included(base)
5
- base.class_eval do
6
- include InstanceMethods
7
- extend ClassMethods
8
- end
9
- end
4
+ extend ActiveSupport::Concern
10
5
  module InstanceMethods
11
6
  # Get the id associated with this object. This will pull the _id value out
12
7
  # of the attributes +Hash+.
@@ -46,7 +41,6 @@ module Mongoid #:nodoc:
46
41
  send("#{key}=", value)
47
42
  end
48
43
  end
49
- setup_modifications
50
44
  end
51
45
 
52
46
  # Read a value from the +Document+ attributes. If the value does not exist
@@ -61,7 +55,7 @@ module Mongoid #:nodoc:
61
55
  # <tt>person.read_attribute(:title)</tt>
62
56
  def read_attribute(name)
63
57
  access = name.to_s
64
- accessed(access, fields[access].get(@attributes[access]))
58
+ fields[access].get(@attributes[access])
65
59
  end
66
60
 
67
61
  # Remove a value from the +Document+ attributes. If the value does not exist
@@ -75,8 +69,7 @@ module Mongoid #:nodoc:
75
69
  #
76
70
  # <tt>person.remove_attribute(:title)</tt>
77
71
  def remove_attribute(name)
78
- access = name.to_s
79
- modify(access, @attributes.delete(access), nil)
72
+ @attributes.delete(name.to_s)
80
73
  end
81
74
 
82
75
  # Returns the object type. This corresponds to the name of the class that
@@ -108,8 +101,8 @@ module Mongoid #:nodoc:
108
101
  # there is any.
109
102
  def write_attribute(name, value)
110
103
  access = name.to_s
111
- modify(access, @attributes[access], fields[access].set(value))
112
- notify if !id.blank? && new_record?
104
+ @attributes[access] = fields[access].set(value)
105
+ notify unless id.blank?
113
106
  end
114
107
 
115
108
  # Writes the supplied attributes +Hash+ to the +Document+. This will only
@@ -128,23 +121,12 @@ module Mongoid #:nodoc:
128
121
  # there is any.
129
122
  def write_attributes(attrs = nil)
130
123
  process(attrs || {})
131
- identified = !id.blank?
132
- if new_record? && !identified
133
- identify; notify
134
- end
124
+ identify if id.blank?
125
+ notify
135
126
  end
136
- alias :attributes= write_attributes
127
+ alias :attributes= :write_attributes
137
128
 
138
129
  protected
139
- # apply default values to attributes - calling procs as required
140
- def default_attributes
141
- default_values = defaults
142
- default_values.each_pair do |key, val|
143
- default_values[key] = val.call if val.respond_to?(:call)
144
- end
145
- default_values || {}
146
- end
147
-
148
130
  # Return true if dynamic field setting is enabled.
149
131
  def set_allowed?(key)
150
132
  Mongoid.allow_dynamic_fields && !respond_to?("#{key}=")
@@ -163,10 +145,8 @@ module Mongoid #:nodoc:
163
145
 
164
146
  # Return true if writing to the given field is allowed
165
147
  def write_allowed?(key)
166
- name = key.to_s
167
- existing = fields[name]
168
- return true unless existing
169
- existing.accessible?
148
+ return true unless fields[key.to_s]
149
+ fields[key.to_s].accessible?
170
150
  end
171
151
  end
172
152
 
@@ -178,8 +158,8 @@ module Mongoid #:nodoc:
178
158
  #
179
159
  # class Person
180
160
  # include Mongoid::Document
181
- # embeds_one :name
182
- # embeds_many :addresses
161
+ # embed_one :name
162
+ # embed_many :addresses
183
163
  #
184
164
  # accepts_nested_attributes_for :name, :addresses
185
165
  # end
@@ -191,7 +171,7 @@ module Mongoid #:nodoc:
191
171
  reject(attrs, options)
192
172
  association = send(name)
193
173
  if association
194
- observe(association, true)
174
+ update(association, true)
195
175
  association.nested_build(attrs)
196
176
  else
197
177
  send("build_#{name}", attrs)
@@ -1,23 +1,18 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Callbacks
4
- def self.included(base)
5
- base.class_eval do
6
- include ActiveSupport::Callbacks
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ extend ActiveModel::Callbacks
7
7
 
8
- # Define all the callbacks that are accepted by the document.
9
- define_callbacks \
10
- :before_create,
11
- :after_create,
12
- :before_destroy,
13
- :after_destroy,
14
- :before_save,
15
- :after_save,
16
- :before_update,
17
- :after_update,
18
- :before_validation,
19
- :after_validation
20
- end
8
+ # Define all the callbacks that are accepted by the document.
9
+ define_model_callbacks \
10
+ :create,
11
+ :destroy,
12
+ :save,
13
+ :update,
14
+ :validate,
15
+ :terminator => false
21
16
  end
22
17
  end
23
18
  end
@@ -1,12 +1,13 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/collections/operations"
3
3
  require "mongoid/collections/cyclic_iterator"
4
+ require "mongoid/collections/mimic"
4
5
  require "mongoid/collections/master"
5
6
  require "mongoid/collections/slaves"
6
7
 
7
8
  module Mongoid #:nodoc
8
- # The Mongoid wrapper to the Mongo Ruby driver's collection object.
9
9
  class Collection
10
+ include Collections::Mimic
10
11
  attr_reader :counter, :name
11
12
 
12
13
  # All write operations should delegate to the master connection. These
@@ -15,9 +16,7 @@ module Mongoid #:nodoc
15
16
  # Example:
16
17
  #
17
18
  # <tt>collection.save({ :name => "Al" })</tt>
18
- Collections::Operations::PROXIED.each do |name|
19
- define_method(name) { |*args| master.send(name, *args) }
20
- end
19
+ proxy(:master, Collections::Operations::PROXIED)
21
20
 
22
21
  # Determines where to send the next read query. If the slaves are not
23
22
  # defined then send to master. If the read counter is under the configured
@@ -2,6 +2,7 @@
2
2
  module Mongoid #:nodoc:
3
3
  module Collections #:nodoc:
4
4
  class Master
5
+ include Mimic
5
6
 
6
7
  attr_reader :collection
7
8
 
@@ -11,9 +12,7 @@ module Mongoid #:nodoc:
11
12
  # Example:
12
13
  #
13
14
  # <tt>collection.save({ :name => "Al" })</tt>
14
- Operations::ALL.each do |name|
15
- define_method(name) { |*args| collection.send(name, *args) }
16
- end
15
+ proxy(:collection, Operations::ALL)
17
16
 
18
17
  # Create the new database writer. Will create a collection from the
19
18
  # master database.
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Collections #:nodoc:
4
+ module Mimic #:nodoc:
5
+ def self.included(base)
6
+ base.class_eval do
7
+ include InstanceMethods
8
+ extend ClassMethods
9
+ end
10
+ end
11
+
12
+ module InstanceMethods #:nodoc:
13
+ # Retry the supplied operation until the reconnect time has expired,
14
+ # defined in the mongoid Config module.
15
+ #
16
+ # Example:
17
+ #
18
+ # <tt>master.attempt(operation)</tt>
19
+ def attempt(operation, start)
20
+ begin
21
+ elapsed = (Time.now - start)
22
+ operation.call
23
+ rescue Mongo::ConnectionFailure => error
24
+ (elapsed < Mongoid.reconnect_time) ? retry : (raise error)
25
+ end
26
+ end
27
+ end
28
+
29
+ module ClassMethods #:nodoc:
30
+ # Proxy all the supplied operations to the internal collection or target.
31
+ #
32
+ # Example:
33
+ #
34
+ # <tt>proxy Operations::ALL, :collection</tt>
35
+ def proxy(target, operations)
36
+ operations.each do |name|
37
+ define_method(name) do |*args|
38
+ operation = lambda { send(target).send(name, *args) }
39
+ attempt(operation, Time.now)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -2,6 +2,7 @@
2
2
  module Mongoid #:nodoc:
3
3
  module Collections #:nodoc:
4
4
  class Slaves
5
+ include Mimic
5
6
 
6
7
  attr_reader :iterator
7
8
 
@@ -11,9 +12,7 @@ module Mongoid #:nodoc:
11
12
  # Example:
12
13
  #
13
14
  # <tt>collection.save({ :name => "Al" })</tt>
14
- Operations::READ.each do |name|
15
- define_method(name) { |*args| collection.send(name, *args) }
16
- end
15
+ proxy(:collection, Operations::READ)
17
16
 
18
17
  # Is the collection of slaves empty or not?
19
18
  #
@@ -0,0 +1,161 @@
1
+ # encoding: utf-8
2
+ require "mongoid/commands/create"
3
+ require "mongoid/commands/deletion"
4
+ require "mongoid/commands/delete"
5
+ require "mongoid/commands/delete_all"
6
+ require "mongoid/commands/destroy"
7
+ require "mongoid/commands/destroy_all"
8
+ require "mongoid/commands/save"
9
+
10
+ module Mongoid #:nodoc:
11
+
12
+ # This module is included in the +Document+ to provide all the persistence
13
+ # methods required on the +Document+ object and class.
14
+ module Commands
15
+ extend ActiveSupport::Concern
16
+ module InstanceMethods
17
+
18
+ # Delete the +Document+ from the database. This method is an optimized
19
+ # delete that does not force any callbacks.
20
+ #
21
+ # Example:
22
+ #
23
+ # <tt>document.delete</tt>
24
+ #
25
+ # Returns: true unless an error occurs.
26
+ def delete
27
+ Delete.execute(self)
28
+ end
29
+
30
+ # Destroy the +Document+. This will delete the document from the database
31
+ # and run the before and after destroy callbacks.
32
+ #
33
+ # Example:
34
+ #
35
+ # <tt>document.destroy</tt>
36
+ #
37
+ # Returns: true unless an error occurs.
38
+ def destroy
39
+ Destroy.execute(self)
40
+ end
41
+
42
+ # Save the +Document+. If the document is new, then the before and after
43
+ # create callbacks will get executed as well as the save callbacks.
44
+ # Otherwise only the save callbacks will run.
45
+ #
46
+ # Options:
47
+ #
48
+ # validate: Run validations or not. Defaults to true.
49
+ #
50
+ # Example:
51
+ #
52
+ # <tt>document.save # save with validations</tt>
53
+ # <tt>document.save(false) # save without validations</tt>
54
+ #
55
+ # Returns: true if validation passes, false if not.
56
+ def save(validate = true)
57
+ save = lambda { Save.execute(self, validate) }
58
+ new_record? ? run_callbacks(:create, &save) : save.call
59
+ end
60
+
61
+ # Save the +Document+, dangerously. Before and after save callbacks will
62
+ # get run. If validation fails an error will get raised.
63
+ #
64
+ # Example:
65
+ #
66
+ # <tt>document.save!</tt>
67
+ #
68
+ # Returns: true if validation passes
69
+ def save!
70
+ save(true) || (raise Errors::Validations.new(self.errors))
71
+ end
72
+
73
+ # Update the document attributes and persist the document to the
74
+ # database. Will delegate to save with all callbacks.
75
+ #
76
+ # Example:
77
+ #
78
+ # <tt>document.update_attributes(:title => "Test")</tt>
79
+ def update_attributes(attrs = {})
80
+ set_attributes(attrs); save
81
+ end
82
+
83
+ # Update the document attributes and persist the document to the
84
+ # database. Will delegate to save!
85
+ #
86
+ # Example:
87
+ #
88
+ # <tt>document.update_attributes!(:title => "Test")</tt>
89
+ def update_attributes!(attrs = {})
90
+ set_attributes(attrs); save!
91
+ end
92
+
93
+ protected
94
+ def set_attributes(attrs = {})
95
+ run_callbacks(:update) { write_attributes(attrs) }
96
+ end
97
+
98
+ end
99
+
100
+ module ClassMethods
101
+
102
+ # Create a new +Document+. This will instantiate a new document and save
103
+ # it in a single call. Will always return the document whether save
104
+ # passed or not.
105
+ #
106
+ # Example:
107
+ #
108
+ # <tt>Person.create(:title => "Mr")</tt>
109
+ #
110
+ # Returns: the +Document+.
111
+ def create(attributes = {})
112
+ document = new(attributes)
113
+ Create.execute(document)
114
+ document
115
+ end
116
+
117
+ # Create a new +Document+. This will instantiate a new document and save
118
+ # it in a single call. Will always return the document whether save
119
+ # passed or not. Will raise an error if validation fails.
120
+ #
121
+ # Example:
122
+ #
123
+ # <tt>Person.create!(:title => "Mr")</tt>
124
+ #
125
+ # Returns: the +Document+.
126
+ def create!(attributes = {})
127
+ document = Create.execute(new(attributes), true)
128
+ raise Errors::Validations.new(document.errors) unless document.errors.empty?
129
+ document
130
+ end
131
+
132
+ # Delete all documents given the supplied conditions. If no conditions
133
+ # are passed, the entire collection will be dropped for performance
134
+ # benefits. Does not fire any callbacks.
135
+ #
136
+ # Example:
137
+ #
138
+ # <tt>Person.delete_all(:conditions => { :title => "Sir" })</tt>
139
+ # <tt>Person.delete_all</tt>
140
+ #
141
+ # Returns: true or raises an error.
142
+ def delete_all(conditions = {})
143
+ DeleteAll.execute(self, conditions)
144
+ end
145
+
146
+ # Delete all documents given the supplied conditions. If no conditions
147
+ # are passed, the entire collection will be dropped for performance
148
+ # benefits. Fires the destroy callbacks if conditions were passed.
149
+ #
150
+ # Example:
151
+ #
152
+ # <tt>Person.destroy_all(:conditions => { :title => "Sir" })</tt>
153
+ # <tt>Person.destroy_all</tt>
154
+ #
155
+ # Returns: true or raises an error.
156
+ def destroy_all(conditions = {})
157
+ DestroyAll.execute(self, conditions)
158
+ end
159
+ end
160
+ end
161
+ end