mongoid 1.2.14 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (200) hide show
  1. data/lib/mongoid.rb +10 -3
  2. data/lib/mongoid/associations.rb +133 -97
  3. data/lib/mongoid/associations/belongs_to_related.rb +2 -3
  4. data/lib/mongoid/associations/{belongs_to.rb → embedded_in.rb} +14 -6
  5. data/lib/mongoid/associations/{has_many.rb → embeds_many.rb} +89 -31
  6. data/lib/mongoid/associations/{has_one.rb → embeds_one.rb} +8 -7
  7. data/lib/mongoid/associations/has_many_related.rb +52 -7
  8. data/lib/mongoid/associations/has_one_related.rb +8 -4
  9. data/lib/mongoid/associations/meta_data.rb +2 -1
  10. data/lib/mongoid/associations/options.rb +6 -1
  11. data/lib/mongoid/associations/proxy.rb +14 -21
  12. data/lib/mongoid/attributes.rb +27 -12
  13. data/lib/mongoid/collection.rb +4 -3
  14. data/lib/mongoid/collections.rb +41 -0
  15. data/lib/mongoid/collections/master.rb +3 -2
  16. data/lib/mongoid/collections/slaves.rb +3 -2
  17. data/lib/mongoid/components.rb +21 -19
  18. data/lib/mongoid/concern.rb +31 -0
  19. data/lib/mongoid/config.rb +117 -12
  20. data/lib/mongoid/contexts.rb +1 -1
  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/criterion/inclusion.rb +17 -0
  25. data/lib/mongoid/criterion/optional.rb +1 -1
  26. data/lib/mongoid/dirty.rb +253 -0
  27. data/lib/mongoid/document.rb +81 -52
  28. data/lib/mongoid/errors.rb +32 -1
  29. data/lib/mongoid/extensions.rb +11 -9
  30. data/lib/mongoid/extensions/big_decimal/conversions.rb +2 -2
  31. data/lib/mongoid/extensions/boolean/conversions.rb +8 -2
  32. data/lib/mongoid/extensions/date/conversions.rb +13 -4
  33. data/lib/mongoid/extensions/datetime/conversions.rb +1 -6
  34. data/lib/mongoid/extensions/float/conversions.rb +5 -1
  35. data/lib/mongoid/extensions/hash/assimilation.rb +12 -3
  36. data/lib/mongoid/extensions/hash/conversions.rb +34 -4
  37. data/lib/mongoid/extensions/integer/conversions.rb +5 -1
  38. data/lib/mongoid/extensions/nil/assimilation.rb +4 -0
  39. data/lib/mongoid/extensions/object/conversions.rb +1 -1
  40. data/lib/mongoid/extensions/string/conversions.rb +1 -1
  41. data/lib/mongoid/extensions/symbol/inflections.rb +1 -1
  42. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  43. data/lib/mongoid/extras.rb +6 -9
  44. data/lib/mongoid/factory.rb +2 -1
  45. data/lib/mongoid/field.rb +9 -2
  46. data/lib/mongoid/fields.rb +1 -0
  47. data/lib/mongoid/identity.rb +3 -3
  48. data/lib/mongoid/indexes.rb +3 -3
  49. data/lib/mongoid/memoization.rb +8 -2
  50. data/lib/mongoid/named_scope.rb +0 -3
  51. data/lib/mongoid/observable.rb +30 -0
  52. data/lib/mongoid/paths.rb +62 -0
  53. data/lib/mongoid/persistence.rb +222 -0
  54. data/lib/mongoid/persistence/command.rb +39 -0
  55. data/lib/mongoid/persistence/insert.rb +50 -0
  56. data/lib/mongoid/persistence/insert_embedded.rb +38 -0
  57. data/lib/mongoid/persistence/remove.rb +39 -0
  58. data/lib/mongoid/persistence/remove_all.rb +37 -0
  59. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  60. data/lib/mongoid/persistence/update.rb +63 -0
  61. data/lib/mongoid/state.rb +28 -21
  62. data/lib/mongoid/timestamps.rb +5 -8
  63. data/lib/mongoid/version.rb +4 -0
  64. data/lib/mongoid/versioning.rb +6 -7
  65. metadata +81 -300
  66. data/.gitignore +0 -6
  67. data/.watchr +0 -29
  68. data/Rakefile +0 -53
  69. data/VERSION +0 -1
  70. data/caliper.yml +0 -4
  71. data/lib/mongoid/collections/mimic.rb +0 -46
  72. data/lib/mongoid/commands.rb +0 -174
  73. data/lib/mongoid/commands/create.rb +0 -21
  74. data/lib/mongoid/commands/delete.rb +0 -16
  75. data/lib/mongoid/commands/delete_all.rb +0 -23
  76. data/lib/mongoid/commands/deletion.rb +0 -18
  77. data/lib/mongoid/commands/destroy.rb +0 -19
  78. data/lib/mongoid/commands/destroy_all.rb +0 -23
  79. data/lib/mongoid/commands/save.rb +0 -27
  80. data/lib/mongoid/extensions/time/conversions.rb +0 -18
  81. data/mongoid.gemspec +0 -395
  82. data/perf/benchmark.rb +0 -77
  83. data/spec/integration/mongoid/associations_spec.rb +0 -340
  84. data/spec/integration/mongoid/attributes_spec.rb +0 -22
  85. data/spec/integration/mongoid/commands_spec.rb +0 -218
  86. data/spec/integration/mongoid/contexts/enumerable_spec.rb +0 -33
  87. data/spec/integration/mongoid/criteria_spec.rb +0 -272
  88. data/spec/integration/mongoid/document_spec.rb +0 -593
  89. data/spec/integration/mongoid/extensions_spec.rb +0 -26
  90. data/spec/integration/mongoid/finders_spec.rb +0 -119
  91. data/spec/integration/mongoid/inheritance_spec.rb +0 -137
  92. data/spec/integration/mongoid/named_scope_spec.rb +0 -46
  93. data/spec/models/address.rb +0 -39
  94. data/spec/models/animal.rb +0 -6
  95. data/spec/models/callbacks.rb +0 -18
  96. data/spec/models/comment.rb +0 -8
  97. data/spec/models/country_code.rb +0 -6
  98. data/spec/models/employer.rb +0 -5
  99. data/spec/models/game.rb +0 -7
  100. data/spec/models/inheritance.rb +0 -56
  101. data/spec/models/location.rb +0 -5
  102. data/spec/models/mixed_drink.rb +0 -4
  103. data/spec/models/name.rb +0 -13
  104. data/spec/models/namespacing.rb +0 -11
  105. data/spec/models/patient.rb +0 -4
  106. data/spec/models/person.rb +0 -99
  107. data/spec/models/pet.rb +0 -7
  108. data/spec/models/pet_owner.rb +0 -6
  109. data/spec/models/phone.rb +0 -7
  110. data/spec/models/post.rb +0 -15
  111. data/spec/models/translation.rb +0 -5
  112. data/spec/models/vet_visit.rb +0 -5
  113. data/spec/spec.opts +0 -3
  114. data/spec/spec_helper.rb +0 -31
  115. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +0 -145
  116. data/spec/unit/mongoid/associations/belongs_to_spec.rb +0 -193
  117. data/spec/unit/mongoid/associations/has_many_related_spec.rb +0 -420
  118. data/spec/unit/mongoid/associations/has_many_spec.rb +0 -519
  119. data/spec/unit/mongoid/associations/has_one_related_spec.rb +0 -179
  120. data/spec/unit/mongoid/associations/has_one_spec.rb +0 -282
  121. data/spec/unit/mongoid/associations/meta_data_spec.rb +0 -88
  122. data/spec/unit/mongoid/associations/options_spec.rb +0 -192
  123. data/spec/unit/mongoid/associations_spec.rb +0 -595
  124. data/spec/unit/mongoid/attributes_spec.rb +0 -507
  125. data/spec/unit/mongoid/callbacks_spec.rb +0 -55
  126. data/spec/unit/mongoid/collection_spec.rb +0 -187
  127. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +0 -75
  128. data/spec/unit/mongoid/collections/master_spec.rb +0 -41
  129. data/spec/unit/mongoid/collections/mimic_spec.rb +0 -43
  130. data/spec/unit/mongoid/collections/slaves_spec.rb +0 -81
  131. data/spec/unit/mongoid/commands/create_spec.rb +0 -30
  132. data/spec/unit/mongoid/commands/delete_all_spec.rb +0 -58
  133. data/spec/unit/mongoid/commands/delete_spec.rb +0 -38
  134. data/spec/unit/mongoid/commands/destroy_all_spec.rb +0 -23
  135. data/spec/unit/mongoid/commands/destroy_spec.rb +0 -50
  136. data/spec/unit/mongoid/commands/save_spec.rb +0 -105
  137. data/spec/unit/mongoid/commands_spec.rb +0 -275
  138. data/spec/unit/mongoid/config_spec.rb +0 -172
  139. data/spec/unit/mongoid/contexts/enumerable_spec.rb +0 -421
  140. data/spec/unit/mongoid/contexts/mongo_spec.rb +0 -682
  141. data/spec/unit/mongoid/contexts_spec.rb +0 -25
  142. data/spec/unit/mongoid/criteria_spec.rb +0 -824
  143. data/spec/unit/mongoid/criterion/complex_spec.rb +0 -19
  144. data/spec/unit/mongoid/criterion/exclusion_spec.rb +0 -91
  145. data/spec/unit/mongoid/criterion/inclusion_spec.rb +0 -219
  146. data/spec/unit/mongoid/criterion/optional_spec.rb +0 -319
  147. data/spec/unit/mongoid/cursor_spec.rb +0 -74
  148. data/spec/unit/mongoid/deprecation_spec.rb +0 -24
  149. data/spec/unit/mongoid/document_spec.rb +0 -952
  150. data/spec/unit/mongoid/errors_spec.rb +0 -103
  151. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +0 -50
  152. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +0 -24
  153. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +0 -35
  154. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +0 -20
  155. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +0 -22
  156. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +0 -22
  157. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +0 -49
  158. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +0 -102
  159. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +0 -70
  160. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +0 -61
  161. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +0 -184
  162. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +0 -46
  163. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +0 -21
  164. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +0 -17
  165. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +0 -14
  166. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +0 -61
  167. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +0 -24
  168. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +0 -57
  169. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +0 -34
  170. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +0 -17
  171. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +0 -208
  172. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +0 -91
  173. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +0 -70
  174. data/spec/unit/mongoid/extras_spec.rb +0 -102
  175. data/spec/unit/mongoid/factory_spec.rb +0 -31
  176. data/spec/unit/mongoid/field_spec.rb +0 -143
  177. data/spec/unit/mongoid/fields_spec.rb +0 -181
  178. data/spec/unit/mongoid/finders_spec.rb +0 -404
  179. data/spec/unit/mongoid/identity_spec.rb +0 -109
  180. data/spec/unit/mongoid/indexes_spec.rb +0 -93
  181. data/spec/unit/mongoid/javascript_spec.rb +0 -48
  182. data/spec/unit/mongoid/matchers/all_spec.rb +0 -27
  183. data/spec/unit/mongoid/matchers/default_spec.rb +0 -27
  184. data/spec/unit/mongoid/matchers/exists_spec.rb +0 -56
  185. data/spec/unit/mongoid/matchers/gt_spec.rb +0 -39
  186. data/spec/unit/mongoid/matchers/gte_spec.rb +0 -49
  187. data/spec/unit/mongoid/matchers/in_spec.rb +0 -27
  188. data/spec/unit/mongoid/matchers/lt_spec.rb +0 -39
  189. data/spec/unit/mongoid/matchers/lte_spec.rb +0 -49
  190. data/spec/unit/mongoid/matchers/ne_spec.rb +0 -27
  191. data/spec/unit/mongoid/matchers/nin_spec.rb +0 -27
  192. data/spec/unit/mongoid/matchers/size_spec.rb +0 -27
  193. data/spec/unit/mongoid/matchers_spec.rb +0 -329
  194. data/spec/unit/mongoid/memoization_spec.rb +0 -75
  195. data/spec/unit/mongoid/named_scope_spec.rb +0 -123
  196. data/spec/unit/mongoid/scope_spec.rb +0 -240
  197. data/spec/unit/mongoid/state_spec.rb +0 -83
  198. data/spec/unit/mongoid/timestamps_spec.rb +0 -25
  199. data/spec/unit/mongoid/versioning_spec.rb +0 -41
  200. data/spec/unit/mongoid_spec.rb +0 -46
@@ -14,8 +14,8 @@ module Mongoid #:nodoc
14
14
  # Add the default indexes to the root document if they do not already
15
15
  # exist. Currently this is only _type.
16
16
  def add_indexes
17
- unless indexed
18
- self._collection.create_index(:_type, false)
17
+ if hereditary && !indexed
18
+ self._collection.create_index(:_type, :unique => false, :background => true)
19
19
  self.indexed = true
20
20
  end
21
21
  end
@@ -23,7 +23,7 @@ module Mongoid #:nodoc
23
23
  # Adds an index on the field specified. Options can be :unique => true or
24
24
  # :unique => false. It will default to the latter.
25
25
  def index(name, options = { :unique => false })
26
- collection.create_index(name, options[:unique])
26
+ collection.create_index(name, options)
27
27
  end
28
28
  end
29
29
  end
@@ -2,14 +2,20 @@ module Mongoid #:nodoc
2
2
  module Memoization
3
3
 
4
4
  # Handles cases when accessing an association that should be memoized in
5
- # the Mongoid specific manner.
5
+ # the Mongoid specific manner. Does not memoize nil values though
6
6
  def memoized(name, &block)
7
7
  var = "@#{name}"
8
8
  if instance_variable_defined?(var)
9
9
  return instance_variable_get(var)
10
10
  end
11
11
  value = yield
12
- instance_variable_set(var, value)
12
+ instance_variable_set(var, value) if value
13
+ end
14
+
15
+ # Removes an memozied association if it exists
16
+ def unmemoize(name)
17
+ var = "@#{name}"
18
+ remove_instance_variable(var) if instance_variable_defined?(var)
13
19
  end
14
20
 
15
21
  # Mongoid specific behavior is to remove the memoized object when setting
@@ -27,14 +27,11 @@ module Mongoid #:nodoc:
27
27
  end
28
28
  EOT
29
29
  end
30
-
31
30
  alias :scope :named_scope
32
31
 
33
32
  # Return the scopes or default to an empty +Hash+.
34
33
  def scopes
35
34
  read_inheritable_attribute(:scopes) || write_inheritable_attribute(:scopes, {})
36
35
  end
37
-
38
36
  end
39
37
  end
40
-
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Observable #:nodoc:
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ attr_reader :observers
7
+ end
8
+
9
+ # Add an observer to this object. This mimics the standard Ruby observable
10
+ # library.
11
+ #
12
+ # Example:
13
+ #
14
+ # <tt>address.add_observer(person)</tt>
15
+ def add_observer(object)
16
+ @observers ||= []
17
+ @observers.push(object)
18
+ end
19
+
20
+ # Notify all the objects observing this object of an update. All observers
21
+ # need to respond to the update method in order to handle this.
22
+ #
23
+ # Example:
24
+ #
25
+ # <tt>document.notify_observers(self)</tt>
26
+ def notify_observers(*args)
27
+ @observers.dup.each { |observer| observer.observe(*args) } if @observers
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,62 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Paths #:nodoc:
4
+ extend ActiveSupport::Concern
5
+ included do
6
+ attr_accessor :__path
7
+ attr_accessor :_index
8
+ end
9
+ module InstanceMethods
10
+ # Get the insertion modifier for the document. Will be nil on root
11
+ # documents, $set on embeds_one, $push on embeds_many.
12
+ #
13
+ # Example:
14
+ #
15
+ # <tt>name.inserter</tt>
16
+ def _inserter
17
+ embedded? ? (embedded_many? ? "$push" : "$set") : nil
18
+ end
19
+
20
+ # Return the path to this +Document+ in JSON notation, used for atomic
21
+ # updates via $set in MongoDB.
22
+ #
23
+ # Example:
24
+ #
25
+ # <tt>address.path # returns "addresses"</tt>
26
+ def _path
27
+ _position.sub!(/\.\d+$/, '') || _position
28
+ end
29
+ alias :_pull :_path
30
+
31
+ # Returns the positional operator of this document for modification.
32
+ #
33
+ # Example:
34
+ #
35
+ # <tt>address.position</tt>
36
+ def _position
37
+ locator = _index ? (new_record? ? "" : ".#{_index}") : ""
38
+ embedded? ? "#{_parent._position}#{"." unless _parent._position.blank?}#{@association_name}#{locator}" : ""
39
+ end
40
+
41
+ # Get the removal modifier for the document. Will be nil on root
42
+ # documents, $unset on embeds_one, $set on embeds_many.
43
+ #
44
+ # Example:
45
+ #
46
+ # <tt>name.remover</tt>
47
+ def _remover
48
+ embedded? ? (_index ? "$pull" : "$unset") : nil
49
+ end
50
+
51
+ # Return the selector for this document to be matched exactly for use
52
+ # with MongoDB's $ operator.
53
+ #
54
+ # Example:
55
+ #
56
+ # <tt>address.selector</tt>
57
+ def _selector
58
+ embedded? ? _parent._selector.merge("#{_path}._id" => id) : { "_id" => id }
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,222 @@
1
+ # encoding: utf-8
2
+ require "mongoid/persistence/command"
3
+ require "mongoid/persistence/insert"
4
+ require "mongoid/persistence/insert_embedded"
5
+ require "mongoid/persistence/remove"
6
+ require "mongoid/persistence/remove_all"
7
+ require "mongoid/persistence/remove_embedded"
8
+ require "mongoid/persistence/update"
9
+
10
+ module Mongoid #:nodoc:
11
+ # The persistence module is a mixin to provide database accessor methods for
12
+ # the document. These correspond to the appropriate accessors on a
13
+ # +Mongo::Collection+ and retain the same DSL.
14
+ #
15
+ # Examples:
16
+ #
17
+ # <tt>document.insert</tt>
18
+ # <tt>document.update</tt>
19
+ # <tt>document.upsert</tt>
20
+ module Persistence
21
+ extend ActiveSupport::Concern
22
+ module InstanceMethods #:nodoc:
23
+ # Remove the +Document+ from the datbase with callbacks.
24
+ #
25
+ # Example:
26
+ #
27
+ # <tt>document.destroy</tt>
28
+ #
29
+ # TODO: Will get rid of other #destroy once new persistence complete.
30
+ def destroy
31
+ run_callbacks(:before_destroy)
32
+ if _remove
33
+ self.destroyed = true
34
+ run_callbacks(:after_destroy)
35
+ end; true
36
+ end
37
+
38
+ # Insert a new +Document+ into the database. Will return the document
39
+ # itself whether or not the save was successful.
40
+ #
41
+ # Example:
42
+ #
43
+ # <tt>document.insert</tt>
44
+ def insert(validate = true)
45
+ Insert.new(self, validate).persist
46
+ end
47
+
48
+ # Remove the +Document+ from the datbase.
49
+ #
50
+ # Example:
51
+ #
52
+ # <tt>document._remove</tt>
53
+ #
54
+ # TODO: Will get rid of other #remove once observable pattern killed.
55
+ def _remove
56
+ Remove.new(self).persist
57
+ end
58
+
59
+ alias :delete :_remove
60
+
61
+ # Save the document - will perform an insert if the document is new, and
62
+ # update if not. If a validation error occurs a
63
+ # Mongoid::Errors::Validations error will get raised.
64
+ #
65
+ # Example:
66
+ #
67
+ # <tt>document.save!</tt>
68
+ #
69
+ # Returns:
70
+ #
71
+ # +true+ if validation passed, will raise error otherwise.
72
+ def save!
73
+ self.class.fail_validate!(self) unless upsert; true
74
+ end
75
+
76
+ # Update the +Document+ in the datbase.
77
+ #
78
+ # Example:
79
+ #
80
+ # <tt>document.update</tt>
81
+ def update(validate = true)
82
+ Update.new(self, validate).persist
83
+ end
84
+
85
+ # Update the +Document+ attributes in the datbase.
86
+ #
87
+ # Example:
88
+ #
89
+ # <tt>document.update_attributes(:title => "Sir")</tt>
90
+ #
91
+ # Returns:
92
+ #
93
+ # +true+ if validation passed, +false+ if not.
94
+ def update_attributes(attributes = {})
95
+ write_attributes(attributes); update
96
+ end
97
+
98
+ # Update the +Document+ attributes in the datbase.
99
+ #
100
+ # Example:
101
+ #
102
+ # <tt>document.update_attributes(:title => "Sir")</tt>
103
+ #
104
+ # Returns:
105
+ #
106
+ # +true+ if validation passed, raises an error if not
107
+ def update_attributes!(attributes = {})
108
+ write_attributes(attributes)
109
+ result = update
110
+ self.class.fail_validate!(self) unless result
111
+ result
112
+ end
113
+
114
+ # Upsert the document - will perform an insert if the document is new, and
115
+ # update if not.
116
+ #
117
+ # Example:
118
+ #
119
+ # <tt>document.upsert</tt>
120
+ #
121
+ # Returns:
122
+ #
123
+ # A +Boolean+ for updates.
124
+ def upsert(validate = true)
125
+ validate = parse_validate(validate)
126
+ if new_record?
127
+ insert(validate).errors.any? ? false : true
128
+ else
129
+ update(validate)
130
+ end
131
+ end
132
+
133
+ # Save is aliased so that users familiar with active record can have some
134
+ # semblance of a familiar API.
135
+ #
136
+ # Example:
137
+ #
138
+ # <tt>document.save</tt>
139
+ alias :save :upsert
140
+
141
+ protected
142
+ # Alternative validation params.
143
+ def parse_validate(validate)
144
+ if validate.is_a?(Hash) && validate.has_key?(:validate)
145
+ validate = validate[:validate]
146
+ end
147
+ validate
148
+ end
149
+ end
150
+
151
+ module ClassMethods #:nodoc:
152
+
153
+ # Create a new +Document+. This will instantiate a new document and
154
+ # insert it in a single call. Will always return the document
155
+ # whether save passed or not.
156
+ #
157
+ # Example:
158
+ #
159
+ # <tt>Person.create(:title => "Mr")</tt>
160
+ #
161
+ # Returns: the +Document+.
162
+ def create(attributes = {})
163
+ document = new(attributes); document.insert
164
+ end
165
+
166
+ # Create a new +Document+. This will instantiate a new document and
167
+ # insert it in a single call. Will always return the document
168
+ # whether save passed or not, and if validation fails an error will be
169
+ # raise.
170
+ #
171
+ # Example:
172
+ #
173
+ # <tt>Person.create!(:title => "Mr")</tt>
174
+ #
175
+ # Returns: the +Document+.
176
+ def create!(attributes = {})
177
+ document = new(attributes)
178
+ fail_validate!(document) if document.insert.errors.any?
179
+ document
180
+ end
181
+
182
+ # Delete all documents given the supplied conditions. If no conditions
183
+ # are passed, the entire collection will be dropped for performance
184
+ # benefits. Does not fire any callbacks.
185
+ #
186
+ # Example:
187
+ #
188
+ # <tt>Person.delete_all(:conditions => { :title => "Sir" })</tt>
189
+ # <tt>Person.delete_all</tt>
190
+ #
191
+ # Returns: true or raises an error.
192
+ def delete_all(conditions = {})
193
+ RemoveAll.new(
194
+ self,
195
+ false,
196
+ conditions[:conditions] || {}
197
+ ).persist
198
+ end
199
+
200
+ # Delete all documents given the supplied conditions. If no conditions
201
+ # are passed, the entire collection will be dropped for performance
202
+ # benefits. Fires the destroy callbacks if conditions were passed.
203
+ #
204
+ # Example:
205
+ #
206
+ # <tt>Person.destroy_all(:conditions => { :title => "Sir" })</tt>
207
+ # <tt>Person.destroy_all</tt>
208
+ #
209
+ # Returns: true or raises an error.
210
+ def destroy_all(conditions = {})
211
+ documents = all(conditions)
212
+ count = documents.count
213
+ documents.each { |doc| doc.destroy }; count
214
+ end
215
+
216
+ # Raise an error if validation failed.
217
+ def fail_validate!(document)
218
+ raise Errors::Validations.new(document.errors)
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,39 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Persistence commands extend from this class to get basic functionality on
5
+ # initialization.
6
+ class Command
7
+ attr_reader \
8
+ :collection,
9
+ :document,
10
+ :klass,
11
+ :options,
12
+ :selector,
13
+ :validate
14
+
15
+ # Initialize the persistence +Command+.
16
+ #
17
+ # Options:
18
+ #
19
+ # document_or_class: The +Document+ or +Class+ to get the collection.
20
+ # validate: Is the document to be validated.
21
+ # selector: Optional selector to use in query.
22
+ #
23
+ # Example:
24
+ #
25
+ # <tt>DeleteAll.new(Person, false, {})</tt>
26
+ def initialize(document_or_class, validate = true, selector = {})
27
+ if document_or_class.is_a?(Mongoid::Document)
28
+ @document = document_or_class
29
+ @collection = @document.embedded? ? @document._root.collection : @document.collection
30
+ else
31
+ @klass = document_or_class
32
+ @collection = @klass.collection
33
+ end
34
+ @selector, @validate = selector, validate
35
+ @options = { :safe => Mongoid.persist_in_safe_mode }
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,50 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ # Insert is a persistence command responsible for taking a document that
5
+ # has not been saved to the database and saving it.
6
+ #
7
+ # The underlying query resembles the following MongoDB query:
8
+ #
9
+ # collection.insert(
10
+ # { "_id" : 1, "field" : "value" },
11
+ # false
12
+ # );
13
+ class Insert < Command
14
+ # Insert the new document in the database. This delegates to the standard
15
+ # MongoDB collection's insert command.
16
+ #
17
+ # Example:
18
+ #
19
+ # <tt>Insert.persist</tt>
20
+ #
21
+ # Returns:
22
+ #
23
+ # The +Document+, whether the insert succeeded or not.
24
+ def persist
25
+ return @document if @validate && !@document.valid?
26
+ @document.run_callbacks(:before_create)
27
+ @document.run_callbacks(:before_save)
28
+ if insert
29
+ @document.new_record = false
30
+ # TODO: All child document new_record flags must get set to false
31
+ # here or somewhere - this will cause problems.
32
+ @document.move_changes
33
+ @document.run_callbacks(:after_create)
34
+ @document.run_callbacks(:after_save)
35
+ end
36
+ @document
37
+ end
38
+
39
+ protected
40
+ # Insert the document into the database.
41
+ def insert
42
+ if @document.embedded?
43
+ Persistence::InsertEmbedded.new(@document, @validate).persist
44
+ else
45
+ @collection.insert(@document.raw_attributes, @options)
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end