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,3 @@
1
+ # encoding: utf-8
2
+ require "mongoid/atomic/paths/embedded"
3
+ require "mongoid/atomic/paths/root"
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ require "mongoid/atomic/paths/embedded/one"
3
+ require "mongoid/atomic/paths/embedded/many"
4
+
5
+ module Mongoid #:nodoc:
6
+ module Atomic #:nodoc:
7
+ module Paths #:nodoc:
8
+
9
+ # Common functionality between the two different embedded paths.
10
+ module Embedded
11
+
12
+ attr_reader :delete_modifier, :document, :insert_modifier, :parent
13
+
14
+ # Get the path to the document in the hierarchy.
15
+ #
16
+ # @example Get the path.
17
+ # many.path
18
+ #
19
+ # @return [ String ] The path to the document.
20
+ #
21
+ # @since 2.1.0
22
+ def path
23
+ position.sub(/\.\d+$/, "")
24
+ end
25
+
26
+ # Get the selector to use for the root document when performing atomic
27
+ # updates. When sharding this will include the shard key.
28
+ #
29
+ # @example Get the selector.
30
+ # many.selector
31
+ #
32
+ # @return [ Hash ] The selector to identify the document with.
33
+ #
34
+ # @since 2.1.0
35
+ def selector
36
+ parent.atomic_selector.
37
+ merge!({ "#{path}._id" => document.identifier || document._id }).
38
+ merge!(document.shard_key_selector)
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Atomic #:nodoc:
4
+ module Paths #:nodoc:
5
+ module Embedded #:nodoc:
6
+
7
+ # This class encapsulates behaviour for locating and updating
8
+ # documents that are defined as an embedded 1-n.
9
+ class Many
10
+ include Embedded
11
+
12
+ # Create the new path utility.
13
+ #
14
+ # @example Create the path util.
15
+ # Many.new(document)
16
+ #
17
+ # @param [ Document ] document The document to generate the paths for.
18
+ #
19
+ # @since 2.1.0
20
+ def initialize(document)
21
+ @document, @parent = document, document._parent
22
+ @insert_modifier, @delete_modifier ="$push", "$pull"
23
+ end
24
+
25
+ # Get the position of the document in the hierarchy. This will
26
+ # include indexes of 1-n embedded relations that may sit above the
27
+ # embedded many.
28
+ #
29
+ # @example Get the position.
30
+ # many.position
31
+ #
32
+ # @return [ String ] The position of the document.
33
+ #
34
+ # @since 2.1.0
35
+ def position
36
+ pos = parent.atomic_position
37
+ locator = document.new? ? "" : ".#{document._index}"
38
+ "#{pos}#{"." unless pos.blank?}#{document.metadata.name}#{locator}"
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,43 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Atomic #:nodoc:
4
+ module Paths #:nodoc:
5
+ module Embedded #:nodoc:
6
+
7
+ # This class encapsulates behaviour for locating and updating
8
+ # documents that are defined as an embedded 1-1.
9
+ class One
10
+ include Embedded
11
+
12
+ # Create the new path utility.
13
+ #
14
+ # @example Create the path util.
15
+ # One.new(document)
16
+ #
17
+ # @param [ Document ] document The document to generate the paths for.
18
+ #
19
+ # @since 2.1.0
20
+ def initialize(document)
21
+ @document, @parent = document, document._parent
22
+ @insert_modifier, @delete_modifier ="$set", "$unset"
23
+ end
24
+
25
+ # Get the position of the document in the hierarchy. This will
26
+ # include indexes of 1-n embedded relations that may sit above the
27
+ # embedded one.
28
+ #
29
+ # @example Get the position.
30
+ # one.position
31
+ #
32
+ # @return [ String ] The position of the document.
33
+ #
34
+ # @since 2.1.0
35
+ def position
36
+ pos = parent.atomic_position
37
+ "#{pos}#{"." unless pos.blank?}#{document.metadata.name}"
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Atomic #:nodoc:
4
+ module Paths #:nodoc:
5
+
6
+ # This class encapsulates behaviour for locating and updating root
7
+ # documents atomically.
8
+ class Root
9
+
10
+ attr_reader :document, :path, :position
11
+
12
+ # Create the new root path utility.
13
+ #
14
+ # @example Create the root path util.
15
+ # Root.new(document)
16
+ #
17
+ # @param [ Document ] document The document to generate the paths for.
18
+ #
19
+ # @since 2.1.0
20
+ def initialize(document)
21
+ @document, @path, @position = document, "", ""
22
+ end
23
+
24
+ # Get the selector to use for the root document when performing atomic
25
+ # updates. When sharding this will include the shard key.
26
+ #
27
+ # @example Get the selector.
28
+ # root.selector
29
+ #
30
+ # @return [ Hash ] The selector to identify the document with.
31
+ #
32
+ # @since 2.1.0
33
+ def selector
34
+ { "_id" => document.identifier || document._id }.
35
+ merge!(document.shard_key_selector)
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,234 @@
1
+ # encoding: utf-8
2
+ require "mongoid/attributes/processing"
3
+
4
+ module Mongoid #:nodoc:
5
+
6
+ # This module contains the logic for handling the internal attributes hash,
7
+ # and how to get and set values.
8
+ module Attributes
9
+ extend ActiveSupport::Concern
10
+ include Processing
11
+
12
+ attr_reader :attributes
13
+ alias :raw_attributes :attributes
14
+
15
+ # Determine if an attribute is present.
16
+ #
17
+ # @example Is the attribute present?
18
+ # person.attribute_present?("title")
19
+ #
20
+ # @param [ String, Symbol ] name The name of the attribute.
21
+ #
22
+ # @return [ true, false ] True if present, false if not.
23
+ #
24
+ # @since 1.0.0
25
+ def attribute_present?(name)
26
+ attribute = read_attribute(name)
27
+ ! attribute.blank? || attribute == false
28
+ end
29
+ alias :has_attribute? :attribute_present?
30
+
31
+ # Read a value from the document attributes. If the value does not exist
32
+ # it will return nil.
33
+ #
34
+ # @example Read an attribute.
35
+ # person.read_attribute(:title)
36
+ #
37
+ # @example Read an attribute (alternate syntax.)
38
+ # person[:title]
39
+ #
40
+ # @param [ String, Symbol ] name The name of the attribute to get.
41
+ #
42
+ # @return [ Object ] The value of the attribute.
43
+ #
44
+ # @since 1.0.0
45
+ def read_attribute(name)
46
+ attributes[name.to_s]
47
+ end
48
+ alias :[] :read_attribute
49
+
50
+ # Remove a value from the +Document+ attributes. If the value does not exist
51
+ # it will fail gracefully.
52
+ #
53
+ # @example Remove the attribute.
54
+ # person.remove_attribute(:title)
55
+ #
56
+ # @param [ String, Symbol ] name The name of the attribute to remove.
57
+ #
58
+ # @since 1.0.0
59
+ def remove_attribute(name)
60
+ _assigning do
61
+ access = name.to_s
62
+ attribute_will_change!(access)
63
+ attributes.delete(access)
64
+ end
65
+ end
66
+
67
+ # Override respond_to? so it responds properly for dynamic attributes.
68
+ #
69
+ # @example Does this object respond to the method?
70
+ # person.respond_to?(:title)
71
+ #
72
+ # @param [ Array ] *args The name of the method.
73
+ #
74
+ # @return [ true, false ] True if it does, false if not.
75
+ #
76
+ # @since 1.0.0
77
+ def respond_to?(*args)
78
+ (Mongoid.allow_dynamic_fields &&
79
+ attributes &&
80
+ attributes.has_key?(args.first.to_s)
81
+ ) || super
82
+ end
83
+
84
+ # Write a single attribute to the document attribute hash. This will
85
+ # also fire the before and after update callbacks, and perform any
86
+ # necessary typecasting.
87
+ #
88
+ # @example Write the attribute.
89
+ # person.write_attribute(:title, "Mr.")
90
+ #
91
+ # @example Write the attribute (alternate syntax.)
92
+ # person[:title] = "Mr."
93
+ #
94
+ # @param [ String, Symbol ] name The name of the attribute to update.
95
+ # @param [ Object ] value The value to set for the attribute.
96
+ #
97
+ # @since 1.0.0
98
+ def write_attribute(name, value)
99
+ _assigning do
100
+ access = name.to_s
101
+ localized = fields[access].try(:localized?)
102
+ typed_value_for(access, value).tap do |value|
103
+ unless attributes[access] == value || attribute_changed?(access)
104
+ attribute_will_change!(access)
105
+ end
106
+ if localized
107
+ (attributes[access] ||= {}).merge!(value)
108
+ else
109
+ attributes[access] = value
110
+ end
111
+ end
112
+ end
113
+ end
114
+ alias :[]= :write_attribute
115
+
116
+ # Allows you to set all the attributes for a particular mass-assignment security role
117
+ # by passing in a hash of attributes with keys matching the attribute names
118
+ # (which again matches the column names) and the role name using the :as option.
119
+ # To bypass mass-assignment security you can use the :without_protection => true option.
120
+ #
121
+ # @example Assign the attributes.
122
+ # person.assign_attributes(:title => "Mr.")
123
+ #
124
+ # @example Assign the attributes (with a role).
125
+ # person.assign_attributes({ :title => "Mr." }, :as => :admin)
126
+ #
127
+ # @param [ Hash ] attrs The new attributes to set.
128
+ # @param [ Hash ] options Supported options: :without_protection, :as
129
+ #
130
+ # @since 2.2.1
131
+ def assign_attributes(attrs = nil, options = {})
132
+ _assigning do
133
+ process(attrs, options[:as] || :default, !options[:without_protection]) do |document|
134
+ document.identify if new? && id.blank?
135
+ end
136
+ end
137
+ end
138
+
139
+ # Writes the supplied attributes hash to the document. This will only
140
+ # overwrite existing attributes if they are present in the new +Hash+, all
141
+ # others will be preserved.
142
+ #
143
+ # @example Write the attributes.
144
+ # person.write_attributes(:title => "Mr.")
145
+ #
146
+ # @example Write the attributes (alternate syntax.)
147
+ # person.attributes = { :title => "Mr." }
148
+ #
149
+ # @param [ Hash ] attrs The new attributes to set.
150
+ # @param [ Boolean ] guard_protected_attributes False to skip mass assignment protection.
151
+ #
152
+ # @since 1.0.0
153
+ def write_attributes(attrs = nil, guard_protected_attributes = true)
154
+ assign_attributes(attrs, :without_protection => !guard_protected_attributes)
155
+ end
156
+ alias :attributes= :write_attributes
157
+
158
+ protected
159
+
160
+ # Set any missing default values in the attributes.
161
+ #
162
+ # @example Get the raw attributes after defaults have been applied.
163
+ # person.apply_defaults
164
+ #
165
+ # @return [ Hash ] The raw attributes.
166
+ #
167
+ # @since 2.0.0.rc.8
168
+ def apply_defaults
169
+ defaults.each do |name|
170
+ unless attributes.has_key?(name)
171
+ if field = fields[name]
172
+ attributes[name] = field.eval_default(self)
173
+ end
174
+ end
175
+ end
176
+ end
177
+
178
+ # Used for allowing accessor methods for dynamic attributes.
179
+ #
180
+ # @param [ String, Symbol ] name The name of the method.
181
+ # @param [ Array ] *args The arguments to the method.
182
+ def method_missing(name, *args)
183
+ attr = name.to_s
184
+ return super unless attributes.has_key?(attr.reader)
185
+ if attr.writer?
186
+ write_attribute(attr.reader, (args.size > 1) ? args : args.first)
187
+ else
188
+ read_attribute(attr.reader)
189
+ end
190
+ end
191
+
192
+ # Return the typecasted value for a field.
193
+ #
194
+ # @example Get the value typecasted.
195
+ # person.typed_value_for(:title, :sir)
196
+ #
197
+ # @param [ String, Symbol ] key The field name.
198
+ # @param [ Object ] value The uncast value.
199
+ #
200
+ # @return [ Object ] The cast value.
201
+ #
202
+ # @since 1.0.0
203
+ def typed_value_for(key, value)
204
+ fields.has_key?(key) ? fields[key].serialize(value) : value
205
+ end
206
+
207
+ module ClassMethods #:nodoc:
208
+
209
+ # Alias the provided name to the original field. This will provide an
210
+ # aliased getter, setter, existance check, and all dirty attribute
211
+ # methods.
212
+ #
213
+ # @example Alias the attribute.
214
+ # class Product
215
+ # include Mongoid::Document
216
+ # field :price, :type => Float
217
+ # alias_attribute :cost, :price
218
+ # end
219
+ #
220
+ # @param [ Symbol ] name The new name.
221
+ # @param [ Symbol ] original The original name.
222
+ #
223
+ # @since 2.3.0
224
+ def alias_attribute(name, original)
225
+ class_eval <<-RUBY
226
+ alias :#{name} :#{original}
227
+ alias :#{name}= :#{original}=
228
+ alias :#{name}? :#{original}?
229
+ RUBY
230
+ super
231
+ end
232
+ end
233
+ end
234
+ end
@@ -0,0 +1,146 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Attributes #:nodoc:
4
+
5
+ # This module contains the behavior for processing attributes.
6
+ module Processing
7
+
8
+ # Process the provided attributes casting them to their proper values if a
9
+ # field exists for them on the document. This will be limited to only the
10
+ # attributes provided in the suppied +Hash+ so that no extra nil values get
11
+ # put into the document's attributes.
12
+ #
13
+ # @example Process the attributes.
14
+ # person.process(:title => "sir", :age => 40)
15
+ #
16
+ # @param [ Hash ] attrs The attributes to set.
17
+ # @param [ Symbol ] role A role for scoped mass assignment.
18
+ # @param [ Boolean ] guard_protected_attributes False to skip mass assignment protection.
19
+ #
20
+ # @since 2.0.0.rc.7
21
+ def process(attrs = nil, role = :default, guard_protected_attributes = true)
22
+ attrs ||= {}
23
+ attrs = sanitize_for_mass_assignment(attrs, role) if guard_protected_attributes
24
+ attrs.each_pair do |key, value|
25
+ next if pending_attribute?(key, value)
26
+ process_attribute(key, value)
27
+ end
28
+ yield self if block_given?
29
+ process_pending
30
+ end
31
+
32
+ protected
33
+
34
+ # If the key provided is the name of a relation or a nested attribute, we
35
+ # need to wait until all other attributes are set before processing
36
+ # these.
37
+ #
38
+ # @example Is the attribute pending?
39
+ # document.pending_attribute?(:name, "Durran")
40
+ #
41
+ # @param [ Symbol ] key The name of the attribute.
42
+ # @param [ Object ] value The value of the attribute.
43
+ #
44
+ # @return [ true, false ] True if pending, false if not.
45
+ #
46
+ # @since 2.0.0.rc.7
47
+ def pending_attribute?(key, value)
48
+ name = key.to_s
49
+ if relations.has_key?(name)
50
+ pending_relations[name] = value
51
+ return true
52
+ end
53
+ if nested_attributes.include?("#{name}=")
54
+ pending_nested[name] = value
55
+ return true
56
+ end
57
+ return false
58
+ end
59
+
60
+ # Get all the pending relations that need to be set.
61
+ #
62
+ # @example Get the pending relations.
63
+ # document.pending_relations
64
+ #
65
+ # @return [ Hash ] The pending relations in key/value pairs.
66
+ #
67
+ # @since 2.0.0.rc.7
68
+ def pending_relations
69
+ @pending_relations ||= {}
70
+ end
71
+
72
+ # Get all the pending nested attributes that need to be set.
73
+ #
74
+ # @example Get the pending nested attributes.
75
+ # document.pending_nested
76
+ #
77
+ # @return [ Hash ] The pending nested attributes in key/value pairs.
78
+ #
79
+ # @since 2.0.0.rc.7
80
+ def pending_nested
81
+ @pending_nested ||= {}
82
+ end
83
+
84
+ # If the attribute is dynamic, add a field for it with a type of object
85
+ # and then either way set the value.
86
+ #
87
+ # @example Process the attribute.
88
+ # document.process_attribute(name, value)
89
+ #
90
+ # @param [ Symbol ] name The name of the field.
91
+ # @param [ Object ] value The value of the field.
92
+ #
93
+ # @since 2.0.0.rc.7
94
+ def process_attribute(name, value)
95
+ if Mongoid.allow_dynamic_fields && !respond_to?("#{name}=")
96
+ write_attribute(name, value)
97
+ else
98
+ send("#{name}=", value)
99
+ end
100
+ end
101
+
102
+ # Process all the pending nested attributes that needed to wait until
103
+ # ids were set to fire off.
104
+ #
105
+ # @example Process the nested attributes.
106
+ # document.process_nested
107
+ #
108
+ # @since 2.0.0.rc.7
109
+ def process_nested
110
+ pending_nested.each_pair do |name, value|
111
+ send("#{name}=", value)
112
+ end
113
+ end
114
+
115
+ # Process all the pending items, then clear them out.
116
+ #
117
+ # @example Process the pending items.
118
+ # document.process_pending
119
+ #
120
+ # @since 2.0.0.rc.7
121
+ def process_pending
122
+ process_nested and process_relations
123
+ pending_nested.clear and pending_relations.clear
124
+ end
125
+
126
+ # Process all the pending relations that needed to wait until ids were set
127
+ # to fire off.
128
+ #
129
+ # @example Process the relations.
130
+ # document.process_relations
131
+ #
132
+ # @since 2.0.0.rc.7
133
+ def process_relations
134
+ pending_relations.each_pair do |name, value|
135
+ metadata = relations[name]
136
+ if value.is_a?(Hash)
137
+ metadata.nested_builder(value, {}).build(self)
138
+ else
139
+ send("#{name}=", value)
140
+ end
141
+ end
142
+ end
143
+ end
144
+ end
145
+ end
146
+