mongoid-multi-db 3.0.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 (276) hide show
  1. data/CHANGELOG.md +615 -0
  2. data/LICENSE +20 -0
  3. data/README.md +62 -0
  4. data/Rakefile +49 -0
  5. data/lib/config/locales/bg.yml +54 -0
  6. data/lib/config/locales/de.yml +54 -0
  7. data/lib/config/locales/en-GB.yml +55 -0
  8. data/lib/config/locales/en.yml +55 -0
  9. data/lib/config/locales/es.yml +52 -0
  10. data/lib/config/locales/fr.yml +55 -0
  11. data/lib/config/locales/hi.yml +46 -0
  12. data/lib/config/locales/hu.yml +57 -0
  13. data/lib/config/locales/id.yml +55 -0
  14. data/lib/config/locales/it.yml +52 -0
  15. data/lib/config/locales/ja.yml +50 -0
  16. data/lib/config/locales/kr.yml +47 -0
  17. data/lib/config/locales/nl.yml +52 -0
  18. data/lib/config/locales/pl.yml +52 -0
  19. data/lib/config/locales/pt-BR.yml +53 -0
  20. data/lib/config/locales/pt.yml +53 -0
  21. data/lib/config/locales/ro.yml +59 -0
  22. data/lib/config/locales/ru.yml +54 -0
  23. data/lib/config/locales/sv.yml +53 -0
  24. data/lib/config/locales/vi.yml +55 -0
  25. data/lib/config/locales/zh-CN.yml +46 -0
  26. data/lib/mongoid.rb +148 -0
  27. data/lib/mongoid/atomic.rb +230 -0
  28. data/lib/mongoid/atomic/modifiers.rb +243 -0
  29. data/lib/mongoid/atomic/paths.rb +3 -0
  30. data/lib/mongoid/atomic/paths/embedded.rb +43 -0
  31. data/lib/mongoid/atomic/paths/embedded/many.rb +44 -0
  32. data/lib/mongoid/atomic/paths/embedded/one.rb +43 -0
  33. data/lib/mongoid/atomic/paths/root.rb +40 -0
  34. data/lib/mongoid/attributes.rb +234 -0
  35. data/lib/mongoid/attributes/processing.rb +146 -0
  36. data/lib/mongoid/callbacks.rb +135 -0
  37. data/lib/mongoid/collection.rb +153 -0
  38. data/lib/mongoid/collection_proxy.rb +59 -0
  39. data/lib/mongoid/collections.rb +120 -0
  40. data/lib/mongoid/collections/master.rb +45 -0
  41. data/lib/mongoid/collections/operations.rb +44 -0
  42. data/lib/mongoid/collections/retry.rb +46 -0
  43. data/lib/mongoid/components.rb +96 -0
  44. data/lib/mongoid/config.rb +347 -0
  45. data/lib/mongoid/config/database.rb +186 -0
  46. data/lib/mongoid/config/replset_database.rb +82 -0
  47. data/lib/mongoid/connection_proxy.rb +30 -0
  48. data/lib/mongoid/contexts.rb +25 -0
  49. data/lib/mongoid/contexts/enumerable.rb +288 -0
  50. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  51. data/lib/mongoid/contexts/mongo.rb +409 -0
  52. data/lib/mongoid/copyable.rb +48 -0
  53. data/lib/mongoid/criteria.rb +418 -0
  54. data/lib/mongoid/criterion/builder.rb +34 -0
  55. data/lib/mongoid/criterion/complex.rb +84 -0
  56. data/lib/mongoid/criterion/creational.rb +34 -0
  57. data/lib/mongoid/criterion/exclusion.rb +108 -0
  58. data/lib/mongoid/criterion/inclusion.rb +305 -0
  59. data/lib/mongoid/criterion/inspection.rb +22 -0
  60. data/lib/mongoid/criterion/optional.rb +232 -0
  61. data/lib/mongoid/criterion/selector.rb +153 -0
  62. data/lib/mongoid/cursor.rb +86 -0
  63. data/lib/mongoid/database_proxy.rb +97 -0
  64. data/lib/mongoid/default_scope.rb +36 -0
  65. data/lib/mongoid/dirty.rb +110 -0
  66. data/lib/mongoid/document.rb +280 -0
  67. data/lib/mongoid/errors.rb +17 -0
  68. data/lib/mongoid/errors/callback.rb +26 -0
  69. data/lib/mongoid/errors/document_not_found.rb +28 -0
  70. data/lib/mongoid/errors/eager_load.rb +25 -0
  71. data/lib/mongoid/errors/invalid_collection.rb +18 -0
  72. data/lib/mongoid/errors/invalid_database.rb +19 -0
  73. data/lib/mongoid/errors/invalid_field.rb +18 -0
  74. data/lib/mongoid/errors/invalid_find.rb +19 -0
  75. data/lib/mongoid/errors/invalid_options.rb +28 -0
  76. data/lib/mongoid/errors/invalid_time.rb +25 -0
  77. data/lib/mongoid/errors/invalid_type.rb +25 -0
  78. data/lib/mongoid/errors/mixed_relations.rb +37 -0
  79. data/lib/mongoid/errors/mongoid_error.rb +26 -0
  80. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +20 -0
  81. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  82. data/lib/mongoid/errors/unsupported_version.rb +20 -0
  83. data/lib/mongoid/errors/validations.rb +23 -0
  84. data/lib/mongoid/extensions.rb +82 -0
  85. data/lib/mongoid/extensions/array/deletion.rb +29 -0
  86. data/lib/mongoid/extensions/false_class/equality.rb +26 -0
  87. data/lib/mongoid/extensions/hash/criteria_helpers.rb +45 -0
  88. data/lib/mongoid/extensions/hash/scoping.rb +25 -0
  89. data/lib/mongoid/extensions/integer/checks.rb +23 -0
  90. data/lib/mongoid/extensions/nil/collectionization.rb +23 -0
  91. data/lib/mongoid/extensions/object/checks.rb +29 -0
  92. data/lib/mongoid/extensions/object/reflections.rb +48 -0
  93. data/lib/mongoid/extensions/object/substitutable.rb +15 -0
  94. data/lib/mongoid/extensions/object/yoda.rb +44 -0
  95. data/lib/mongoid/extensions/object_id/conversions.rb +60 -0
  96. data/lib/mongoid/extensions/proc/scoping.rb +25 -0
  97. data/lib/mongoid/extensions/string/checks.rb +36 -0
  98. data/lib/mongoid/extensions/string/conversions.rb +22 -0
  99. data/lib/mongoid/extensions/string/inflections.rb +118 -0
  100. data/lib/mongoid/extensions/symbol/checks.rb +23 -0
  101. data/lib/mongoid/extensions/symbol/inflections.rb +66 -0
  102. data/lib/mongoid/extensions/true_class/equality.rb +26 -0
  103. data/lib/mongoid/extras.rb +31 -0
  104. data/lib/mongoid/factory.rb +46 -0
  105. data/lib/mongoid/fields.rb +332 -0
  106. data/lib/mongoid/fields/mappings.rb +41 -0
  107. data/lib/mongoid/fields/serializable.rb +201 -0
  108. data/lib/mongoid/fields/serializable/array.rb +49 -0
  109. data/lib/mongoid/fields/serializable/big_decimal.rb +42 -0
  110. data/lib/mongoid/fields/serializable/bignum.rb +10 -0
  111. data/lib/mongoid/fields/serializable/binary.rb +11 -0
  112. data/lib/mongoid/fields/serializable/boolean.rb +43 -0
  113. data/lib/mongoid/fields/serializable/date.rb +51 -0
  114. data/lib/mongoid/fields/serializable/date_time.rb +28 -0
  115. data/lib/mongoid/fields/serializable/fixnum.rb +10 -0
  116. data/lib/mongoid/fields/serializable/float.rb +32 -0
  117. data/lib/mongoid/fields/serializable/foreign_keys/array.rb +42 -0
  118. data/lib/mongoid/fields/serializable/foreign_keys/object.rb +47 -0
  119. data/lib/mongoid/fields/serializable/hash.rb +11 -0
  120. data/lib/mongoid/fields/serializable/integer.rb +44 -0
  121. data/lib/mongoid/fields/serializable/localized.rb +41 -0
  122. data/lib/mongoid/fields/serializable/nil_class.rb +38 -0
  123. data/lib/mongoid/fields/serializable/object.rb +11 -0
  124. data/lib/mongoid/fields/serializable/object_id.rb +31 -0
  125. data/lib/mongoid/fields/serializable/range.rb +42 -0
  126. data/lib/mongoid/fields/serializable/set.rb +42 -0
  127. data/lib/mongoid/fields/serializable/string.rb +27 -0
  128. data/lib/mongoid/fields/serializable/symbol.rb +27 -0
  129. data/lib/mongoid/fields/serializable/time.rb +23 -0
  130. data/lib/mongoid/fields/serializable/time_with_zone.rb +23 -0
  131. data/lib/mongoid/fields/serializable/timekeeping.rb +106 -0
  132. data/lib/mongoid/finders.rb +152 -0
  133. data/lib/mongoid/hierarchy.rb +120 -0
  134. data/lib/mongoid/identity.rb +92 -0
  135. data/lib/mongoid/identity_map.rb +119 -0
  136. data/lib/mongoid/indexes.rb +54 -0
  137. data/lib/mongoid/inspection.rb +54 -0
  138. data/lib/mongoid/javascript.rb +20 -0
  139. data/lib/mongoid/javascript/functions.yml +63 -0
  140. data/lib/mongoid/json.rb +16 -0
  141. data/lib/mongoid/keys.rb +144 -0
  142. data/lib/mongoid/logger.rb +39 -0
  143. data/lib/mongoid/matchers.rb +32 -0
  144. data/lib/mongoid/matchers/all.rb +21 -0
  145. data/lib/mongoid/matchers/and.rb +30 -0
  146. data/lib/mongoid/matchers/default.rb +70 -0
  147. data/lib/mongoid/matchers/exists.rb +23 -0
  148. data/lib/mongoid/matchers/gt.rb +21 -0
  149. data/lib/mongoid/matchers/gte.rb +21 -0
  150. data/lib/mongoid/matchers/in.rb +21 -0
  151. data/lib/mongoid/matchers/lt.rb +21 -0
  152. data/lib/mongoid/matchers/lte.rb +21 -0
  153. data/lib/mongoid/matchers/ne.rb +21 -0
  154. data/lib/mongoid/matchers/nin.rb +21 -0
  155. data/lib/mongoid/matchers/or.rb +33 -0
  156. data/lib/mongoid/matchers/size.rb +21 -0
  157. data/lib/mongoid/matchers/strategies.rb +93 -0
  158. data/lib/mongoid/multi_database.rb +31 -0
  159. data/lib/mongoid/multi_parameter_attributes.rb +106 -0
  160. data/lib/mongoid/named_scope.rb +146 -0
  161. data/lib/mongoid/nested_attributes.rb +54 -0
  162. data/lib/mongoid/observer.rb +170 -0
  163. data/lib/mongoid/paranoia.rb +158 -0
  164. data/lib/mongoid/persistence.rb +264 -0
  165. data/lib/mongoid/persistence/atomic.rb +223 -0
  166. data/lib/mongoid/persistence/atomic/add_to_set.rb +35 -0
  167. data/lib/mongoid/persistence/atomic/bit.rb +37 -0
  168. data/lib/mongoid/persistence/atomic/inc.rb +31 -0
  169. data/lib/mongoid/persistence/atomic/operation.rb +85 -0
  170. data/lib/mongoid/persistence/atomic/pop.rb +34 -0
  171. data/lib/mongoid/persistence/atomic/pull.rb +34 -0
  172. data/lib/mongoid/persistence/atomic/pull_all.rb +34 -0
  173. data/lib/mongoid/persistence/atomic/push.rb +31 -0
  174. data/lib/mongoid/persistence/atomic/push_all.rb +31 -0
  175. data/lib/mongoid/persistence/atomic/rename.rb +31 -0
  176. data/lib/mongoid/persistence/atomic/sets.rb +30 -0
  177. data/lib/mongoid/persistence/atomic/unset.rb +28 -0
  178. data/lib/mongoid/persistence/deletion.rb +32 -0
  179. data/lib/mongoid/persistence/insertion.rb +41 -0
  180. data/lib/mongoid/persistence/modification.rb +37 -0
  181. data/lib/mongoid/persistence/operations.rb +211 -0
  182. data/lib/mongoid/persistence/operations/embedded/insert.rb +42 -0
  183. data/lib/mongoid/persistence/operations/embedded/remove.rb +40 -0
  184. data/lib/mongoid/persistence/operations/insert.rb +34 -0
  185. data/lib/mongoid/persistence/operations/remove.rb +33 -0
  186. data/lib/mongoid/persistence/operations/update.rb +64 -0
  187. data/lib/mongoid/railtie.rb +126 -0
  188. data/lib/mongoid/railties/database.rake +182 -0
  189. data/lib/mongoid/railties/document.rb +12 -0
  190. data/lib/mongoid/relations.rb +144 -0
  191. data/lib/mongoid/relations/accessors.rb +138 -0
  192. data/lib/mongoid/relations/auto_save.rb +38 -0
  193. data/lib/mongoid/relations/binding.rb +26 -0
  194. data/lib/mongoid/relations/bindings.rb +9 -0
  195. data/lib/mongoid/relations/bindings/embedded/in.rb +69 -0
  196. data/lib/mongoid/relations/bindings/embedded/many.rb +93 -0
  197. data/lib/mongoid/relations/bindings/embedded/one.rb +61 -0
  198. data/lib/mongoid/relations/bindings/referenced/in.rb +76 -0
  199. data/lib/mongoid/relations/bindings/referenced/many.rb +54 -0
  200. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +51 -0
  201. data/lib/mongoid/relations/bindings/referenced/one.rb +58 -0
  202. data/lib/mongoid/relations/builder.rb +57 -0
  203. data/lib/mongoid/relations/builders.rb +83 -0
  204. data/lib/mongoid/relations/builders/embedded/in.rb +29 -0
  205. data/lib/mongoid/relations/builders/embedded/many.rb +40 -0
  206. data/lib/mongoid/relations/builders/embedded/one.rb +30 -0
  207. data/lib/mongoid/relations/builders/nested_attributes/many.rb +110 -0
  208. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  209. data/lib/mongoid/relations/builders/referenced/in.rb +26 -0
  210. data/lib/mongoid/relations/builders/referenced/many.rb +27 -0
  211. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +38 -0
  212. data/lib/mongoid/relations/builders/referenced/one.rb +26 -0
  213. data/lib/mongoid/relations/cascading.rb +56 -0
  214. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  215. data/lib/mongoid/relations/cascading/destroy.rb +26 -0
  216. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  217. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  218. data/lib/mongoid/relations/constraint.rb +42 -0
  219. data/lib/mongoid/relations/conversions.rb +35 -0
  220. data/lib/mongoid/relations/cyclic.rb +103 -0
  221. data/lib/mongoid/relations/embedded/atomic.rb +89 -0
  222. data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
  223. data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
  224. data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
  225. data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
  226. data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
  227. data/lib/mongoid/relations/embedded/in.rb +220 -0
  228. data/lib/mongoid/relations/embedded/many.rb +560 -0
  229. data/lib/mongoid/relations/embedded/one.rb +206 -0
  230. data/lib/mongoid/relations/embedded/sort.rb +31 -0
  231. data/lib/mongoid/relations/macros.rb +310 -0
  232. data/lib/mongoid/relations/many.rb +135 -0
  233. data/lib/mongoid/relations/metadata.rb +919 -0
  234. data/lib/mongoid/relations/nested_builder.rb +75 -0
  235. data/lib/mongoid/relations/one.rb +36 -0
  236. data/lib/mongoid/relations/options.rb +47 -0
  237. data/lib/mongoid/relations/polymorphic.rb +40 -0
  238. data/lib/mongoid/relations/proxy.rb +145 -0
  239. data/lib/mongoid/relations/referenced/batch.rb +72 -0
  240. data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
  241. data/lib/mongoid/relations/referenced/in.rb +262 -0
  242. data/lib/mongoid/relations/referenced/many.rb +623 -0
  243. data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
  244. data/lib/mongoid/relations/referenced/one.rb +272 -0
  245. data/lib/mongoid/relations/reflections.rb +62 -0
  246. data/lib/mongoid/relations/synchronization.rb +153 -0
  247. data/lib/mongoid/relations/targets.rb +2 -0
  248. data/lib/mongoid/relations/targets/enumerable.rb +372 -0
  249. data/lib/mongoid/reloading.rb +91 -0
  250. data/lib/mongoid/safety.rb +105 -0
  251. data/lib/mongoid/scope.rb +31 -0
  252. data/lib/mongoid/serialization.rb +134 -0
  253. data/lib/mongoid/sharding.rb +61 -0
  254. data/lib/mongoid/state.rb +97 -0
  255. data/lib/mongoid/threaded.rb +530 -0
  256. data/lib/mongoid/threaded/lifecycle.rb +192 -0
  257. data/lib/mongoid/timestamps.rb +15 -0
  258. data/lib/mongoid/timestamps/created.rb +24 -0
  259. data/lib/mongoid/timestamps/timeless.rb +50 -0
  260. data/lib/mongoid/timestamps/updated.rb +26 -0
  261. data/lib/mongoid/validations.rb +140 -0
  262. data/lib/mongoid/validations/associated.rb +46 -0
  263. data/lib/mongoid/validations/uniqueness.rb +145 -0
  264. data/lib/mongoid/version.rb +4 -0
  265. data/lib/mongoid/versioning.rb +185 -0
  266. data/lib/rack/mongoid.rb +2 -0
  267. data/lib/rack/mongoid/middleware/identity_map.rb +38 -0
  268. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  269. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
  270. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  271. data/lib/rails/generators/mongoid/model/templates/model.rb.tt +19 -0
  272. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  273. data/lib/rails/generators/mongoid/observer/templates/observer.rb.tt +4 -0
  274. data/lib/rails/generators/mongoid_generator.rb +70 -0
  275. data/lib/rails/mongoid.rb +91 -0
  276. metadata +465 -0
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Relations #:nodoc:
4
+
5
+ # Contains utility methods for object id conversion.
6
+ module Conversions
7
+ extend self
8
+
9
+ # Mark the provided object as unconvertable to bson or not, and always
10
+ # return the provided object.
11
+ #
12
+ # @example Flag the object.
13
+ # Conversions.flag(metadata, 15)
14
+ #
15
+ # @param [ Object ] object The object to flag.
16
+ # @param [ Metadata ] The relation metadata.
17
+ #
18
+ # @return [ Object ] The provided object.
19
+ #
20
+ # @since 2.3.0
21
+ def flag(object, metadata)
22
+ inverse = metadata.inverse_klass
23
+ if inverse.using_object_ids? || object.is_a?(BSON::ObjectId)
24
+ object
25
+ else
26
+ object.tap do |obj|
27
+ if obj.is_a?(String)
28
+ obj.unconvertable_to_bson = true
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,103 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+
5
+ # This module provides convenience macros for using cyclic embedded
6
+ # relations.
7
+ module Cyclic
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ class_attribute :cyclic
12
+ end
13
+
14
+ module ClassMethods #:nodoc:
15
+
16
+ # Create a cyclic embedded relation that creates a tree hierarchy for
17
+ # the document and many embedded child documents.
18
+ #
19
+ # @example Set up a recursive embeds many.
20
+ #
21
+ # class Role
22
+ # include Mongoid::Document
23
+ # recursively_embeds_many
24
+ # end
25
+ #
26
+ # @example The previous example is a shorcut for this.
27
+ #
28
+ # class Role
29
+ # include Mongoid::Document
30
+ # embeds_many :child_roles, :class_name => "Role", :cyclic => true
31
+ # embedded_in :parent_role, :class_name => "Role", :cyclic => true
32
+ # end
33
+ #
34
+ # This provides the default nomenclature for accessing a parent document
35
+ # or its children.
36
+ #
37
+ # @since 2.0.0.rc.1
38
+ def recursively_embeds_many
39
+ self.cyclic = true
40
+ embeds_many cyclic_child_name, :class_name => self.name, :cyclic => true
41
+ embedded_in cyclic_parent_name, :class_name => self.name, :cyclic => true
42
+ end
43
+
44
+ # Create a cyclic embedded relation that creates a single self
45
+ # referencing relationship for a parent and a single child.
46
+ #
47
+ # @example Set up a recursive embeds one.
48
+ #
49
+ # class Role
50
+ # include Mongoid::Document
51
+ # recursively_embeds_one
52
+ # end
53
+ #
54
+ # @example The previous example is a shorcut for this.
55
+ #
56
+ # class Role
57
+ # include Mongoid::Document
58
+ # embeds_one :child_role, :class_name => "Role", :cyclic => true
59
+ # embedded_in :parent_role, :class_name => "Role", :cyclic => true
60
+ # end
61
+ #
62
+ # This provides the default nomenclature for accessing a parent document
63
+ # or its children.
64
+ #
65
+ # @since 2.0.0.rc.1
66
+ def recursively_embeds_one
67
+ self.cyclic = true
68
+ embeds_one cyclic_child_name(false), :class_name => self.name, :cyclic => true
69
+ embedded_in cyclic_parent_name, :class_name => self.name, :cyclic => true
70
+ end
71
+
72
+ private
73
+
74
+ # Determines the parent name given the class.
75
+ #
76
+ # @example Determine the parent name.
77
+ # Role.cyclic_parent_name
78
+ #
79
+ # @return [ String ] "parent_" plus the class name underscored.
80
+ #
81
+ # @since 2.0.0.rc.1
82
+ def cyclic_parent_name
83
+ ("parent_" << self.name.demodulize.underscore.singularize).to_sym
84
+ end
85
+
86
+ # Determines the child name given the class.
87
+ #
88
+ # @example Determine the child name.
89
+ # Role.cyclic_child_name
90
+ #
91
+ # @param [ true, false ] many Is the a many relation?
92
+ #
93
+ # @return [ String ] "child_" plus the class name underscored in
94
+ # singular or plural form.
95
+ #
96
+ # @since 2.0.0.rc.1
97
+ def cyclic_child_name(many = true)
98
+ ("child_" << self.name.demodulize.underscore.send(many ? :pluralize : :singularize)).to_sym
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,89 @@
1
+ # encoding: utf-8
2
+ require "mongoid/relations/embedded/atomic/operation"
3
+ require "mongoid/relations/embedded/atomic/pull"
4
+ require "mongoid/relations/embedded/atomic/push_all"
5
+ require "mongoid/relations/embedded/atomic/set"
6
+ require "mongoid/relations/embedded/atomic/unset"
7
+
8
+ module Mongoid #:nodoc:
9
+ module Relations #:nodoc:
10
+ module Embedded #:nodoc:
11
+
12
+ # This module provides the ability for calls to be declared atomic.
13
+ module Atomic
14
+
15
+ MODIFIERS = {
16
+ :$pull => Pull,
17
+ :$pushAll => PushAll,
18
+ :$set => Set,
19
+ :$unset => Unset
20
+ }
21
+
22
+ private
23
+
24
+ # Executes a block of commands in an atomic fashion. Mongoid will
25
+ # intercept all database upserts while in this block and combine them
26
+ # into a single database call. When the block concludes the atomic
27
+ # update will occur.
28
+ #
29
+ # Since the collection is accessed through the class it would not be
30
+ # thread safe to give it state so we access the atomic updater via the
31
+ # current thread.
32
+ #
33
+ # @note This operation is not safe when attemping to do illegal updates
34
+ # for different objects or collections, since the updator is not
35
+ # scoped on the thread. This is meant for Mongoid internal use only
36
+ # to keep existing design clean.
37
+ #
38
+ # @example Atomically $set multiple saves.
39
+ # atomically(:$set) do
40
+ # address_one.save!
41
+ # address_two.save!
42
+ # end
43
+ #
44
+ # @example Atomically $pushAll multiple new docs.
45
+ # atomically(:$pushAll) do
46
+ # person.addresses.push([ address_one, address_two ])
47
+ # end
48
+ #
49
+ # @todo Durran: Move executions to thread local stack.
50
+ #
51
+ # @param [ Symbol ] modifier The atomic modifier to perform.
52
+ # @param [ Proc ] block The block to execute.
53
+ #
54
+ # @return [ Object ] The result of the operation.
55
+ #
56
+ # @since 2.0.0
57
+ def atomically(modifier, &block)
58
+ updater = Threaded.update_consumer(root_class) ||
59
+ Threaded.set_update_consumer(root_class, MODIFIERS[modifier].new)
60
+ count_executions do
61
+ block.call if block
62
+ end.tap do
63
+ if @executions.zero?
64
+ Threaded.set_update_consumer(root_class, nil)
65
+ updater.execute(collection)
66
+ end
67
+ end
68
+ end
69
+
70
+ # Execute the block, incrementing the executions before the call and
71
+ # decrementing them after in order to be able to nest blocks within
72
+ # each other.
73
+ #
74
+ # @example Execute and increment.
75
+ # execute { block.call }
76
+ #
77
+ # @param [ Proc ] block The block to call.
78
+ #
79
+ # @since 2.0.0
80
+ def count_executions(&block)
81
+ @executions ||= 0 and @executions += 1
82
+ block.call.tap do
83
+ @executions -=1
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Relations #:nodoc:
4
+ module Embedded #:nodoc:
5
+ module Atomic #:nodoc:
6
+
7
+ class Operation
8
+ attr_accessor :documents, :options, :path, :selector
9
+
10
+ # Consumes an execution that was supposed to hit the database, but is
11
+ # now being deferred to later in favor of a single update.
12
+ #
13
+ # @example Consume the operation.
14
+ # set.consume(
15
+ # { "_id" => BSON::ObjectId.new },
16
+ # { "$push" => { "addresses" => { "_id" => "street" } } },
17
+ # { :multi => false, :safe => true }
18
+ # )
19
+ #
20
+ # @param [ Hash ] selector The document selector.
21
+ # @param [ Hash ] operations The ops to set in the db.
22
+ # @param [ Hash ] options The persistence options.
23
+ #
24
+ # @option options [ true, false ] :multi Persist multiple at once.
25
+ # @option options [ true, false ] :safe Persist in safe mode.
26
+ #
27
+ # @since 2.0.0
28
+ def consume(selector, operations, options = {})
29
+ @consumed, @selector, @options = true, selector, options
30
+ @documents ||= []
31
+ parse(operations)
32
+ end
33
+
34
+ # Has this operation consumed any executions?
35
+ #
36
+ # @example Is this consumed?
37
+ # unset.consumed?
38
+ #
39
+ # @return [ true, false ] If the operation has consumed anything.
40
+ #
41
+ # @since 2.0.0
42
+ def consumed?
43
+ !!@consumed
44
+ end
45
+
46
+ # Execute the $pushAll operation on the collection.
47
+ #
48
+ # @example Execute the operation.
49
+ # unset.execute(collection)
50
+ #
51
+ # @param [ Collection ] collection The root collection.
52
+ #
53
+ # @since 2.0.0
54
+ def execute(collection)
55
+ if collection && consumed?
56
+ collection.update(selector, operations, options)
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,65 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Relations #:nodoc:
4
+ module Embedded #:nodoc:
5
+ module Atomic #:nodoc:
6
+
7
+ class Pull < Operation
8
+
9
+ # Get the merged operations for the single atomic set.
10
+ #
11
+ # @example Get the operations
12
+ # set.operations
13
+ #
14
+ # @return [ Hash ] The pull operations.
15
+ #
16
+ # @since 2.0.0
17
+ def operations
18
+ { "$pull" =>
19
+ { path =>
20
+ { "_id" =>
21
+ { "$in" => documents.map { |doc| doc["_id"] } }
22
+ }
23
+ }
24
+ }
25
+ end
26
+
27
+ private
28
+
29
+ # Parses the incoming operations to get the documents to set.
30
+ #
31
+ # @example Parse the operations.
32
+ # set.parse(
33
+ # { "$pull" => { "addresses" => { "_id" => "street" } } }
34
+ # )
35
+ #
36
+ # @param [ Hash ] operations The ops to parse.
37
+ #
38
+ # @since 2.0.0
39
+ def parse(operations)
40
+ modifier = operations.keys.first
41
+ extract(modifier, operations[modifier])
42
+ end
43
+
44
+ # Extract a document from the operation.
45
+ #
46
+ # @example Extract the document.
47
+ # set.extract({ "$pull" => [{ "_id" => "street" }] })
48
+ #
49
+ # @param [ Hash ] operation The op to extract from.
50
+ #
51
+ # @since 2.0.0
52
+ def extract(modifier, operations)
53
+ @path = operations.keys.first
54
+ case modifier
55
+ when "$pull"
56
+ documents.push(operations[path])
57
+ when "$pullAll"
58
+ documents.concat(operations[path])
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,59 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Relations #:nodoc:
4
+ module Embedded #:nodoc:
5
+ module Atomic #:nodoc:
6
+
7
+ class PushAll < Operation
8
+
9
+ # Get the merged operations for the single atomic set.
10
+ #
11
+ # @example Get the operations
12
+ # set.operations
13
+ #
14
+ # @return [ Hash ] The set operations.
15
+ #
16
+ # @since 2.0.0
17
+ def operations
18
+ { "$pushAll" => { path => documents } }
19
+ end
20
+
21
+ private
22
+
23
+ # Parses the incoming operations to get the documents to set.
24
+ #
25
+ # @example Parse the operations.
26
+ # set.parse(
27
+ # { "$push" => { "addresses" => { "_id" => "street" } } }
28
+ # )
29
+ #
30
+ # @param [ Hash ] operations The ops to parse.
31
+ #
32
+ # @since 2.0.0
33
+ def parse(operations)
34
+ modifier = operations.keys.first
35
+ extract(modifier, operations[modifier])
36
+ end
37
+
38
+ # Extract a document from the operation.
39
+ #
40
+ # @example Extract the document.
41
+ # set.extract({ "$pushAll" => [{ "_id" => "street" }] })
42
+ #
43
+ # @param [ Hash ] operation The op to extract from.
44
+ #
45
+ # @since 2.0.0
46
+ def extract(modifier, operations)
47
+ @path = operations.keys.first
48
+ case modifier
49
+ when "$push"
50
+ documents.push(operations[path])
51
+ when "$pushAll"
52
+ documents.concat(operations[path])
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,61 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Relations #:nodoc:
4
+ module Embedded #:nodoc:
5
+ module Atomic #:nodoc:
6
+
7
+ class Set < Operation
8
+
9
+ # Get the merged operations for the single atomic set.
10
+ #
11
+ # @example Get the operations
12
+ # set.operations
13
+ #
14
+ # @return [ Hash ] The set operations.
15
+ #
16
+ # @since 2.0.0
17
+ def operations
18
+ { "$set" => { path => documents } }
19
+ end
20
+
21
+ private
22
+
23
+ # Parses the incoming operations to get the documents to set.
24
+ #
25
+ # @example Parse the operations.
26
+ # set.parse(
27
+ # { "addresses" => { "$pushAll" => [{ "_id" => "street" }] } }
28
+ # )
29
+ #
30
+ # @param [ Hash ] operations The ops to parse.
31
+ #
32
+ # @since 2.0.0
33
+ def parse(operations)
34
+ modifier = operations.keys.first
35
+ extract(modifier, operations[modifier])
36
+ end
37
+
38
+ # Extract a document from the operation.
39
+ #
40
+ # @example Extract the document.
41
+ # set.extract({ "$pushAll" => [{ "_id" => "street" }] })
42
+ #
43
+ # @param [ Hash ] operation The op to extract from.
44
+ #
45
+ # @since 2.0.0
46
+ def extract(modifier, operations)
47
+ @path = operations.keys.first
48
+ case modifier
49
+ when "$push"
50
+ documents.push(operations[path])
51
+ when "$pushAll"
52
+ documents.push(operations[path].first)
53
+ when "$set"
54
+ @documents = operations[path]
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end