mongoid 2.0.2 → 2.1.0

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 (240) hide show
  1. data/README.rdoc +3 -1
  2. data/Rakefile +3 -2
  3. data/lib/config/locales/bg.yml +6 -0
  4. data/lib/config/locales/de.yml +6 -0
  5. data/lib/config/locales/en-GB.yml +48 -0
  6. data/lib/config/locales/en.yml +6 -3
  7. data/lib/config/locales/es.yml +6 -0
  8. data/lib/config/locales/fr.yml +6 -0
  9. data/lib/config/locales/hi.yml +39 -0
  10. data/lib/config/locales/hu.yml +13 -7
  11. data/lib/config/locales/id.yml +3 -0
  12. data/lib/config/locales/it.yml +7 -1
  13. data/lib/config/locales/ja.yml +4 -1
  14. data/lib/config/locales/kr.yml +9 -34
  15. data/lib/config/locales/nl.yml +6 -0
  16. data/lib/config/locales/pl.yml +6 -0
  17. data/lib/config/locales/pt-BR.yml +6 -0
  18. data/lib/config/locales/pt.yml +6 -0
  19. data/lib/config/locales/ro.yml +6 -0
  20. data/lib/config/locales/ru.yml +6 -0
  21. data/lib/config/locales/sv.yml +6 -0
  22. data/lib/config/locales/vi.yml +3 -0
  23. data/lib/config/locales/zh-CN.yml +6 -0
  24. data/lib/mongoid.rb +51 -45
  25. data/lib/mongoid/atomic.rb +145 -0
  26. data/lib/mongoid/atomic/modifiers.rb +109 -0
  27. data/lib/mongoid/atomic/paths.rb +3 -0
  28. data/lib/mongoid/atomic/paths/embedded.rb +43 -0
  29. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  30. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  31. data/lib/mongoid/atomic/paths/root.rb +40 -0
  32. data/lib/mongoid/attributes.rb +12 -23
  33. data/lib/mongoid/attributes/processing.rb +5 -5
  34. data/lib/mongoid/callbacks.rb +2 -0
  35. data/lib/mongoid/collection.rb +12 -59
  36. data/lib/mongoid/collections.rb +23 -20
  37. data/lib/mongoid/collections/master.rb +6 -4
  38. data/lib/mongoid/collections/operations.rb +1 -0
  39. data/lib/mongoid/collections/retry.rb +7 -0
  40. data/lib/mongoid/components.rb +2 -2
  41. data/lib/mongoid/config.rb +42 -55
  42. data/lib/mongoid/config/database.rb +6 -2
  43. data/lib/mongoid/config/replset_database.rb +7 -3
  44. data/lib/mongoid/contexts.rb +9 -3
  45. data/lib/mongoid/contexts/enumerable.rb +7 -3
  46. data/lib/mongoid/contexts/mongo.rb +139 -101
  47. data/lib/mongoid/criteria.rb +86 -69
  48. data/lib/mongoid/criterion/complex.rb +32 -5
  49. data/lib/mongoid/criterion/inclusion.rb +4 -2
  50. data/lib/mongoid/criterion/optional.rb +111 -86
  51. data/lib/mongoid/criterion/selector.rb +8 -4
  52. data/lib/mongoid/cursor.rb +27 -27
  53. data/lib/mongoid/dirty.rb +54 -214
  54. data/lib/mongoid/document.rb +37 -39
  55. data/lib/mongoid/errors/document_not_found.rb +3 -4
  56. data/lib/mongoid/errors/invalid_collection.rb +2 -3
  57. data/lib/mongoid/errors/invalid_database.rb +2 -3
  58. data/lib/mongoid/errors/invalid_field.rb +2 -3
  59. data/lib/mongoid/errors/invalid_options.rb +19 -7
  60. data/lib/mongoid/errors/invalid_type.rb +2 -3
  61. data/lib/mongoid/errors/mongoid_error.rb +5 -6
  62. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +2 -3
  63. data/lib/mongoid/errors/unsupported_version.rb +2 -3
  64. data/lib/mongoid/errors/validations.rb +2 -3
  65. data/lib/mongoid/extensions.rb +8 -62
  66. data/lib/mongoid/extensions/array/deletion.rb +29 -0
  67. data/lib/mongoid/extensions/false_class/equality.rb +14 -1
  68. data/lib/mongoid/extensions/hash/criteria_helpers.rb +21 -10
  69. data/lib/mongoid/extensions/hash/scoping.rb +14 -1
  70. data/lib/mongoid/extensions/nil/collectionization.rb +12 -1
  71. data/lib/mongoid/extensions/object/reflections.rb +33 -2
  72. data/lib/mongoid/extensions/object_id/conversions.rb +2 -36
  73. data/lib/mongoid/extensions/proc/scoping.rb +14 -1
  74. data/lib/mongoid/extensions/string/conversions.rb +4 -16
  75. data/lib/mongoid/extensions/string/inflections.rb +35 -14
  76. data/lib/mongoid/extensions/symbol/inflections.rb +38 -12
  77. data/lib/mongoid/extensions/true_class/equality.rb +14 -1
  78. data/lib/mongoid/extras.rb +11 -30
  79. data/lib/mongoid/factory.rb +1 -1
  80. data/lib/mongoid/fields.rb +121 -29
  81. data/lib/mongoid/fields/mappings.rb +36 -0
  82. data/lib/mongoid/fields/serializable.rb +131 -0
  83. data/lib/mongoid/fields/serializable/array.rb +64 -0
  84. data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
  85. data/lib/mongoid/fields/serializable/bignum.rb +10 -0
  86. data/lib/mongoid/fields/serializable/binary.rb +11 -0
  87. data/lib/mongoid/fields/serializable/boolean.rb +44 -0
  88. data/lib/mongoid/fields/serializable/date.rb +51 -0
  89. data/lib/mongoid/fields/serializable/date_time.rb +28 -0
  90. data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
  91. data/lib/mongoid/fields/serializable/float.rb +33 -0
  92. data/lib/mongoid/fields/serializable/foreign_keys/array.rb +56 -0
  93. data/lib/mongoid/fields/serializable/foreign_keys/object.rb +43 -0
  94. data/lib/mongoid/fields/serializable/hash.rb +25 -0
  95. data/lib/mongoid/fields/serializable/integer.rb +33 -0
  96. data/lib/mongoid/fields/serializable/object.rb +11 -0
  97. data/lib/mongoid/fields/serializable/object_id.rb +32 -0
  98. data/lib/mongoid/fields/serializable/range.rb +42 -0
  99. data/lib/mongoid/fields/serializable/set.rb +42 -0
  100. data/lib/mongoid/fields/serializable/string.rb +28 -0
  101. data/lib/mongoid/fields/serializable/symbol.rb +28 -0
  102. data/lib/mongoid/fields/serializable/time.rb +12 -0
  103. data/lib/mongoid/fields/serializable/time_with_zone.rb +12 -0
  104. data/lib/mongoid/fields/serializable/timekeeping.rb +102 -0
  105. data/lib/mongoid/finders.rb +61 -37
  106. data/lib/mongoid/hierarchy.rb +43 -8
  107. data/lib/mongoid/identity_map.rb +106 -0
  108. data/lib/mongoid/indexes.rb +17 -1
  109. data/lib/mongoid/javascript.rb +2 -3
  110. data/lib/mongoid/keys.rb +10 -21
  111. data/lib/mongoid/logger.rb +22 -1
  112. data/lib/mongoid/matchers/all.rb +10 -0
  113. data/lib/mongoid/matchers/default.rb +1 -1
  114. data/lib/mongoid/matchers/exists.rb +10 -0
  115. data/lib/mongoid/matchers/gt.rb +10 -0
  116. data/lib/mongoid/matchers/gte.rb +10 -0
  117. data/lib/mongoid/matchers/in.rb +10 -0
  118. data/lib/mongoid/matchers/lt.rb +10 -0
  119. data/lib/mongoid/matchers/lte.rb +10 -0
  120. data/lib/mongoid/matchers/ne.rb +10 -0
  121. data/lib/mongoid/matchers/nin.rb +10 -0
  122. data/lib/mongoid/matchers/or.rb +7 -4
  123. data/lib/mongoid/matchers/size.rb +10 -0
  124. data/lib/mongoid/multi_database.rb +26 -6
  125. data/lib/mongoid/multi_parameter_attributes.rb +40 -17
  126. data/lib/mongoid/named_scope.rb +1 -2
  127. data/lib/mongoid/nested_attributes.rb +4 -1
  128. data/lib/mongoid/observer.rb +108 -5
  129. data/lib/mongoid/paranoia.rb +26 -26
  130. data/lib/mongoid/persistence.rb +15 -21
  131. data/lib/mongoid/persistence/atomic.rb +135 -0
  132. data/lib/mongoid/persistence/atomic/add_to_set.rb +11 -8
  133. data/lib/mongoid/persistence/atomic/bit.rb +37 -0
  134. data/lib/mongoid/persistence/atomic/inc.rb +9 -6
  135. data/lib/mongoid/persistence/atomic/operation.rb +48 -7
  136. data/lib/mongoid/persistence/atomic/pop.rb +34 -0
  137. data/lib/mongoid/persistence/atomic/pull.rb +34 -0
  138. data/lib/mongoid/persistence/atomic/pull_all.rb +10 -9
  139. data/lib/mongoid/persistence/atomic/push.rb +8 -5
  140. data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
  141. data/lib/mongoid/persistence/atomic/rename.rb +31 -0
  142. data/lib/mongoid/persistence/atomic/set.rb +30 -0
  143. data/lib/mongoid/persistence/atomic/unset.rb +28 -0
  144. data/lib/mongoid/persistence/deletion.rb +32 -0
  145. data/lib/mongoid/persistence/insertion.rb +41 -0
  146. data/lib/mongoid/persistence/modification.rb +37 -0
  147. data/lib/mongoid/persistence/operations.rb +214 -0
  148. data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
  149. data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
  150. data/lib/mongoid/persistence/operations/insert.rb +34 -0
  151. data/lib/mongoid/persistence/operations/remove.rb +33 -0
  152. data/lib/mongoid/persistence/operations/update.rb +53 -0
  153. data/lib/mongoid/railtie.rb +21 -33
  154. data/lib/mongoid/railties/database.rake +12 -12
  155. data/lib/mongoid/relations.rb +9 -5
  156. data/lib/mongoid/relations/accessors.rb +15 -36
  157. data/lib/mongoid/relations/auto_save.rb +2 -2
  158. data/lib/mongoid/relations/binding.rb +28 -1
  159. data/lib/mongoid/relations/bindings/embedded/in.rb +17 -30
  160. data/lib/mongoid/relations/bindings/embedded/many.rb +16 -21
  161. data/lib/mongoid/relations/bindings/embedded/one.rb +11 -16
  162. data/lib/mongoid/relations/bindings/referenced/in.rb +31 -32
  163. data/lib/mongoid/relations/bindings/referenced/many.rb +19 -61
  164. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +15 -63
  165. data/lib/mongoid/relations/bindings/referenced/one.rb +18 -26
  166. data/lib/mongoid/relations/builder.rb +4 -2
  167. data/lib/mongoid/relations/builders.rb +21 -2
  168. data/lib/mongoid/relations/builders/embedded/in.rb +5 -1
  169. data/lib/mongoid/relations/builders/embedded/many.rb +12 -4
  170. data/lib/mongoid/relations/builders/embedded/one.rb +5 -1
  171. data/lib/mongoid/relations/builders/nested_attributes/many.rb +2 -2
  172. data/lib/mongoid/relations/builders/nested_attributes/one.rb +1 -1
  173. data/lib/mongoid/relations/builders/referenced/in.rb +2 -5
  174. data/lib/mongoid/relations/builders/referenced/many.rb +2 -3
  175. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +14 -5
  176. data/lib/mongoid/relations/builders/referenced/one.rb +2 -3
  177. data/lib/mongoid/relations/embedded/atomic.rb +2 -2
  178. data/lib/mongoid/relations/embedded/in.rb +72 -41
  179. data/lib/mongoid/relations/embedded/many.rb +116 -120
  180. data/lib/mongoid/relations/embedded/one.rb +59 -41
  181. data/lib/mongoid/relations/embedded/sort.rb +31 -0
  182. data/lib/mongoid/relations/macros.rb +28 -24
  183. data/lib/mongoid/relations/many.rb +10 -103
  184. data/lib/mongoid/relations/metadata.rb +335 -38
  185. data/lib/mongoid/relations/one.rb +7 -32
  186. data/lib/mongoid/relations/options.rb +47 -0
  187. data/lib/mongoid/relations/proxy.rb +29 -28
  188. data/lib/mongoid/relations/referenced/batch.rb +2 -3
  189. data/lib/mongoid/relations/referenced/in.rb +66 -53
  190. data/lib/mongoid/relations/referenced/many.rb +216 -143
  191. data/lib/mongoid/relations/referenced/many_to_many.rb +132 -163
  192. data/lib/mongoid/relations/referenced/one.rb +76 -58
  193. data/lib/mongoid/relations/synchronization.rb +113 -0
  194. data/lib/mongoid/relations/targets.rb +2 -0
  195. data/lib/mongoid/relations/targets/enumerable.rb +329 -0
  196. data/lib/mongoid/safety.rb +24 -156
  197. data/lib/mongoid/serialization.rb +21 -0
  198. data/lib/mongoid/state.rb +34 -0
  199. data/lib/mongoid/threaded.rb +175 -0
  200. data/lib/mongoid/timestamps/updated.rb +1 -1
  201. data/lib/mongoid/validations.rb +3 -7
  202. data/lib/mongoid/version.rb +1 -1
  203. data/lib/mongoid/versioning.rb +61 -7
  204. data/lib/rack/mongoid.rb +2 -0
  205. data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
  206. data/lib/rails/generators/mongoid/model/model_generator.rb +1 -1
  207. data/lib/rails/generators/mongoid/model/templates/{model.rb → model.rb.tt} +0 -0
  208. data/lib/rails/generators/mongoid/observer/observer_generator.rb +1 -1
  209. data/lib/rails/generators/mongoid/observer/templates/{observer.rb → observer.rb.tt} +0 -0
  210. data/lib/rails/mongoid.rb +17 -17
  211. metadata +136 -102
  212. data/lib/mongoid/atomicity.rb +0 -111
  213. data/lib/mongoid/collections/cyclic_iterator.rb +0 -34
  214. data/lib/mongoid/collections/slaves.rb +0 -61
  215. data/lib/mongoid/extensions/array/conversions.rb +0 -23
  216. data/lib/mongoid/extensions/array/parentization.rb +0 -13
  217. data/lib/mongoid/extensions/big_decimal/conversions.rb +0 -19
  218. data/lib/mongoid/extensions/binary/conversions.rb +0 -17
  219. data/lib/mongoid/extensions/boolean/conversions.rb +0 -27
  220. data/lib/mongoid/extensions/date/conversions.rb +0 -25
  221. data/lib/mongoid/extensions/datetime/conversions.rb +0 -12
  222. data/lib/mongoid/extensions/float/conversions.rb +0 -20
  223. data/lib/mongoid/extensions/hash/conversions.rb +0 -19
  224. data/lib/mongoid/extensions/integer/conversions.rb +0 -20
  225. data/lib/mongoid/extensions/object/conversions.rb +0 -25
  226. data/lib/mongoid/extensions/range/conversions.rb +0 -25
  227. data/lib/mongoid/extensions/set/conversions.rb +0 -20
  228. data/lib/mongoid/extensions/symbol/conversions.rb +0 -21
  229. data/lib/mongoid/extensions/time_conversions.rb +0 -38
  230. data/lib/mongoid/field.rb +0 -162
  231. data/lib/mongoid/paths.rb +0 -61
  232. data/lib/mongoid/persistence/command.rb +0 -71
  233. data/lib/mongoid/persistence/insert.rb +0 -53
  234. data/lib/mongoid/persistence/insert_embedded.rb +0 -43
  235. data/lib/mongoid/persistence/remove.rb +0 -44
  236. data/lib/mongoid/persistence/remove_all.rb +0 -40
  237. data/lib/mongoid/persistence/remove_embedded.rb +0 -48
  238. data/lib/mongoid/persistence/update.rb +0 -77
  239. data/lib/mongoid/safe.rb +0 -23
  240. data/lib/mongoid/validations/referenced.rb +0 -58
@@ -1,11 +1,11 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
+
3
4
  # Include this module to get soft deletion of root level documents.
4
5
  # This will add a deleted_at field to the +Document+, managed automatically.
5
6
  # Potentially incompatible with unique indices. (if collisions with deleted items)
6
7
  #
7
- # To use:
8
- #
8
+ # @example Make a document paranoid.
9
9
  # class Person
10
10
  # include Mongoid::Document
11
11
  # include Mongoid::Paranoia
@@ -20,47 +20,44 @@ module Mongoid #:nodoc:
20
20
  # Delete the paranoid +Document+ from the database completely. This will
21
21
  # run the destroy callbacks.
22
22
  #
23
- # Example:
24
- #
25
- # <tt>document.destroy!</tt>
23
+ # @example Hard destroy the document.
24
+ # document.destroy!
26
25
  def destroy!
27
26
  run_callbacks(:destroy) { delete! }
28
27
  end
29
28
 
30
29
  # Delete the paranoid +Document+ from the database completely.
31
30
  #
32
- # Example:
33
- #
34
- # <tt>document.delete!</tt>
31
+ # @example Hard delete the document.
32
+ # document.delete!
35
33
  def delete!
36
34
  @destroyed = true
37
- Mongoid::Persistence::Remove.new(self).persist
35
+ Persistence::Operations.remove(self).persist
38
36
  end
39
37
 
40
38
  # Delete the +Document+, will set the deleted_at timestamp and not actually
41
39
  # delete it.
42
40
  #
43
- # Example:
41
+ # @example Soft remove the document.
42
+ # document.remove
44
43
  #
45
- # <tt>document.remove</tt>
44
+ # @param [ Hash ] options The database options.
46
45
  #
47
- # Returns:
48
- #
49
- # true
46
+ # @return [ true ] True.
50
47
  def remove(options = {})
51
48
  now = Time.now
52
49
  collection.update({ :_id => id }, { '$set' => { :deleted_at => now } })
53
50
  @attributes["deleted_at"] = now
54
51
  true
55
52
  end
56
-
57
53
  alias :delete :remove
58
54
 
59
55
  # Determines if this document is destroyed.
60
56
  #
61
- # Returns:
57
+ # @example Is the document destroyed?
58
+ # person.destroyed?
62
59
  #
63
- # true if the +Document+ was destroyed.
60
+ # @return [ true, false ] If the document is destroyed.
64
61
  def destroyed?
65
62
  @destroyed || !!deleted_at
66
63
  end
@@ -68,9 +65,8 @@ module Mongoid #:nodoc:
68
65
  # Restores a previously soft-deleted document. Handles this by removing the
69
66
  # deleted_at flag.
70
67
  #
71
- # Example:
72
- #
73
- # <tt>document.restore</tt>
68
+ # @example Restore the document from deleted state.
69
+ # document.restore
74
70
  def restore
75
71
  collection.update({ :_id => id }, { '$unset' => { :deleted_at => true } })
76
72
  @attributes.delete("deleted_at")
@@ -81,20 +77,24 @@ module Mongoid #:nodoc:
81
77
  # Override the default +Criteria+ accessor to only get existing
82
78
  # documents. Passes all arguments up to +NamedScope.criteria+
83
79
  #
84
- # Returns:
80
+ # @example Override the criteria.
81
+ # Person.criteria
82
+ #
83
+ # @param [ Array ] args The arguments.
85
84
  #
86
- # A +Criteria+ for deleted_at not existing.
85
+ # @return [ Criteria ] The paranoid compliant criteria.
87
86
  def criteria(*args)
88
87
  super.where(:deleted_at.exists => false)
89
88
  end
90
89
 
91
90
  # Find deleted documents
92
91
  #
93
- # Examples:
92
+ # @example Find deleted documents.
93
+ # Person.deleted
94
+ # Company.first.employees.deleted
95
+ # Person.deleted.find("4c188dea7b17235a2a000001").first
94
96
  #
95
- # <tt>Person.deleted</tt> # all deleted employees
96
- # <tt>Company.first.employees.deleted</tt> # works with a join
97
- # <tt>Person.deleted.find("4c188dea7b17235a2a000001").first</tt>
97
+ # @return [ Criteria ] The deleted criteria.
98
98
  def deleted
99
99
  where(:deleted_at.exists => true)
100
100
  end
@@ -1,12 +1,9 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/persistence/atomic"
3
- require "mongoid/persistence/command"
4
- require "mongoid/persistence/insert"
5
- require "mongoid/persistence/insert_embedded"
6
- require "mongoid/persistence/remove"
7
- require "mongoid/persistence/remove_all"
8
- require "mongoid/persistence/remove_embedded"
9
- require "mongoid/persistence/update"
3
+ require "mongoid/persistence/deletion"
4
+ require "mongoid/persistence/insertion"
5
+ require "mongoid/persistence/modification"
6
+ require "mongoid/persistence/operations"
10
7
 
11
8
  module Mongoid #:nodoc:
12
9
 
@@ -44,7 +41,7 @@ module Mongoid #:nodoc:
44
41
  #
45
42
  # @return [ Document ] The persisted document.
46
43
  def insert(options = {})
47
- Insert.new(self, options).persist
44
+ Operations.insert(self, options).persist
48
45
  end
49
46
 
50
47
  # Remove the document from the datbase.
@@ -56,11 +53,7 @@ module Mongoid #:nodoc:
56
53
  #
57
54
  # @return [ TrueClass ] True.
58
55
  def remove(options = {})
59
- if Remove.new(self, options).persist
60
- attributes.freeze
61
- self.destroyed = true
62
- cascade!
63
- end; true
56
+ Operations.remove(self, options).persist
64
57
  end
65
58
  alias :delete :remove
66
59
 
@@ -86,7 +79,7 @@ module Mongoid #:nodoc:
86
79
  #
87
80
  # @return [ true, false ] True if succeeded, false if not.
88
81
  def update(options = {})
89
- Update.new(self, options).persist
82
+ Operations.update(self, options).persist
90
83
  end
91
84
 
92
85
  # Update a single attribute and persist the entire document.
@@ -165,7 +158,7 @@ module Mongoid #:nodoc:
165
158
  #
166
159
  # @return [ Document ] The newly created document.
167
160
  def create(attributes = {}, &block)
168
- new(attributes, &block).tap(&:save)
161
+ new(attributes, &block).tap { |doc| doc.save }
169
162
  end
170
163
 
171
164
  # Create a new document. This will instantiate a new document and
@@ -198,12 +191,13 @@ module Mongoid #:nodoc:
198
191
  # @param [ Hash ] conditions Optional conditions to delete by.
199
192
  #
200
193
  # @return [ Integer ] The number of documents deleted.
201
- def delete_all(conditions = {})
202
- RemoveAll.new(
203
- self,
204
- { :validate => false },
205
- conditions[:conditions] || {}
206
- ).persist
194
+ def delete_all(conditions = nil)
195
+ selector = (conditions || {})[:conditions] || {}
196
+ selector.merge!(:_type => name) if hereditary?
197
+ collection.find(selector).count.tap do
198
+ collection.remove(selector, Safety.merge_safety_options)
199
+ Threaded.clear_safety_options!
200
+ end
207
201
  end
208
202
 
209
203
  # Delete all documents given the supplied conditions. If no conditions
@@ -1,9 +1,16 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/persistence/atomic/operation"
3
3
  require "mongoid/persistence/atomic/add_to_set"
4
+ require "mongoid/persistence/atomic/bit"
4
5
  require "mongoid/persistence/atomic/inc"
6
+ require "mongoid/persistence/atomic/pop"
7
+ require "mongoid/persistence/atomic/pull"
5
8
  require "mongoid/persistence/atomic/pull_all"
6
9
  require "mongoid/persistence/atomic/push"
10
+ require "mongoid/persistence/atomic/push_all"
11
+ require "mongoid/persistence/atomic/rename"
12
+ require "mongoid/persistence/atomic/set"
13
+ require "mongoid/persistence/atomic/unset"
7
14
 
8
15
  module Mongoid #:nodoc:
9
16
  module Persistence #:nodoc:
@@ -31,6 +38,29 @@ module Mongoid #:nodoc:
31
38
  AddToSet.new(self, field, value, options).persist
32
39
  end
33
40
 
41
+ # Performs an atomic $bit operation on the field with the provided hash
42
+ # of bitwise ops to execute in order.
43
+ #
44
+ # @example Execute a bitwise and on the field.
45
+ # person.bit(:age, { :and => 12 })
46
+ #
47
+ # @example Execute a bitwise or on the field.
48
+ # person.bit(:age, { :or => 12 })
49
+ #
50
+ # @example Execute a chain of bitwise operations.
51
+ # person.bit(:age, { :and => 10, :or => 12 })
52
+ #
53
+ # @param [ Symbol ] field The name of the field.
54
+ # @param [ Hash ] value The bitwise operations to perform.
55
+ # @param [ Hash ] options The mongo persistence options.
56
+ #
57
+ # @return [ Integer ] The new value of the field.
58
+ #
59
+ # @since 2.1.0
60
+ def bit(field, value, options = {})
61
+ Bit.new(self, field, value, options).persist
62
+ end
63
+
34
64
  # Performs an atomic $inc of the provided value on the supplied
35
65
  # field. If the field does not exist it will be initialized as
36
66
  # the provided value.
@@ -49,6 +79,45 @@ module Mongoid #:nodoc:
49
79
  Inc.new(self, field, value, options).persist
50
80
  end
51
81
 
82
+ # Performs an atomic $pop of the provided value on the supplied
83
+ # field.
84
+ #
85
+ # @example Pop the last value from the array.
86
+ # person.pop(:aliases, 1)
87
+ #
88
+ # @example Pop the first value from the array.
89
+ # person.pop(:aliases, -1)
90
+ #
91
+ # @param [ Symbol ] field The name of the field.
92
+ # @param [ Integer ] value Whether to pop the first or last.
93
+ # @param [ Hash ] options The mongo persistence options.
94
+ #
95
+ # @return [ Array<Object> ] The new value of the field.
96
+ #
97
+ # @since 2.1.0
98
+ def pop(field, value, options = {})
99
+ Pop.new(self, field, value, options).persist
100
+ end
101
+
102
+ # Performs an atomic $pull of the provided value on the supplied
103
+ # field.
104
+ #
105
+ # @note Support for a $pull with an expression is not yet supported.
106
+ #
107
+ # @example Pull the value from the field.
108
+ # person.pull(:aliases, "Bond")
109
+ #
110
+ # @param [ Symbol ] field The name of the field.
111
+ # @param [ Object ] value The value to pull.
112
+ # @param [ Hash ] options The mongo persistence options.
113
+ #
114
+ # @return [ Array<Object> ] The new value of the field.
115
+ #
116
+ # @since 2.1.0
117
+ def pull(field, value, options = {})
118
+ Pull.new(self, field, value, options).persist
119
+ end
120
+
52
121
  # Performs an atomic $pullAll of the provided value on the supplied
53
122
  # field. If the field does not exist it will be initialized as an
54
123
  # empty array.
@@ -83,6 +152,72 @@ module Mongoid #:nodoc:
83
152
  def push(field, value, options = {})
84
153
  Push.new(self, field, value, options).persist
85
154
  end
155
+
156
+ # Performs an atomic $pushAll of the provided value on the supplied field. If
157
+ # the field does not exist it will be initialized as an empty array.
158
+ #
159
+ # @example Push the values onto the field.
160
+ # person.push_all(:aliases, [ "Bond", "James" ])
161
+ #
162
+ # @param [ Symbol ] field The name of the field.
163
+ # @param [ Array<Object> ] value The values to push.
164
+ # @param [ Hash ] options The mongo persistence options.
165
+ #
166
+ # @return [ Array<Object> ] The new value of the field.
167
+ #
168
+ # @since 2.1.0
169
+ def push_all(field, value, options = {})
170
+ PushAll.new(self, field, value, options).persist
171
+ end
172
+
173
+ # Performs the atomic $rename from the old field to the new field name.
174
+ #
175
+ # @example Rename the field.
176
+ # person.rename(:age, :years)
177
+ #
178
+ # @param [ Symbol ] field The old field name.
179
+ # @param [ Symbol ] value The new field name.
180
+ # @param [ Hash ] options The mongo persistence options.
181
+ #
182
+ # @return [ Object ] The value of the new field.
183
+ #
184
+ # @since 2.1.0
185
+ def rename(field, value, options = {})
186
+ Rename.new(self, field, value, options).persist
187
+ end
188
+
189
+ # Performs an atomic $set of the provided value on the supplied
190
+ # field. If the field does not exist it will be initialized as
191
+ # the provided value.
192
+ #
193
+ # @example Set a field.
194
+ # person.set(:score, 2)
195
+ #
196
+ # @param [ Symbol ] field The name of the field.
197
+ # @param [ Integer ] value The value to set.
198
+ # @param [ Hash ] options The mongo persistence options.
199
+ #
200
+ # @return [ Array<Object> ] The new value of the field.
201
+ #
202
+ # @since 2.1.0
203
+ def set(field, value = nil, options = {})
204
+ Set.new(self, field, value, options).persist
205
+ end
206
+
207
+ # Performs the atomic $unset on the supplied field.
208
+ #
209
+ # @example Remove the field.
210
+ # person.unset(:age)
211
+ #
212
+ # @param [ Symbol ] field The field name.
213
+ # @param [ Hash ] options The mongo persistence options.
214
+ #
215
+ # @return [ nil ] Always nil.
216
+ #
217
+ # @since 2.1.0
218
+ def unset(field, options = {})
219
+ Unset.new(self, field, 1, options).persist
220
+ end
86
221
  end
87
222
  end
88
223
  end
@@ -5,7 +5,8 @@ module Mongoid #:nodoc:
5
5
 
6
6
  # This class provides the ability to perform an explicit $addToSet
7
7
  # modification on a specific field.
8
- class AddToSet < Operation
8
+ class AddToSet
9
+ include Operation
9
10
 
10
11
  # Sends the atomic $addToSet operation to the database.
11
12
  #
@@ -16,13 +17,15 @@ module Mongoid #:nodoc:
16
17
  #
17
18
  # @since 2.0.0
18
19
  def persist
19
- document[field] = [] unless document[field]
20
- values = document.send(field)
21
- values.push(value) unless values.include?(value)
22
- values.tap do
23
- if document.persisted?
24
- document.collection.update(document._selector, operation("$addToSet"), options)
25
- document.changes.delete(field.to_s)
20
+ prepare do
21
+ document[field] = [] unless document[field]
22
+ values = document.send(field)
23
+ values.push(value) unless values.include?(value)
24
+ values.tap do
25
+ if document.persisted?
26
+ collection.update(document.atomic_selector, operation("$addToSet"), options)
27
+ document.remove_change(field)
28
+ end
26
29
  end
27
30
  end
28
31
  end
@@ -0,0 +1,37 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Persistence #:nodoc:
4
+ module Atomic #:nodoc:
5
+
6
+ # This operation is for performing $bit atomic operations against the
7
+ # database.
8
+ class Bit
9
+ include Operation
10
+
11
+ # Execute the bitwise operation. This correlates to a $bit in MongoDB.
12
+ #
13
+ # @example Execute the op.
14
+ # bit.persist
15
+ #
16
+ # @return [ Integer ] The new value.
17
+ #
18
+ # @since 2.1.0
19
+ def persist
20
+ prepare do
21
+ current = document[field]
22
+ return nil unless current
23
+ document[field] = value.inject(current) do |result, (bit, val)|
24
+ result = result & val if bit.to_s == "and"
25
+ result = result | val if bit.to_s == "or"
26
+ result
27
+ end
28
+ document[field].tap do
29
+ collection.update(document.atomic_selector, operation("$bit"), options)
30
+ document.remove_change(field)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -4,7 +4,8 @@ module Mongoid #:nodoc:
4
4
  module Atomic #:nodoc:
5
5
 
6
6
  # This class provides atomic $inc behaviour.
7
- class Inc < Operation
7
+ class Inc
8
+ include Operation
8
9
 
9
10
  # Sends the atomic $inc operation to the database.
10
11
  #
@@ -15,11 +16,13 @@ module Mongoid #:nodoc:
15
16
  #
16
17
  # @since 2.0.0
17
18
  def persist
18
- current = document[field] || 0
19
- document[field] = current + value
20
- document[field].tap do
21
- document.collection.update(document._selector, operation("$inc"), options)
22
- document.changes.delete(field.to_s)
19
+ prepare do
20
+ current = document[field] || 0
21
+ document[field] = current + value
22
+ document[field].tap do
23
+ collection.update(document.atomic_selector, operation("$inc"), options)
24
+ document.remove_change(field)
25
+ end
23
26
  end
24
27
  end
25
28
  end