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,41 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Relations #:nodoc:
4
+ module Embedded #:nodoc:
5
+ module Atomic #:nodoc:
6
+
7
+ class Unset < 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
+ { "$unset" => { path => true } }
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
+ @path ||= operations[modifier].keys.first
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,220 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Embedded
5
+
6
+ # This class defines the behaviour necessary to handle relations that are
7
+ # embedded within another relation, either as a single document or
8
+ # multiple documents.
9
+ class In < Relations::One
10
+
11
+ # Instantiate a new embedded_in relation.
12
+ #
13
+ # @example Create the new relation.
14
+ # Embedded::In.new(name, person, metadata)
15
+ #
16
+ # @param [ Document ] base The document the relation hangs off of.
17
+ # @param [ Document ] target The target (parent) of the relation.
18
+ # @param [ Metadata ] metadata The relation metadata.
19
+ #
20
+ # @return [ In ] The proxy.
21
+ def initialize(base, target, metadata)
22
+ init(base, target, metadata) do
23
+ characterize_one(target)
24
+ bind_one
25
+ end
26
+ end
27
+
28
+ # Substitutes the supplied target documents for the existing document
29
+ # in the relation.
30
+ #
31
+ # @example Substitute the new document.
32
+ # person.name.substitute(new_name)
33
+ #
34
+ # @param [ Document ] other A document to replace the target.
35
+ #
36
+ # @return [ Document, nil ] The relation or nil.
37
+ #
38
+ # @since 2.0.0.rc.1
39
+ def substitute(replacement)
40
+ tap do |proxy|
41
+ proxy.unbind_one
42
+ unless replacement
43
+ base.delete if persistable?
44
+ return nil
45
+ end
46
+ base.new_record = true
47
+ proxy.target = replacement
48
+ proxy.bind_one
49
+ end
50
+ end
51
+
52
+ private
53
+
54
+ # Instantiate the binding associated with this relation.
55
+ #
56
+ # @example Get the binding.
57
+ # binding([ address ])
58
+ #
59
+ # @param [ Proxy ] new_target The new documents to bind with.
60
+ #
61
+ # @return [ Binding ] A binding object.
62
+ #
63
+ # @since 2.0.0.rc.1
64
+ def binding
65
+ Bindings::Embedded::In.new(base, target, metadata)
66
+ end
67
+
68
+ # Characterize the document.
69
+ #
70
+ # @example Set the base metadata.
71
+ # relation.characterize_one(document)
72
+ #
73
+ # @param [ Document ] document The document to set the metadata on.
74
+ #
75
+ # @since 2.1.0
76
+ def characterize_one(document)
77
+ unless base.metadata
78
+ base.metadata = metadata.inverse_metadata(document)
79
+ end
80
+ end
81
+
82
+ # Are we able to persist this relation?
83
+ #
84
+ # @example Can we persist the relation?
85
+ # relation.persistable?
86
+ #
87
+ # @return [ true, false ] If the relation is persistable.
88
+ #
89
+ # @since 2.1.0
90
+ def persistable?
91
+ target.persisted? && !_binding? && !_building?
92
+ end
93
+
94
+ class << self
95
+
96
+ # Return the builder that is responsible for generating the documents
97
+ # that will be used by this relation.
98
+ #
99
+ # @example Get the builder.
100
+ # Embedded::In.builder(meta, object, person)
101
+ #
102
+ # @param [ Document ] base The base document.
103
+ # @param [ Metadata ] meta The metadata of the relation.
104
+ # @param [ Document, Hash ] object A document or attributes to build with.
105
+ #
106
+ # @return [ Builder ] A newly instantiated builder object.
107
+ #
108
+ # @since 2.0.0.rc.1
109
+ def builder(base, meta, object)
110
+ Builders::Embedded::In.new(base, meta, object)
111
+ end
112
+
113
+ # Returns true if the relation is an embedded one. In this case
114
+ # always true.
115
+ #
116
+ # @example Is this relation embedded?
117
+ # Embedded::In.embedded?
118
+ #
119
+ # @return [ true ] true.
120
+ #
121
+ # @since 2.0.0.rc.1
122
+ def embedded?
123
+ true
124
+ end
125
+
126
+ # Returns the macro for this relation. Used mostly as a helper in
127
+ # reflection.
128
+ #
129
+ # @example Get the macro.
130
+ # Mongoid::Relations::Embedded::In.macro
131
+ #
132
+ # @return [ Symbol ] :embedded_in.
133
+ #
134
+ # @since 2.0.0.rc.1
135
+ def macro
136
+ :embedded_in
137
+ end
138
+
139
+ # Return the nested builder that is responsible for generating
140
+ # the documents that will be used by this relation.
141
+ #
142
+ # @example Get the builder.
143
+ # NestedAttributes::One.builder(attributes, options)
144
+ #
145
+ # @param [ Metadata ] metadata The relation metadata.
146
+ # @param [ Hash ] attributes The attributes to build with.
147
+ # @param [ Hash ] options The options for the builder.
148
+ #
149
+ # @option options [ true, false ] :allow_destroy Can documents be
150
+ # deleted?
151
+ # @option options [ Integer ] :limit Max number of documents to
152
+ # create at once.
153
+ # @option options [ Proc, Symbol ] :reject_if If documents match this
154
+ # option then they are ignored.
155
+ # @option options [ true, false ] :update_only Only existing documents
156
+ # can be modified.
157
+ #
158
+ # @return [ Builder ] A newly instantiated nested builder object.
159
+ #
160
+ # @since 2.0.0.rc.1
161
+ def nested_builder(metadata, attributes, options)
162
+ Builders::NestedAttributes::One.new(metadata, attributes, options)
163
+ end
164
+
165
+ # Get the path calculator for the supplied document.
166
+ #
167
+ # @example Get the path calculator.
168
+ # Proxy.path(document)
169
+ #
170
+ # @param [ Document ] document The document to calculate on.
171
+ #
172
+ # @return [ Root ] The root atomic path calculator.
173
+ #
174
+ # @since 2.1.0
175
+ def path(document)
176
+ Mongoid::Atomic::Paths::Root.new(document)
177
+ end
178
+
179
+ # Tells the caller if this relation is one that stores the foreign
180
+ # key on its own objects.
181
+ #
182
+ # @example Does this relation store a foreign key?
183
+ # Embedded::In.stores_foreign_key?
184
+ #
185
+ # @return [ false ] false.
186
+ #
187
+ # @since 2.0.0.rc.1
188
+ def stores_foreign_key?
189
+ false
190
+ end
191
+
192
+ # Get the valid options allowed with this relation.
193
+ #
194
+ # @example Get the valid options.
195
+ # Relation.valid_options
196
+ #
197
+ # @return [ Array<Symbol> ] The valid options.
198
+ #
199
+ # @since 2.1.0
200
+ def valid_options
201
+ [ :cyclic, :polymorphic ]
202
+ end
203
+
204
+ # Get the default validation setting for the relation. Determines if
205
+ # by default a validates associated will occur.
206
+ #
207
+ # @example Get the validation default.
208
+ # Proxy.validation_default
209
+ #
210
+ # @return [ true, false ] The validation default.
211
+ #
212
+ # @since 2.1.9
213
+ def validation_default
214
+ false
215
+ end
216
+ end
217
+ end
218
+ end
219
+ end
220
+ end
@@ -0,0 +1,560 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Embedded #:nodoc:
5
+
6
+ # This class handles the behaviour for a document that embeds many other
7
+ # documents within in it as an array.
8
+ class Many < Relations::Many
9
+ include Atomic
10
+
11
+ # Appends a document or array of documents to the relation. Will set
12
+ # the parent and update the index in the process.
13
+ #
14
+ # @example Append a document.
15
+ # person.addresses << address
16
+ #
17
+ # @example Push a document.
18
+ # person.addresses.push(address)
19
+ #
20
+ # @example Concat with other documents.
21
+ # person.addresses.concat([ address_one, address_two ])
22
+ #
23
+ # @param [ Document, Array<Document> ] *args Any number of documents.
24
+ def <<(*args)
25
+ atomically(:$pushAll) do
26
+ args.flatten.each do |doc|
27
+ next unless doc
28
+ append(doc)
29
+ doc.save if persistable? && !_assigning?
30
+ end
31
+ end
32
+ end
33
+ alias :concat :<<
34
+ alias :push :<<
35
+
36
+ # Builds a new document in the relation and appends it to the target.
37
+ # Takes an optional type if you want to specify a subclass.
38
+ #
39
+ # @example Build a new document on the relation.
40
+ # person.people.build(:name => "Bozo")
41
+ #
42
+ # @overload build(attributes = {}, options = {}, type = nil)
43
+ # @param [ Hash ] attributes The attributes to build the document with.
44
+ # @param [ Hash ] options The scoped assignment options.
45
+ # @param [ Class ] type Optional class to build the document with.
46
+ #
47
+ # @overload build(attributes = {}, type = nil)
48
+ # @param [ Hash ] attributes The attributes to build the document with.
49
+ # @param [ Class ] type Optional class to build the document with.
50
+ #
51
+ # @return [ Document ] The new document.
52
+ def build(attributes = {}, options = {}, type = nil)
53
+ if options.is_a? Class
54
+ options, type = {}, options
55
+ end
56
+
57
+ Factory.build(type || metadata.klass, attributes, options).tap do |doc|
58
+ doc.identify
59
+ append(doc)
60
+ yield(doc) if block_given?
61
+ end
62
+ end
63
+ alias :new :build
64
+
65
+ # Clear the relation. Will delete the documents from the db if they are
66
+ # already persisted.
67
+ #
68
+ # @example Clear the relation.
69
+ # person.addresses.clear
70
+ #
71
+ # @return [ Many ] The empty relation.
72
+ def clear
73
+ tap do |proxy|
74
+ atomically(:$unset) { proxy.delete_all }
75
+ end
76
+ end
77
+
78
+ # Returns a count of the number of documents in the association that have
79
+ # actually been persisted to the database.
80
+ #
81
+ # Use #size if you want the total number of documents.
82
+ #
83
+ # @example Get the count of persisted documents.
84
+ # person.addresses.count
85
+ #
86
+ # @return [ Integer ] The total number of persisted embedded docs, as
87
+ # flagged by the #persisted? method.
88
+ def count
89
+ target.select { |doc| doc.persisted? }.size
90
+ end
91
+
92
+ # Create a new document in the relation. This is essentially the same
93
+ # as doing a #build then #save on the new document.
94
+ #
95
+ # @example Create a new document in the relation.
96
+ # person.movies.create(:name => "Bozo")
97
+ #
98
+ # @overload create(attributes = {}, options = {}, type = nil)
99
+ # @param [ Hash ] attributes The attributes to build the document with.
100
+ # @param [ Hash ] options The scoped assignment options.
101
+ # @param [ Class ] type Optional class to create the document with.
102
+ #
103
+ # @overload create(attributes = {}, type = nil)
104
+ # @param [ Hash ] attributes The attributes to build the document with.
105
+ # @param [ Class ] type Optional class to create the document with.
106
+ #
107
+ # @return [ Document ] The newly created document.
108
+ def create(attributes = {}, options = {}, type = nil, &block)
109
+ build(attributes, options, type, &block).tap { |doc| doc.save }
110
+ end
111
+
112
+ # Create a new document in the relation. This is essentially the same
113
+ # as doing a #build then #save on the new document. If validation
114
+ # failed on the document an error will get raised.
115
+ #
116
+ # @example Create the document.
117
+ # person.addresses.create!(:street => "Unter der Linden")</tt>
118
+ #
119
+ # @overload create!(attributes = {}, options = {}, type = nil)
120
+ # @param [ Hash ] attributes The attributes to build the document with.
121
+ # @param [ Hash ] options The scoped assignment options.
122
+ # @param [ Class ] type Optional class to create the document with.
123
+ #
124
+ # @overload create!(attributes = {}, type = nil)
125
+ # @param [ Hash ] attributes The attributes to build the document with.
126
+ # @param [ Class ] type Optional class to create the document with.
127
+ #
128
+ # @raise [ Errors::Validations ] If a validation error occured.
129
+ #
130
+ # @return [ Document ] The newly created document.
131
+ def create!(attributes = {}, options = {}, type = nil, &block)
132
+ build(attributes, options, type, &block).tap { |doc| doc.save! }
133
+ end
134
+
135
+ # Delete the supplied document from the target. This method is proxied
136
+ # in order to reindex the array after the operation occurs.
137
+ #
138
+ # @example Delete the document from the relation.
139
+ # person.addresses.delete(address)
140
+ #
141
+ # @param [ Document ] document The document to be deleted.
142
+ #
143
+ # @return [ Document, nil ] The deleted document or nil if nothing deleted.
144
+ #
145
+ # @since 2.0.0.rc.1
146
+ def delete(document)
147
+ target.delete_one(document).tap do |doc|
148
+ if doc && !_binding?
149
+ if _assigning?
150
+ base.add_atomic_pull(doc)
151
+ else
152
+ doc.delete(:suppress => true)
153
+ end
154
+ unbind_one(doc)
155
+ end
156
+ reindex
157
+ end
158
+ end
159
+
160
+ # Delete all the documents in the association without running callbacks.
161
+ #
162
+ # @example Delete all documents from the relation.
163
+ # person.addresses.delete_all
164
+ #
165
+ # @example Conditionally delete documents from the relation.
166
+ # person.addresses.delete_all(:conditions => { :street => "Bond" })
167
+ #
168
+ # @param [ Hash ] conditions Conditions on which documents to delete.
169
+ #
170
+ # @return [ Integer ] The number of documents deleted.
171
+ def delete_all(conditions = {})
172
+ atomically(:$pull) { remove_all(conditions, :delete) }
173
+ end
174
+
175
+ # Destroy all the documents in the association whilst running callbacks.
176
+ #
177
+ # @example Destroy all documents from the relation.
178
+ # person.addresses.destroy_all
179
+ #
180
+ # @example Conditionally destroy documents from the relation.
181
+ # person.addresses.destroy_all(:conditions => { :street => "Bond" })
182
+ #
183
+ # @param [ Hash ] conditions Conditions on which documents to destroy.
184
+ #
185
+ # @return [ Integer ] The number of documents destroyed.
186
+ def destroy_all(conditions = {})
187
+ atomically(:$pull) { remove_all(conditions, :destroy) }
188
+ end
189
+
190
+ # Finds a document in this association through several different
191
+ # methods.
192
+ #
193
+ # @example Find a document by its id.
194
+ # person.addresses.find(BSON::ObjectId.new)
195
+ #
196
+ # @example Find documents for multiple ids.
197
+ # person.addresses.find([ BSON::ObjectId.new, BSON::ObjectId.new ])
198
+ #
199
+ # @example Find documents based on conditions.
200
+ # person.addresses.find(:all, :conditions => { :number => 10 })
201
+ # person.addresses.find(:first, :conditions => { :number => 10 })
202
+ # person.addresses.find(:last, :conditions => { :number => 10 })
203
+ #
204
+ # @param [ Array<Object> ] args Various arguments.
205
+ #
206
+ # @return [ Array<Document>, Document ] A single or multiple documents.
207
+ def find(*args)
208
+ criteria.find(*args)
209
+ end
210
+
211
+ # Instantiate a new embeds_many relation.
212
+ #
213
+ # @example Create the new relation.
214
+ # Many.new(person, addresses, metadata)
215
+ #
216
+ # @param [ Document ] base The document this relation hangs off of.
217
+ # @param [ Array<Document> ] target The child documents of the relation.
218
+ # @param [ Metadata ] metadata The relation's metadata
219
+ #
220
+ # @return [ Many ] The proxy.
221
+ def initialize(base, target, metadata)
222
+ init(base, target, metadata) do
223
+ target.each_with_index do |doc, index|
224
+ integrate(doc)
225
+ doc._index = index
226
+ end
227
+ end
228
+ end
229
+
230
+ # Get all the documents in the relation that are loaded into memory.
231
+ #
232
+ # @example Get the in memory documents.
233
+ # relation.in_memory
234
+ #
235
+ # @return [ Array<Document> ] The documents in memory.
236
+ #
237
+ # @since 2.1.0
238
+ def in_memory
239
+ target
240
+ end
241
+
242
+ # Substitutes the supplied target documents for the existing documents
243
+ # in the relation.
244
+ #
245
+ # @example Substitute the relation's target.
246
+ # person.addresses.substitute([ address ])
247
+ #
248
+ # @param [ Array<Document> ] new_target The replacement array.
249
+ # @param [ true, false ] building Are we in build mode?
250
+ #
251
+ # @return [ Many ] The proxied relation.
252
+ #
253
+ # @since 2.0.0.rc.1
254
+ def substitute(replacement)
255
+ tap do |proxy|
256
+ if replacement.blank?
257
+ if _assigning? && !proxy.empty?
258
+ base.atomic_unsets.push(proxy.first.atomic_path)
259
+ end
260
+ proxy.clear
261
+ else
262
+ atomically(:$set) do
263
+ if replacement.first.is_a?(Hash)
264
+ replacement = Many.builder(base, metadata, replacement).build
265
+ end
266
+ proxy.target = replacement.compact
267
+ if _assigning?
268
+ base.delayed_atomic_sets[metadata.name.to_s] = proxy.as_document
269
+ end
270
+ proxy.target.each_with_index do |doc, index|
271
+ integrate(doc)
272
+ doc._index = index
273
+ doc.save if base.persisted? && !_assigning?
274
+ end
275
+ end
276
+ end
277
+ end
278
+ end
279
+
280
+ # Get this relation as as its representation in the database.
281
+ #
282
+ # @example Convert the relation to an attributes hash.
283
+ # person.addresses.as_document
284
+ #
285
+ # @return [ Array<Hash> ] The relation as stored in the db.
286
+ #
287
+ # @since 2.0.0.rc.1
288
+ def as_document
289
+ [].tap do |attributes|
290
+ target.each do |doc|
291
+ attributes << doc.as_document
292
+ end
293
+ end
294
+ end
295
+
296
+ # Get a criteria for the embedded documents without the default scoping
297
+ # applied.
298
+ #
299
+ # @example Get the unscoped criteria.
300
+ # person.addresses.unscoped
301
+ #
302
+ # @return [ Criteria ] The unscoped criteria.
303
+ #
304
+ # @since 2.2.1
305
+ def unscoped
306
+ criteria(false)
307
+ end
308
+
309
+ private
310
+
311
+ # Appends the document to the target array, updating the index on the
312
+ # document at the same time.
313
+ #
314
+ # @example Append to the document.
315
+ # relation.append(document)
316
+ #
317
+ # @param [ Document ] document The document to append to the target.
318
+ #
319
+ # @since 2.0.0.rc.1
320
+ def append(document)
321
+ target.push(document)
322
+ integrate(document)
323
+ document._index = target.size - 1
324
+ end
325
+
326
+ # Instantiate the binding associated with this relation.
327
+ #
328
+ # @example Create the binding.
329
+ # relation.binding([ address ])
330
+ #
331
+ # @param [ Array<Document> ] new_target The new documents to bind with.
332
+ #
333
+ # @return [ Binding ] The many binding.
334
+ #
335
+ # @since 2.0.0.rc.1
336
+ def binding
337
+ Bindings::Embedded::Many.new(base, target, metadata)
338
+ end
339
+
340
+ # Returns the criteria object for the target class with its documents set
341
+ # to target.
342
+ #
343
+ # @example Get a criteria for the relation.
344
+ # relation.criteria
345
+ #
346
+ # @return [ Criteria ] A new criteria.
347
+ def criteria(scoped = true)
348
+ klass.criteria(true, scoped).tap do |criterion|
349
+ criterion.documents = target
350
+ end
351
+ end
352
+
353
+ # Integrate the document into the relation. will set its metadata and
354
+ # attempt to bind the inverse.
355
+ #
356
+ # @example Integrate the document.
357
+ # relation.integrate(document)
358
+ #
359
+ # @param [ Document ] document The document to integrate.
360
+ #
361
+ # @since 2.1.0
362
+ def integrate(document)
363
+ characterize_one(document)
364
+ bind_one(document)
365
+ end
366
+
367
+ # If the target array does not respond to the supplied method then try to
368
+ # find a named scope or criteria on the class and send the call there.
369
+ #
370
+ # If the method exists on the array, use the default proxy behavior.
371
+ #
372
+ # @param [ Symbol, String ] name The name of the method.
373
+ # @param [ Array ] args The method args
374
+ # @param [ Proc ] block Optional block to pass.
375
+ #
376
+ # @return [ Criteria, Object ] A Criteria or return value from the target.
377
+ def method_missing(name, *args, &block)
378
+ return super if target.respond_to?(name)
379
+ klass.send(:with_scope, criteria) do
380
+ criteria.send(name, *args, &block)
381
+ end
382
+ end
383
+
384
+ # Are we able to persist this relation?
385
+ #
386
+ # @example Can we persist the relation?
387
+ # relation.persistable?
388
+ #
389
+ # @return [ true, false ] If the relation is persistable.
390
+ #
391
+ # @since 2.1.0
392
+ def persistable?
393
+ base.persisted? && !_binding?
394
+ end
395
+
396
+ # Reindex all the target elements. This is useful when performing
397
+ # operations on the proxied target directly and the indices need to
398
+ # match that on the database side.
399
+ #
400
+ # @example Reindex the relation.
401
+ # person.addresses.reindex
402
+ #
403
+ # @since 2.0.0.rc.1
404
+ def reindex
405
+ target.each_with_index do |doc, index|
406
+ doc._index = index
407
+ end
408
+ end
409
+
410
+ # Remove all documents from the relation, either with a delete or a
411
+ # destroy depending on what this was called through.
412
+ #
413
+ # @example Destroy documents from the relation.
414
+ # relation.remove_all(:conditions => { :num => 1 }, true)
415
+ #
416
+ # @param [ Hash ] conditions Conditions to filter by.
417
+ # @param [ true, false ] destroy If true then destroy, else delete.
418
+ #
419
+ # @return [ Integer ] The number of documents removed.
420
+ def remove_all(conditions = {}, method = :delete)
421
+ criteria = find(:all, conditions || {})
422
+ criteria.size.tap do
423
+ criteria.each do |doc|
424
+ target.delete_one(doc)
425
+ doc.send(method, :suppress => true) unless _assigning?
426
+ unbind_one(doc)
427
+ end
428
+ reindex
429
+ end
430
+ end
431
+
432
+ class << self
433
+
434
+ # Return the builder that is responsible for generating the documents
435
+ # that will be used by this relation.
436
+ #
437
+ # @example Get the builder.
438
+ # Embedded::Many.builder(meta, object)
439
+ #
440
+ # @param [ Document ] base The base document.
441
+ # @param [ Metadata ] meta The metadata of the relation.
442
+ # @param [ Document, Hash ] object A document or attributes to build
443
+ # with.
444
+ #
445
+ # @return [ Builder ] A newly instantiated builder object.
446
+ #
447
+ # @since 2.0.0.rc.1
448
+ def builder(base, meta, object)
449
+ Builders::Embedded::Many.new(base, meta, object)
450
+ end
451
+
452
+ # Returns true if the relation is an embedded one. In this case
453
+ # always true.
454
+ #
455
+ # @example Is the relation embedded?
456
+ # Embedded::Many.embedded?
457
+ #
458
+ # @return [ true ] true.
459
+ #
460
+ # @since 2.0.0.rc.1
461
+ def embedded?
462
+ true
463
+ end
464
+
465
+ # Returns the macro for this relation. Used mostly as a helper in
466
+ # reflection.
467
+ #
468
+ # @example Get the relation macro.
469
+ # Mongoid::Relations::Embedded::Many.macro
470
+ #
471
+ # @return [ Symbol ] :embeds_many
472
+ #
473
+ # @since 2.0.0.rc.1
474
+ def macro
475
+ :embeds_many
476
+ end
477
+
478
+ # Return the nested builder that is responsible for generating the
479
+ # documents that will be used by this relation.
480
+ #
481
+ # @example Get the nested builder.
482
+ # NestedAttributes::Many.builder(attributes, options)
483
+ #
484
+ # @param [ Metadata ] metadata The relation metadata.
485
+ # @param [ Hash ] attributes The attributes to build with.
486
+ # @param [ Hash ] options The builder options.
487
+ #
488
+ # @option options [ true, false ] :allow_destroy Can documents be
489
+ # deleted?
490
+ # @option options [ Integer ] :limit Max number of documents to
491
+ # create at once.
492
+ # @option options [ Proc, Symbol ] :reject_if If documents match this
493
+ # option then they are ignored.
494
+ # @option options [ true, false ] :update_only Only existing documents
495
+ # can be modified.
496
+ #
497
+ # @return [ NestedBuilder ] The nested attributes builder.
498
+ #
499
+ # @since 2.0.0.rc.1
500
+ def nested_builder(metadata, attributes, options)
501
+ Builders::NestedAttributes::Many.new(metadata, attributes, options)
502
+ end
503
+
504
+ # Get the path calculator for the supplied document.
505
+ #
506
+ # @example Get the path calculator.
507
+ # Proxy.path(document)
508
+ #
509
+ # @param [ Document ] document The document to calculate on.
510
+ #
511
+ # @return [ Mongoid::Atomic::Paths::Embedded::Many ]
512
+ # The embedded many atomic path calculator.
513
+ #
514
+ # @since 2.1.0
515
+ def path(document)
516
+ Mongoid::Atomic::Paths::Embedded::Many.new(document)
517
+ end
518
+
519
+ # Tells the caller if this relation is one that stores the foreign
520
+ # key on its own objects.
521
+ #
522
+ # @example Does this relation store a foreign key?
523
+ # Embedded::Many.stores_foreign_key?
524
+ #
525
+ # @return [ false ] false.
526
+ #
527
+ # @since 2.0.0.rc.1
528
+ def stores_foreign_key?
529
+ false
530
+ end
531
+
532
+ # Get the valid options allowed with this relation.
533
+ #
534
+ # @example Get the valid options.
535
+ # Relation.valid_options
536
+ #
537
+ # @return [ Array<Symbol> ] The valid options.
538
+ #
539
+ # @since 2.1.0
540
+ def valid_options
541
+ [ :as, :cascade_callbacks, :cyclic, :order, :versioned ]
542
+ end
543
+
544
+ # Get the default validation setting for the relation. Determines if
545
+ # by default a validates associated will occur.
546
+ #
547
+ # @example Get the validation default.
548
+ # Proxy.validation_default
549
+ #
550
+ # @return [ true, false ] The validation default.
551
+ #
552
+ # @since 2.1.9
553
+ def validation_default
554
+ true
555
+ end
556
+ end
557
+ end
558
+ end
559
+ end
560
+ end