mongoid 2.0.0.beta.20 → 2.0.0.rc.1

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 (134) hide show
  1. data/README.rdoc +8 -0
  2. data/Rakefile +51 -0
  3. data/lib/config/locales/nl.yml +39 -0
  4. data/lib/config/locales/ro.yml +1 -1
  5. data/lib/mongoid.rb +17 -17
  6. data/lib/mongoid/atomicity.rb +54 -22
  7. data/lib/mongoid/attributes.rb +145 -125
  8. data/lib/mongoid/callbacks.rb +7 -2
  9. data/lib/mongoid/collection.rb +49 -32
  10. data/lib/mongoid/collections.rb +0 -1
  11. data/lib/mongoid/components.rb +34 -29
  12. data/lib/mongoid/config.rb +207 -193
  13. data/lib/mongoid/config/database.rb +167 -0
  14. data/lib/mongoid/contexts.rb +2 -5
  15. data/lib/mongoid/contexts/enumerable.rb +30 -4
  16. data/lib/mongoid/contexts/ids.rb +2 -2
  17. data/lib/mongoid/contexts/mongo.rb +30 -5
  18. data/lib/mongoid/copyable.rb +44 -0
  19. data/lib/mongoid/criteria.rb +110 -56
  20. data/lib/mongoid/criterion/creational.rb +34 -0
  21. data/lib/mongoid/criterion/destructive.rb +37 -0
  22. data/lib/mongoid/criterion/exclusion.rb +3 -1
  23. data/lib/mongoid/criterion/inclusion.rb +59 -64
  24. data/lib/mongoid/criterion/inspection.rb +22 -0
  25. data/lib/mongoid/criterion/optional.rb +42 -54
  26. data/lib/mongoid/criterion/selector.rb +9 -0
  27. data/lib/mongoid/default_scope.rb +28 -0
  28. data/lib/mongoid/deprecation.rb +5 -5
  29. data/lib/mongoid/dirty.rb +4 -5
  30. data/lib/mongoid/document.rb +161 -114
  31. data/lib/mongoid/extensions.rb +7 -11
  32. data/lib/mongoid/extensions/array/parentization.rb +2 -2
  33. data/lib/mongoid/extensions/date/conversions.rb +1 -1
  34. data/lib/mongoid/extensions/hash/conversions.rb +0 -23
  35. data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
  36. data/lib/mongoid/extensions/object/reflections.rb +17 -0
  37. data/lib/mongoid/extensions/object/yoda.rb +27 -0
  38. data/lib/mongoid/extensions/string/conversions.rb +23 -4
  39. data/lib/mongoid/extensions/time_conversions.rb +4 -4
  40. data/lib/mongoid/field.rb +30 -19
  41. data/lib/mongoid/fields.rb +15 -5
  42. data/lib/mongoid/finders.rb +19 -11
  43. data/lib/mongoid/hierarchy.rb +34 -28
  44. data/lib/mongoid/identity.rb +62 -20
  45. data/lib/mongoid/inspection.rb +58 -0
  46. data/lib/mongoid/matchers.rb +20 -0
  47. data/lib/mongoid/multi_database.rb +11 -0
  48. data/lib/mongoid/nested_attributes.rb +41 -0
  49. data/lib/mongoid/paranoia.rb +3 -4
  50. data/lib/mongoid/paths.rb +1 -1
  51. data/lib/mongoid/persistence.rb +89 -90
  52. data/lib/mongoid/persistence/command.rb +20 -4
  53. data/lib/mongoid/persistence/insert.rb +13 -11
  54. data/lib/mongoid/persistence/insert_embedded.rb +8 -6
  55. data/lib/mongoid/persistence/remove.rb +6 -4
  56. data/lib/mongoid/persistence/remove_all.rb +6 -4
  57. data/lib/mongoid/persistence/remove_embedded.rb +8 -6
  58. data/lib/mongoid/persistence/update.rb +12 -10
  59. data/lib/mongoid/railtie.rb +2 -2
  60. data/lib/mongoid/railties/database.rake +10 -9
  61. data/lib/mongoid/relations.rb +104 -0
  62. data/lib/mongoid/relations/accessors.rb +154 -0
  63. data/lib/mongoid/relations/auto_save.rb +34 -0
  64. data/lib/mongoid/relations/binding.rb +24 -0
  65. data/lib/mongoid/relations/bindings.rb +9 -0
  66. data/lib/mongoid/relations/bindings/embedded/in.rb +77 -0
  67. data/lib/mongoid/relations/bindings/embedded/many.rb +93 -0
  68. data/lib/mongoid/relations/bindings/embedded/one.rb +65 -0
  69. data/lib/mongoid/relations/bindings/referenced/in.rb +78 -0
  70. data/lib/mongoid/relations/bindings/referenced/many.rb +93 -0
  71. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +94 -0
  72. data/lib/mongoid/relations/bindings/referenced/one.rb +63 -0
  73. data/lib/mongoid/relations/builder.rb +41 -0
  74. data/lib/mongoid/relations/builders.rb +79 -0
  75. data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
  76. data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
  77. data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
  78. data/lib/mongoid/relations/builders/nested_attributes/many.rb +116 -0
  79. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  80. data/lib/mongoid/relations/builders/referenced/in.rb +32 -0
  81. data/lib/mongoid/relations/builders/referenced/many.rb +26 -0
  82. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
  83. data/lib/mongoid/relations/builders/referenced/one.rb +30 -0
  84. data/lib/mongoid/relations/cascading.rb +55 -0
  85. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  86. data/lib/mongoid/relations/cascading/destroy.rb +19 -0
  87. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  88. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  89. data/lib/mongoid/relations/cyclic.rb +97 -0
  90. data/lib/mongoid/relations/embedded/in.rb +172 -0
  91. data/lib/mongoid/relations/embedded/many.rb +450 -0
  92. data/lib/mongoid/relations/embedded/one.rb +169 -0
  93. data/lib/mongoid/relations/macros.rb +302 -0
  94. data/lib/mongoid/relations/many.rb +185 -0
  95. data/lib/mongoid/relations/metadata.rb +529 -0
  96. data/lib/mongoid/relations/nested_builder.rb +52 -0
  97. data/lib/mongoid/relations/one.rb +29 -0
  98. data/lib/mongoid/relations/polymorphic.rb +54 -0
  99. data/lib/mongoid/relations/proxy.rb +122 -0
  100. data/lib/mongoid/relations/referenced/in.rb +214 -0
  101. data/lib/mongoid/relations/referenced/many.rb +358 -0
  102. data/lib/mongoid/relations/referenced/many_to_many.rb +379 -0
  103. data/lib/mongoid/relations/referenced/one.rb +204 -0
  104. data/lib/mongoid/relations/reflections.rb +45 -0
  105. data/lib/mongoid/safe.rb +11 -1
  106. data/lib/mongoid/safety.rb +122 -97
  107. data/lib/mongoid/scope.rb +14 -9
  108. data/lib/mongoid/state.rb +37 -3
  109. data/lib/mongoid/timestamps.rb +11 -0
  110. data/lib/mongoid/validations.rb +42 -3
  111. data/lib/mongoid/validations/associated.rb +8 -5
  112. data/lib/mongoid/validations/uniqueness.rb +23 -2
  113. data/lib/mongoid/version.rb +1 -1
  114. data/lib/mongoid/versioning.rb +25 -16
  115. data/lib/rails/generators/mongoid/model/templates/model.rb +3 -1
  116. metadata +95 -80
  117. data/lib/mongoid/associations.rb +0 -364
  118. data/lib/mongoid/associations/embedded_in.rb +0 -74
  119. data/lib/mongoid/associations/embeds_many.rb +0 -299
  120. data/lib/mongoid/associations/embeds_one.rb +0 -111
  121. data/lib/mongoid/associations/foreign_key.rb +0 -35
  122. data/lib/mongoid/associations/meta_data.rb +0 -38
  123. data/lib/mongoid/associations/options.rb +0 -78
  124. data/lib/mongoid/associations/proxy.rb +0 -60
  125. data/lib/mongoid/associations/referenced_in.rb +0 -70
  126. data/lib/mongoid/associations/references_many.rb +0 -254
  127. data/lib/mongoid/associations/references_many_as_array.rb +0 -128
  128. data/lib/mongoid/associations/references_one.rb +0 -104
  129. data/lib/mongoid/extensions/array/accessors.rb +0 -17
  130. data/lib/mongoid/extensions/array/assimilation.rb +0 -26
  131. data/lib/mongoid/extensions/hash/accessors.rb +0 -42
  132. data/lib/mongoid/extensions/hash/assimilation.rb +0 -40
  133. data/lib/mongoid/extensions/nil/assimilation.rb +0 -17
  134. data/lib/mongoid/memoization.rb +0 -33
@@ -0,0 +1,204 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Referenced #:nodoc:
5
+
6
+ # This class defines the behaviour for all relations that are a
7
+ # one-to-one between documents in different collections.
8
+ class One < Relations::One
9
+
10
+ # Binds the base object to the inverse of the relation. This is so we
11
+ # are referenced to the actual objects themselves and dont hit the
12
+ # database twice when setting the relations up.
13
+ #
14
+ # This is called after first creating the relation, or if a new object
15
+ # is set on the relation.
16
+ #
17
+ # @example Bind the relation.
18
+ # person.game.bind(:continue => false)
19
+ #
20
+ # @param [ Hash ] options The options to bind with.
21
+ #
22
+ # @option options [ true, false ] :building Are we in build mode?
23
+ # @option options [ true, false ] :continue Continue binding the
24
+ # inverse?
25
+ #
26
+ # @since 2.0.0.rc.1
27
+ def bind(options = {})
28
+ binding.bind(options)
29
+ target.save if base.persisted? && !options[:building]
30
+ end
31
+
32
+ # Instantiate a new references_one relation. Will set the foreign key
33
+ # and the base on the inverse object.
34
+ #
35
+ # @example Create the new relation.
36
+ # Referenced::One.new(base, target, metadata)
37
+ #
38
+ # @param [ Document ] base The document this relation hangs off of.
39
+ # @param [ Document ] target The target (child) of the relation.
40
+ # @param [ Metadata ] metadata The relation's metadata.
41
+ def initialize(base, target, metadata)
42
+ init(base, target, metadata)
43
+ end
44
+
45
+ # Removes the association between the base document and the target
46
+ # document by deleting the foreign key and the reference, orphaning
47
+ # the target document in the process.
48
+ #
49
+ # @example Nullify the relation.
50
+ # person.game.nullify
51
+ #
52
+ # @since 2.0.0.rc.1
53
+ def nullify
54
+ target.send(metadata.foreign_key_setter, nil)
55
+ target.send(:remove_instance_variable, "@#{metadata.inverse(target)}")
56
+ base.send(:remove_instance_variable, "@#{metadata.name}")
57
+ target.save
58
+ end
59
+
60
+ # Unbinds the base object to the inverse of the relation. This occurs
61
+ # when setting a side of the relation to nil.
62
+ #
63
+ # Will delete the object if necessary.
64
+ #
65
+ # @example Unbind the relation.
66
+ # person.game.unbind(name, :continue => true)
67
+ #
68
+ # @param [ Document ] old_target The previous target of the relation.
69
+ # @param [ Hash ] options The options to bind with.
70
+ #
71
+ # @option options [ true, false ] :building Are we in build mode?
72
+ # @option options [ true, false ] :continue Continue binding the
73
+ # inverse?
74
+ #
75
+ # @since 2.0.0.rc.1
76
+ def unbind(old_target, options = {})
77
+ binding(old_target).unbind(options)
78
+ old_target.delete if base.persisted? && !old_target.destroyed?
79
+ end
80
+
81
+ private
82
+
83
+ # Instantiate the binding associated with this relation.
84
+ #
85
+ # @example Get the binding.
86
+ # relation.binding([ address ])
87
+ #
88
+ # @param [ Document ] new_target The new target of the relation.
89
+ #
90
+ # @return [ Binding ] The binding object.
91
+ def binding(new_target = nil)
92
+ Bindings::Referenced::One.new(base, new_target || target, metadata)
93
+ end
94
+
95
+ class << self
96
+
97
+ # Return the builder that is responsible for generating the documents
98
+ # that will be used by this relation.
99
+ #
100
+ # @example Get the builder.
101
+ # Referenced::One.builder(meta, object)
102
+ #
103
+ # @param [ Metadata ] meta The metadata of the relation.
104
+ # @param [ Document, Hash ] object A document or attributes to build
105
+ # with.
106
+ #
107
+ # @return [ Builder ] A new builder object.
108
+ #
109
+ # @since 2.0.0.rc.1
110
+ def builder(meta, object)
111
+ Builders::Referenced::One.new(meta, object)
112
+ end
113
+
114
+ # Returns true if the relation is an embedded one. In this case
115
+ # always false.
116
+ #
117
+ # @example Is this relation embedded?
118
+ # Referenced::One.embedded?
119
+ #
120
+ # @return [ false ] Always false.
121
+ #
122
+ # @since 2.0.0.rc.1
123
+ def embedded?
124
+ false
125
+ end
126
+
127
+ # Get the default value for the foreign key.
128
+ #
129
+ # @example Get the default.
130
+ # Referenced::One.foreign_key_default
131
+ #
132
+ # @return [ nil ] Always nil.
133
+ #
134
+ # @since 2.0.0.rc.1
135
+ def foreign_key_default
136
+ nil
137
+ end
138
+
139
+ # Returns the suffix of the foreign key field, either "_id" or "_ids".
140
+ #
141
+ # @example Get the suffix for the foreign key.
142
+ # Referenced::One.foreign_key_suffix
143
+ #
144
+ # @return [ String ] "_id"
145
+ #
146
+ # @since 2.0.0.rc.1
147
+ def foreign_key_suffix
148
+ "_id"
149
+ end
150
+
151
+ # Returns the macro for this relation. Used mostly as a helper in
152
+ # reflection.
153
+ #
154
+ # @example Get the macro.
155
+ # Referenced::One.macro
156
+ #
157
+ # @return [ Symbol ] :references_one.
158
+ def macro
159
+ :references_one
160
+ end
161
+
162
+ # Return the nested builder that is responsible for generating the documents
163
+ # that will be used by this relation.
164
+ #
165
+ # @example Get the nested builder.
166
+ # Referenced::One.builder(attributes, options)
167
+ #
168
+ # @param [ Metadata ] metadata The relation metadata.
169
+ # @param [ Hash ] attributes The attributes to build with.
170
+ # @param [ Hash ] options The options for the builder.
171
+ #
172
+ # @option options [ true, false ] :allow_destroy Can documents be
173
+ # deleted?
174
+ # @option options [ Integer ] :limit Max number of documents to
175
+ # create at once.
176
+ # @option options [ Proc, Symbol ] :reject_if If documents match this
177
+ # option then they are ignored.
178
+ # @option options [ true, false ] :update_only Only existing documents
179
+ # can be modified.
180
+ #
181
+ # @return [ NestedBuilder ] A newly instantiated nested builder object.
182
+ #
183
+ # @since 2.0.0.rc.1
184
+ def nested_builder(metadata, attributes, options)
185
+ Builders::NestedAttributes::One.new(metadata, attributes, options)
186
+ end
187
+
188
+ # Tells the caller if this relation is one that stores the foreign
189
+ # key on its own objects.
190
+ #
191
+ # @example Does this relation store a foreign key?
192
+ # Referenced::One.stores_foreign_key?
193
+ #
194
+ # @return [ false ] Always false.
195
+ #
196
+ # @since 2.0.0.rc.1
197
+ def stores_foreign_key?
198
+ false
199
+ end
200
+ end
201
+ end
202
+ end
203
+ end
204
+ end
@@ -0,0 +1,45 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+
5
+ # The reflections module provides convenience methods that can retrieve
6
+ # useful information about associations.
7
+ module Reflections
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+
12
+ delegate \
13
+ :reflect_on_association,
14
+ :reflect_on_all_associations, :to => "self.class"
15
+ end
16
+
17
+ module ClassMethods #:nodoc
18
+
19
+ # Returns the relation metadata for the supplied name.
20
+ #
21
+ # @example Find relation metadata by name.
22
+ # Person.reflect_on_association(:addresses)
23
+ #
24
+ # @param [ String, Symbol ] name The name of the relation to find.
25
+ #
26
+ # @return [ Metadata ] The matching relation metadata.
27
+ def reflect_on_association(name)
28
+ relations[name.to_s]
29
+ end
30
+
31
+ # Returns all relation metadata for the supplied macros.
32
+ #
33
+ # @example Find multiple relation metadata by macro.
34
+ # Person.reflect_on_all_associations(:embeds_many)
35
+ #
36
+ # @param [ Array<String, Symbol> ] *macros The relation macros.
37
+ #
38
+ # @return [ Array<Metadata> ] The matching relation metadata.
39
+ def reflect_on_all_associations(*macros)
40
+ relations.values.select { |meta| macros.include?(meta.macro) }
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -1,10 +1,20 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
- module Safe #:nodoc:
3
+
4
+ # Contains behaviour for determining if Mongoid is in safe mode.
5
+ module Safe
6
+
4
7
  # Determine based on configuration if we are persisting in safe mode or
5
8
  # not.
6
9
  #
7
10
  # The query option will always override the global configuration.
11
+ #
12
+ # @example Are we in safe mode?
13
+ # document.safe_mode?(:safe => true)
14
+ #
15
+ # @param [ Hash ] options Persistence options.
16
+ #
17
+ # @return [ true, false ] True if in safe mode, false if not.
8
18
  def safe_mode?(options)
9
19
  safe = options[:safe]
10
20
  safe.nil? ? Mongoid.persist_in_safe_mode : safe
@@ -9,14 +9,20 @@ module Mongoid #:nodoc:
9
9
 
10
10
  # Execute the following class-level persistence operation in safe mode.
11
11
  #
12
- # Example:
12
+ # @example Upsert in safe mode.
13
+ # person.safely.upsert
13
14
  #
14
- # <tt>person.safely.upsert</tt>
15
- # <tt>person.safely(:w => 2, :fsync => true).destroy</tt>
15
+ # @example Destroy in safe mode with w and fsync options.
16
+ # person.safely(:w => 2, :fsync => true).destroy
16
17
  #
17
- # Returns:
18
+ # @param [ Hash ] options The safe mode options.
18
19
  #
19
- # A +Proxy+ to the +Document+.
20
+ # @option options [ Integer ] :w The number of nodes to write to.
21
+ # @option options [ Integer ] :wtimeout Time to wait for return from all
22
+ # nodes.
23
+ # @option options [ true, false ] :fsync Should a fsync occur.
24
+ #
25
+ # @return [ Proxy ] The safety proxy.
20
26
  def safely(safety = true)
21
27
  Proxy.new(self, safety)
22
28
  end
@@ -25,14 +31,20 @@ module Mongoid #:nodoc:
25
31
 
26
32
  # Execute the following class-level persistence operation in safe mode.
27
33
  #
28
- # Example:
34
+ # @example Create in safe mode.
35
+ # Person.safely.create(:name => "John")
36
+ #
37
+ # @example Delete all in safe mode with options.
38
+ # Person.safely(:w => 2, :fsync => true).delete_all
29
39
  #
30
- # <tt>Person.safely.create(:name => "John")</tt>
31
- # <tt>Person.safely(:w => 2, :fsync => true).delete_all</tt>
40
+ # @param [ Hash ] options The safe mode options.
32
41
  #
33
- # Returns:
42
+ # @option options [ Integer ] :w The number of nodes to write to.
43
+ # @option options [ Integer ] :wtimeout Time to wait for return from all
44
+ # nodes.
45
+ # @option options [ true, false ] :fsync Should a fsync occur.
34
46
  #
35
- # A +Proxy+ to the +Document+ class.
47
+ # @return [ Proxy ] The safety proxy.
36
48
  def safely(safety = true)
37
49
  Proxy.new(self, safety)
38
50
  end
@@ -50,132 +62,145 @@ module Mongoid #:nodoc:
50
62
 
51
63
  attr_reader :target, :safety_options
52
64
 
53
- # Create the new +Proxy+.
65
+ # Create a new +Document+. This will instantiate a new document and
66
+ # insert it in a single call. Will always return the document
67
+ # whether save passed or not.
54
68
  #
55
- # Options:
69
+ # @example Safely create a document.
70
+ # Person.safely.create(:title => "Mr")
56
71
  #
57
- # target: Either the class or the instance.
58
- # safety_options: true or a hash of options
59
- def initialize(target, safety_options)
60
- @target = target
61
- @safety_options = safety_options
72
+ # @param [ Hash ] attributes The attributes to create with.
73
+ #
74
+ # @return [ Document ] The new document.
75
+ def create(attributes = {})
76
+ target.new(attributes).tap { |doc| doc.insert(:safe => safety_options) }
62
77
  end
63
78
 
64
- # We will use method missing to proxy calls to the target.
79
+ # Create a new +Document+. This will instantiate a new document and
80
+ # insert it in a single call. Will always return the document
81
+ # whether save passed or not, and if validation fails an error will be
82
+ # raise.
65
83
  #
66
- # Example:
84
+ # @example Safely create a document.
85
+ # Person.safely.create!(:title => "Mr")
67
86
  #
68
- # <tt>person.safely.save</tt>
69
- def method_missing(*args)
70
- name = args[0]
71
- attributes = args[1] || {}
72
- @target.send(name, attributes.merge(:safe => safety_options))
73
- end
74
-
75
- # Increment the field by the provided value, else if it doesn't exists set
76
- # it to that value.
87
+ # @param [ Hash ] attributes The attributes to create with.
77
88
  #
78
- # Options:
89
+ # @raise [ Errors::Validations ] If validation failed.
79
90
  #
80
- # field: The field to increment.
81
- # value: The value to increment by.
82
- # options: Options to pass through to the driver.
83
- def inc(field, value, options = {})
84
- @target.inc(field, value, :safe => safety_options)
91
+ # @return [ Document ] If validation passed.
92
+ def create!(attributes = {})
93
+ target.new(attributes).tap do |document|
94
+ fail_validate!(document) if document.insert(:safe => safety_options).errors.any?
95
+ end
85
96
  end
86
97
 
87
- # Update the +Document+ attributes in the datbase.
98
+ # Delete all documents given the supplied conditions. If no conditions
99
+ # are passed, the entire collection will be dropped for performance
100
+ # benefits. Does not fire any callbacks.
88
101
  #
89
- # Example:
102
+ # @example Delete all documents.
103
+ # Person.safely.delete_all
90
104
  #
91
- # <tt>document.update_attributes(:title => "Sir")</tt>
105
+ # @example Conditionally delete all documents.
106
+ # Person.safely.delete_all(:conditions => { :title => "Sir" })
92
107
  #
93
- # Returns:
108
+ # @param [ Hash ] conditions The conditions to delete with.
94
109
  #
95
- # +true+ if validation passed, +false+ if not.
96
- def update_attributes(attributes = {})
97
- @target.write_attributes(attributes)
98
- @target.update(:safe => safety_options)
110
+ # @return [ Integer ] The number of documents deleted.
111
+ def delete_all(conditions = {})
112
+ Mongoid::Persistence::RemoveAll.new(
113
+ target,
114
+ { :validate => false, :safe => safety_options },
115
+ conditions[:conditions] || {}
116
+ ).persist
99
117
  end
100
118
 
101
- # Update the +Document+ attributes in the datbase.
119
+ # destroy all documents given the supplied conditions. If no conditions
120
+ # are passed, the entire collection will be dropped for performance
121
+ # benefits. Fires the destroy callbacks if conditions were passed.
102
122
  #
103
- # Example:
123
+ # @example destroy all documents.
124
+ # Person.safely.destroy_all
104
125
  #
105
- # <tt>document.update_attributes(:title => "Sir")</tt>
126
+ # @example Conditionally destroy all documents.
127
+ # Person.safely.destroy_all(:conditions => { :title => "Sir" })
106
128
  #
107
- # Returns:
129
+ # @param [ Hash ] conditions The conditions to destroy with.
108
130
  #
109
- # +true+ if validation passed, raises an error if not
110
- def update_attributes!(attributes = {})
111
- @target.write_attributes(attributes)
112
- result = update(:safe => safety_options)
113
- @target.class.fail_validate!(self) unless result
114
- result
131
+ # @return [ Integer ] The number of documents destroyd.
132
+ def destroy_all(conditions = {})
133
+ documents = target.all(conditions)
134
+ documents.count.tap do |count|
135
+ documents.each { |doc| doc.destroy(:safe => safety_options) }
136
+ end
115
137
  end
116
138
 
117
- # Create a new +Document+. This will instantiate a new document and
118
- # insert it in a single call. Will always return the document
119
- # whether save passed or not.
120
- #
121
- # Example:
139
+ # Increment the field by the provided value, else if it doesn't exists set
140
+ # it to that value.
122
141
  #
123
- # <tt>Person.create(:title => "Mr")</tt>
142
+ # @example Safely increment a field.
143
+ # person.safely.inc(:age, 1)
124
144
  #
125
- # Returns: the +Document+.
126
- def create(attributes = {})
127
- @target.new(attributes).tap { |doc| doc.insert(:safe => safety_options) }
145
+ # @param [ Symbol, String ] field The field to increment.
146
+ # @param [ Integer ] value The value to increment by.
147
+ # @param [ Hash ] options Options to pass through to the driver.
148
+ def inc(field, value, options = {})
149
+ target.inc(field, value, :safe => safety_options)
128
150
  end
129
151
 
130
- # Create a new +Document+. This will instantiate a new document and
131
- # insert it in a single call. Will always return the document
132
- # whether save passed or not, and if validation fails an error will be
133
- # raise.
152
+ # Create the new +Proxy+.
153
+ #
154
+ # @example Create the proxy.
155
+ # Proxy.new(document, :w => 3)
134
156
  #
135
- # Example:
157
+ # @param [ Document, Class ] target Either the class or the instance.
158
+ # @param [ true, Hash ] safety_options The options.
159
+ def initialize(target, safety_options)
160
+ @target = target
161
+ @safety_options = safety_options
162
+ end
163
+
164
+ # We will use method missing to proxy calls to the target.
136
165
  #
137
- # <tt>Person.create!(:title => "Mr")</tt>
166
+ # @example Save safely.
167
+ # person.safely.save
138
168
  #
139
- # Returns: the +Document+.
140
- def create!(attributes = {})
141
- document = @target.new(attributes)
142
- fail_validate!(document) if document.insert(:safe => safety_options).errors.any?
143
- document
169
+ # @param [ Array ] *args The arguments to pass on.
170
+ def method_missing(*args)
171
+ name = args[0]
172
+ attributes = args[1] || {}
173
+ target.send(name, attributes.merge(:safe => safety_options))
144
174
  end
145
175
 
146
- # Delete all documents given the supplied conditions. If no conditions
147
- # are passed, the entire collection will be dropped for performance
148
- # benefits. Does not fire any callbacks.
176
+ # Update the +Document+ attributes in the datbase.
149
177
  #
150
- # Example:
178
+ # @example Safely update attributes.
179
+ # person.safely.update_attributes(:title => "Sir")
151
180
  #
152
- # <tt>Person.delete_all(:conditions => { :title => "Sir" })</tt>
153
- # <tt>Person.delete_all</tt>
181
+ # @param [ Hash ] attributes The attributes to update.
154
182
  #
155
- # Returns: true or raises an error.
156
- def delete_all(conditions = {})
157
- Mongoid::Persistence::RemoveAll.new(
158
- @target,
159
- { :validate => false, :safe => safety_options },
160
- conditions[:conditions] || {}
161
- ).persist
183
+ # @return [ true, false ] Whether the document was saved.
184
+ def update_attributes(attributes = {})
185
+ target.write_attributes(attributes)
186
+ target.update(:safe => safety_options)
162
187
  end
163
188
 
164
- # Delete all documents given the supplied conditions. If no conditions
165
- # are passed, the entire collection will be dropped for performance
166
- # benefits. Fires the destroy callbacks if conditions were passed.
189
+ # Update the +Document+ attributes in the datbase.
167
190
  #
168
- # Example:
191
+ # @example Safely update attributes.
192
+ # person.safely.update_attributes(:title => "Sir")
169
193
  #
170
- # <tt>Person.destroy_all(:conditions => { :title => "Sir" })</tt>
171
- # <tt>Person.destroy_all</tt>
194
+ # @param [ Hash ] attributes The attributes to update.
172
195
  #
173
- # Returns: true or raises an error.
174
- def destroy_all(conditions = {})
175
- documents = @target.all(conditions)
176
- count = documents.count
177
- documents.each { |doc| doc.destroy(:safe => safety_options) }
178
- count
196
+ # @raise [ Errors::Validations ] If validation failed.
197
+ #
198
+ # @return [ true ] If the document was saved.
199
+ def update_attributes!(attributes = {})
200
+ target.write_attributes(attributes)
201
+ update(:safe => safety_options).tap do |result|
202
+ target.class.fail_validate!(self) unless result
203
+ end
179
204
  end
180
205
  end
181
206
  end