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,230 @@
1
+ # encoding: utf-8
2
+ require "mongoid/atomic/modifiers"
3
+ require "mongoid/atomic/paths"
4
+
5
+ module Mongoid #:nodoc:
6
+
7
+ # This module contains the logic for supporting atomic operations against the
8
+ # database.
9
+ module Atomic
10
+ extend ActiveSupport::Concern
11
+
12
+ included do
13
+
14
+ # When MongoDB finally fully implements the positional operator, we can
15
+ # get rid of all indexing related code in Mongoid.
16
+ attr_accessor :_index
17
+ end
18
+
19
+ # Get all the atomic updates that need to happen for the current
20
+ # +Document+. This includes all changes that need to happen in the
21
+ # entire hierarchy that exists below where the save call was made.
22
+ #
23
+ # @note MongoDB does not allow "conflicting modifications" to be
24
+ # performed in a single operation. Conflicting modifications are
25
+ # detected by the 'haveConflictingMod' function in MongoDB.
26
+ # Examination of the code suggests that two modifications (a $set
27
+ # and a $pushAll, for example) conflict if:
28
+ # (1) the key paths being modified are equal.
29
+ # (2) one key path is a prefix of the other.
30
+ # So a $set of 'addresses.0.street' will conflict with a $pushAll
31
+ # to 'addresses', and we will need to split our update into two
32
+ # pieces. We do not, however, attempt to match MongoDB's logic
33
+ # exactly. Instead, we assume that two updates conflict if the
34
+ # first component of the two key paths matches.
35
+ #
36
+ # @example Get the updates that need to occur.
37
+ # person.atomic_updates(children)
38
+ #
39
+ # @return [ Hash ] The updates and their modifiers.
40
+ #
41
+ # @since 2.1.0
42
+ def atomic_updates
43
+ Modifiers.new.tap do |mods|
44
+ generate_atomic_updates(mods, self)
45
+ _children.each do |child|
46
+ generate_atomic_updates(mods, child)
47
+ end
48
+ end
49
+ end
50
+ alias :_updates :atomic_updates
51
+
52
+ # Get the removal modifier for the document. Will be nil on root
53
+ # documents, $unset on embeds_one, $set on embeds_many.
54
+ #
55
+ # @example Get the removal operator.
56
+ # name.atomic_delete_modifier
57
+ #
58
+ # @return [ String ] The pull or unset operation.
59
+ def atomic_delete_modifier
60
+ atomic_paths.delete_modifier
61
+ end
62
+
63
+ # Get the insertion modifier for the document. Will be nil on root
64
+ # documents, $set on embeds_one, $push on embeds_many.
65
+ #
66
+ # @example Get the insert operation.
67
+ # name.atomic_insert_modifier
68
+ #
69
+ # @return [ String ] The pull or set operator.
70
+ def atomic_insert_modifier
71
+ atomic_paths.insert_modifier
72
+ end
73
+
74
+ # Return the path to this +Document+ in JSON notation, used for atomic
75
+ # updates via $set in MongoDB.
76
+ #
77
+ # @example Get the path to this document.
78
+ # address.atomic_path
79
+ #
80
+ # @return [ String ] The path to the document in the database.
81
+ def atomic_path
82
+ atomic_paths.path
83
+ end
84
+
85
+ # Returns the positional operator of this document for modification.
86
+ #
87
+ # @example Get the positional operator.
88
+ # address.atomic_position
89
+ #
90
+ # @return [ String ] The positional operator with indexes.
91
+ def atomic_position
92
+ atomic_paths.position
93
+ end
94
+
95
+ # Get all the attributes that need to be pulled.
96
+ #
97
+ # @example Get the pulls.
98
+ # person.atomic_pulls
99
+ #
100
+ # @return [ Array<Hash> ] The $pullAll operations.
101
+ #
102
+ # @since 2.2.0
103
+ def atomic_pulls
104
+ delayed_atomic_pulls.inject({}) do |pulls, (name, docs)|
105
+ pulls.tap do |pull|
106
+ docs.each do |doc|
107
+ (pull[doc.atomic_path] ||= []).push(doc.as_document)
108
+ doc.destroyed = true
109
+ doc.flagged_for_destroy = false
110
+ end
111
+ end
112
+ end
113
+ end
114
+
115
+ # Add the document as an atomic pull.
116
+ #
117
+ # @example Add the atomic pull.
118
+ # person.add_atomic_pull(address)
119
+ #
120
+ # @param [ Document ] The embedded document to pull.
121
+ #
122
+ # @since 2.2.0
123
+ def add_atomic_pull(document)
124
+ document.flagged_for_destroy = true
125
+ (delayed_atomic_pulls[document.metadata.name.to_s] ||= []).push(document)
126
+ end
127
+
128
+ # Get all the push attributes that need to occur.
129
+ #
130
+ # @example Get the pushes.
131
+ # person.atomic_pushes
132
+ #
133
+ # @return [ Hash ] The $pushAll operations.
134
+ #
135
+ # @since 2.1.0
136
+ def atomic_pushes
137
+ pushable? ? { atomic_path => as_document } : {}
138
+ end
139
+
140
+ # Return the selector for this document to be matched exactly for use
141
+ # with MongoDB's $ operator.
142
+ #
143
+ # @example Get the selector.
144
+ # address.atomic_selector
145
+ #
146
+ # @return [ String ] The exact selector for this document.
147
+ def atomic_selector
148
+ atomic_paths.selector
149
+ end
150
+
151
+ # Get all the attributes that need to be set.
152
+ #
153
+ # @example Get the sets.
154
+ # person.atomic_sets
155
+ #
156
+ # @return [ Hash ] The $set operations.
157
+ #
158
+ # @since 2.1.0
159
+ def atomic_sets
160
+ updateable? ? setters : settable? ? { atomic_path => as_document } : {}
161
+ end
162
+
163
+ # Get all the attributes that need to be unset.
164
+ #
165
+ # @example Get the unsets.
166
+ # person.atomic_unsets
167
+ #
168
+ # @return [ Array<Hash> ] The $unset operations.
169
+ #
170
+ # @since 2.2.0
171
+ def atomic_unsets
172
+ @atomic_unsets ||= []
173
+ end
174
+
175
+ # Get all the atomic sets that have had their saves delayed.
176
+ #
177
+ # @example Get the delayed atomic sets.
178
+ # person.delayed_atomic_sets
179
+ #
180
+ # @return [ Hash ] The delayed $sets.
181
+ #
182
+ # @since 2.3.0
183
+ def delayed_atomic_sets
184
+ @delayed_atomic_sets ||= {}
185
+ end
186
+
187
+ # Get a hash of atomic pulls that are pending.
188
+ #
189
+ # @example Get the atomic pulls.
190
+ # document.delayed_atomic_pulls
191
+ #
192
+ # @return [ Hash ] name/document pairs.
193
+ #
194
+ # @since 2.3.2
195
+ def delayed_atomic_pulls
196
+ @delayed_atomic_pulls ||= {}
197
+ end
198
+
199
+ private
200
+
201
+ # Get the atomic paths utility for this document.
202
+ #
203
+ # @example Get the atomic paths.
204
+ # document.atomic_paths
205
+ #
206
+ # @return [ Object ] The associated path.
207
+ #
208
+ # @since 2.1.0
209
+ def atomic_paths
210
+ @atomic_paths ||= metadata ? metadata.path(self) : Atomic::Paths::Root.new(self)
211
+ end
212
+
213
+ # Generates the atomic updates in the correct order.
214
+ #
215
+ # @example Generate the updates.
216
+ # model.generate_atomic_updates(mods, doc)
217
+ #
218
+ # @param [ Modifiers ] mods The atomic modifications.
219
+ # @param [ Document ] doc The document to update for.
220
+ #
221
+ # @since 2.2.0
222
+ def generate_atomic_updates(mods, doc)
223
+ mods.unset(doc.atomic_unsets)
224
+ mods.pull(doc.atomic_pulls)
225
+ mods.set(doc.atomic_sets)
226
+ mods.set(doc.delayed_atomic_sets)
227
+ mods.push(doc.atomic_pushes)
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,243 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Atomic #:nodoc:
4
+
5
+ # This class contains the logic for supporting atomic operations against the
6
+ # database.
7
+ class Modifiers < Hash
8
+
9
+ # Adds pull modifiers to the modifiers hash.
10
+ #
11
+ # @example Add pull operations.
12
+ # modifiers.pull({ "addresses" => { "street" => "Bond" }})
13
+ #
14
+ # @param [ Hash ] modifications The pull modifiers.
15
+ #
16
+ # @since 2.2.0
17
+ def pull(modifications)
18
+ modifications.each_pair do |field, value|
19
+ add_operation(pulls, field, value)
20
+ pull_fields << field.split(".", 2)[0]
21
+ end
22
+ end
23
+
24
+ # Adds push modifiers to the modifiers hash.
25
+ #
26
+ # @example Add push operations.
27
+ # modifiers.push({ "addresses" => { "street" => "Bond" }})
28
+ #
29
+ # @param [ Hash ] modifications The push modifiers.
30
+ #
31
+ # @since 2.1.0
32
+ def push(modifications)
33
+ modifications.each_pair do |field, value|
34
+ mods = push_conflict?(field) ? conflicting_pushes : pushes
35
+ add_operation(mods, field, Array.wrap(value))
36
+ end
37
+ end
38
+
39
+ # Adds set operations to the modifiers hash.
40
+ #
41
+ # @example Add set operations.
42
+ # modifiers.set({ "title" => "sir" })
43
+ #
44
+ # @param [ Hash ] modifications The set modifiers.
45
+ #
46
+ # @since 2.1.0
47
+ def set(modifications)
48
+ modifications.each_pair do |field, value|
49
+ next if field == "_id"
50
+ mods = set_conflict?(field) ? conflicting_sets : sets
51
+ add_operation(mods, field, value)
52
+ set_fields << field.split(".", 2)[0]
53
+ end
54
+ end
55
+
56
+ # Adds unset operations to the modifiers hash.
57
+ #
58
+ # @example Add unset operations.
59
+ # modifiers.unset([ "addresses" ])
60
+ #
61
+ # @param [ Array<String> ] modifications The unset relation names.
62
+ #
63
+ # @since 2.2.0
64
+ def unset(modifications)
65
+ modifications.each do |field|
66
+ unsets.update(field => true)
67
+ end
68
+ end
69
+
70
+ private
71
+
72
+ # Add the operation to the modifications, either appending or creating a
73
+ # new one.
74
+ #
75
+ # @example Add the operation.
76
+ # modifications.add_operation(mods, field, value)
77
+ #
78
+ # @param [ Hash ] mods The modifications.
79
+ # @param [ String ] field The field.
80
+ # @param [ Hash ] value The atomic op.
81
+ #
82
+ # @since 2.2.0
83
+ def add_operation(mods, field, value)
84
+ if mods.has_key?(field)
85
+ value.each do |val|
86
+ mods[field].push(val)
87
+ end
88
+ else
89
+ mods[field] = value
90
+ end
91
+ end
92
+
93
+ # Is the operation going to be a conflict for a $set?
94
+ #
95
+ # @example Is this a conflict for a set?
96
+ # modifiers.set_conflict?(field)
97
+ #
98
+ # @param [ String ] field The field.
99
+ #
100
+ # @return [ true, false ] If this field is a conflict.
101
+ #
102
+ # @since 2.2.0
103
+ def set_conflict?(field)
104
+ pull_fields.include?(field.split(".", 2)[0])
105
+ end
106
+
107
+ # Is the operation going to be a conflict for a $push?
108
+ #
109
+ # @example Is this a conflict for a push?
110
+ # modifiers.push_conflict?(field)
111
+ #
112
+ # @param [ String ] field The field.
113
+ #
114
+ # @return [ true, false ] If this field is a conflict.
115
+ #
116
+ # @since 2.2.0
117
+ def push_conflict?(field)
118
+ name = field.split(".", 2)[0]
119
+ set_fields.include?(name) || pull_fields.include?(name)
120
+ end
121
+
122
+ # Get the conflicting pull modifications.
123
+ #
124
+ # @example Get the conflicting pulls.
125
+ # modifiers.conflicting_pulls
126
+ #
127
+ # @return [ Hash ] The conflicting pull operations.
128
+ #
129
+ # @since 2.2.0
130
+ def conflicting_pulls
131
+ conflicts["$pullAll"] ||= {}
132
+ end
133
+
134
+ # Get the conflicting push modifications.
135
+ #
136
+ # @example Get the conflicting pushs.
137
+ # modifiers.conflicting_pushs
138
+ #
139
+ # @return [ Hash ] The conflicting push operations.
140
+ #
141
+ # @since 2.2.0
142
+ def conflicting_pushes
143
+ conflicts["$pushAll"] ||= {}
144
+ end
145
+
146
+ # Get the conflicting set modifications.
147
+ #
148
+ # @example Get the conflicting sets.
149
+ # modifiers.conflicting_sets
150
+ #
151
+ # @return [ Hash ] The conflicting set operations.
152
+ #
153
+ # @since 2.2.0
154
+ def conflicting_sets
155
+ conflicts["$set"] ||= {}
156
+ end
157
+
158
+ # Get the push operations that would have conflicted with the sets.
159
+ #
160
+ # @example Get the conflicts.
161
+ # modifiers.conflicts
162
+ #
163
+ # @return [ Hash ] The conflicting modifications.
164
+ #
165
+ # @since 2.1.0
166
+ def conflicts
167
+ self[:conflicts] ||= {}
168
+ end
169
+
170
+ # Get the names of the fields that need to be pulled.
171
+ #
172
+ # @example Get the pull fields.
173
+ # modifiers.pull_fields
174
+ #
175
+ # @return [ Array<String> ] The pull fields.
176
+ #
177
+ # @since 2.2.0
178
+ def pull_fields
179
+ @pull_fields ||= []
180
+ end
181
+
182
+ # Get the names of the fields that need to be set.
183
+ #
184
+ # @example Get the set fields.
185
+ # modifiers.set_fields
186
+ #
187
+ # @return [ Array<String> ] The set fields.
188
+ #
189
+ # @since 2.2.0
190
+ def set_fields
191
+ @set_fields ||= []
192
+ end
193
+
194
+ # Get the $pullAll operations or intialize a new one.
195
+ #
196
+ # @example Get the $pullAll operations.
197
+ # modifiers.pulles
198
+ #
199
+ # @return [ Hash ] The $pullAll operations.
200
+ #
201
+ # @since 2.1.0
202
+ def pulls
203
+ self["$pullAll"] ||= {}
204
+ end
205
+
206
+ # Get the $pushAll operations or intialize a new one.
207
+ #
208
+ # @example Get the $pushAll operations.
209
+ # modifiers.pushes
210
+ #
211
+ # @return [ Hash ] The $pushAll operations.
212
+ #
213
+ # @since 2.1.0
214
+ def pushes
215
+ self["$pushAll"] ||= {}
216
+ end
217
+
218
+ # Get the $set operations or intialize a new one.
219
+ #
220
+ # @example Get the $set operations.
221
+ # modifiers.sets
222
+ #
223
+ # @return [ Hash ] The $set operations.
224
+ #
225
+ # @since 2.1.0
226
+ def sets
227
+ self["$set"] ||= {}
228
+ end
229
+
230
+ # Get the $unset operations or initialize a new one.
231
+ #
232
+ # @example Get the $unset operations.
233
+ # modifiers.unsets
234
+ #
235
+ # @return [ Hash ] The $unset operations.
236
+ #
237
+ # @since 2.2.0
238
+ def unsets
239
+ self["$unset"] ||= {}
240
+ end
241
+ end
242
+ end
243
+ end