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,54 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Bindings #:nodoc:
5
+ module Referenced #:nodoc:
6
+
7
+ # Binding class for references_many relations.
8
+ class Many < Binding
9
+
10
+ # Binds a single document with the inverse relation. Used
11
+ # specifically when appending to the proxy.
12
+ #
13
+ # @example Bind one document.
14
+ # person.posts.bind_one(post)
15
+ #
16
+ # @param [ Document ] doc The single document to bind.
17
+ #
18
+ # @since 2.0.0.rc.1
19
+ def bind_one(doc)
20
+ unless _binding?
21
+ _binding do
22
+ doc.you_must(metadata.foreign_key_setter, base.id)
23
+ if metadata.type
24
+ doc.you_must(metadata.type_setter, base.class.model_name)
25
+ end
26
+ doc.send(metadata.inverse_setter, base)
27
+ end
28
+ end
29
+ end
30
+
31
+ # Unbind a single document.
32
+ #
33
+ # @example Unbind the document.
34
+ # person.posts.unbind_one(document)
35
+ #
36
+ # @param [ Document ] document The document to unbind.
37
+ #
38
+ # @since 2.0.0.rc.1
39
+ def unbind_one(doc)
40
+ unless _binding?
41
+ _binding do
42
+ doc.you_must(metadata.foreign_key_setter, nil)
43
+ if metadata.type
44
+ doc.you_must(metadata.type_setter, nil)
45
+ end
46
+ doc.send(metadata.inverse_setter, nil)
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Bindings #:nodoc:
5
+ module Referenced #:nodoc:
6
+
7
+ # Binding class for all references_and_referenced_in_many relations.
8
+ class ManyToMany < Binding
9
+
10
+ # Binds a single document with the inverse relation. Used
11
+ # specifically when appending to the proxy.
12
+ #
13
+ # @example Bind one document.
14
+ # person.preferences.bind_one(preference)
15
+ #
16
+ # @param [ Document ] doc The single document to bind.
17
+ #
18
+ # @since 2.0.0.rc.1
19
+ def bind_one(doc)
20
+ unless _binding?
21
+ _binding do
22
+ inverse_keys = doc.you_must(metadata.inverse_foreign_key)
23
+ inverse_keys.push(base.id) if inverse_keys
24
+ base.synced[metadata.foreign_key] = true
25
+ doc.synced[metadata.inverse_foreign_key] = true
26
+ end
27
+ end
28
+ end
29
+
30
+ # Unbind a single document.
31
+ #
32
+ # @example Unbind the document.
33
+ # person.preferences.unbind_one(document)
34
+ #
35
+ # @since 2.0.0.rc.1
36
+ def unbind_one(doc)
37
+ unless _binding?
38
+ _binding do
39
+ base.send(metadata.foreign_key).delete_one(doc.id)
40
+ inverse_keys = doc.you_must(metadata.inverse_foreign_key)
41
+ inverse_keys.delete_one(base.id) if inverse_keys
42
+ base.synced[metadata.foreign_key] = true
43
+ doc.synced[metadata.inverse_foreign_key] = true
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,58 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Bindings #:nodoc:
5
+ module Referenced #:nodoc:
6
+
7
+ # Binding class for references_one relations.
8
+ class One < Binding
9
+
10
+ # Binds the base object to the inverse of the relation. This is so we
11
+ # are referenced to the actual objects themselves on both sides.
12
+ #
13
+ # This case sets the metadata on the inverse object as well as the
14
+ # document itself.
15
+ #
16
+ # @example Bind the document.
17
+ # person.game.bind(:continue => true)
18
+ # person.game = Game.new
19
+ #
20
+ # @since 2.0.0.rc.1
21
+ def bind
22
+ unless _binding?
23
+ _binding do
24
+ target.you_must(metadata.foreign_key_setter, base.id)
25
+ target.send(metadata.inverse_setter, base)
26
+ if metadata.type
27
+ target.you_must(metadata.type_setter, base.class.model_name)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ alias :bind_one :bind
33
+
34
+ # Unbinds the base object and the inverse, caused by setting the
35
+ # reference to nil.
36
+ #
37
+ # @example Unbind the document.
38
+ # person.game.unbind(:continue => true)
39
+ # person.game = nil
40
+ #
41
+ # @since 2.0.0.rc.1
42
+ def unbind
43
+ unless _binding?
44
+ _binding do
45
+ target.you_must(metadata.foreign_key_setter, nil)
46
+ target.send(metadata.inverse_setter, nil)
47
+ if metadata.type
48
+ target.you_must(metadata.type_setter, nil)
49
+ end
50
+ end
51
+ end
52
+ end
53
+ alias :unbind_one :unbind
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,57 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+
5
+ # Superclass for all builder objects. Builders are responsible for either
6
+ # looking up a relation's target from the database, or creating them from a
7
+ # supplied attributes hash.
8
+ class Builder
9
+ include Threaded::Lifecycle
10
+
11
+ attr_reader :base, :metadata, :object
12
+
13
+ # Instantiate the new builder for a relation.
14
+ #
15
+ # @example Create the builder.
16
+ # Builder.new(metadata, { :field => "value })
17
+ #
18
+ # @param [ Document ] base The base document.
19
+ # @param [ Metdata ] metadata The metadata for the relation.
20
+ # @param [ Hash, BSON::ObjectId ] object The attributes to build from or
21
+ # id to query with.
22
+ #
23
+ # @since 2.0.0.rc.1
24
+ def initialize(base, metadata, object)
25
+ @base, @metadata, @object = base, metadata, object
26
+ end
27
+
28
+ protected
29
+
30
+ # Get the class from the metadata.
31
+ #
32
+ # @example Get the class.
33
+ # builder.klass
34
+ #
35
+ # @return [ Class ] The class from the metadata.
36
+ #
37
+ # @since 2.3.2
38
+ def klass
39
+ @klass ||= metadata.klass
40
+ end
41
+
42
+ # Do we need to perform a database query? It will be so if the object we
43
+ # have is not a document.
44
+ #
45
+ # @example Should we query the database?
46
+ # builder.query?
47
+ #
48
+ # @return [ true, false ] Whether a database query should happen.
49
+ #
50
+ # @since 2.0.0.rc.1
51
+ def query?
52
+ obj = Array(object).first
53
+ !obj.is_a?(Mongoid::Document) && !obj.nil?
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,83 @@
1
+ # encoding: utf-8
2
+ require "mongoid/relations/builder"
3
+ require "mongoid/relations/nested_builder"
4
+ require "mongoid/relations/builders/embedded/in"
5
+ require "mongoid/relations/builders/embedded/many"
6
+ require "mongoid/relations/builders/embedded/one"
7
+ require "mongoid/relations/builders/nested_attributes/one"
8
+ require "mongoid/relations/builders/nested_attributes/many"
9
+ require "mongoid/relations/builders/referenced/in"
10
+ require "mongoid/relations/builders/referenced/many"
11
+ require "mongoid/relations/builders/referenced/many_to_many"
12
+ require "mongoid/relations/builders/referenced/one"
13
+
14
+ module Mongoid # :nodoc:
15
+ module Relations #:nodoc:
16
+
17
+ # This module is responsible for defining the build and create methods used
18
+ # in one to one relations.
19
+ #
20
+ # @example Methods that get created.
21
+ #
22
+ # class Person
23
+ # include Mongoid::Document
24
+ # embeds_one :name
25
+ # end
26
+ #
27
+ # # The following methods get created:
28
+ # person.build_name({ :first_name => "Durran" })
29
+ # person.create_name({ :first_name => "Durran" })
30
+ #
31
+ # @since 2.0.0.rc.1
32
+ module Builders
33
+ extend ActiveSupport::Concern
34
+
35
+ module ClassMethods #:nodoc:
36
+
37
+ # Defines a builder method for an embeds_one relation. This is
38
+ # defined as #build_name.
39
+ #
40
+ # @example
41
+ # Person.builder("name")
42
+ #
43
+ # @param [ String, Symbol ] name The name of the relation.
44
+ #
45
+ # @return [ Class ] The class being set up.
46
+ #
47
+ # @since 2.0.0.rc.1
48
+ def builder(name, metadata)
49
+ tap do
50
+ define_method("build_#{name}") do |*args|
51
+ attributes = args.first || {}
52
+ options = args.size > 1 ? args[1] : {}
53
+ document = Factory.build(metadata.klass, attributes, options)
54
+ _building do
55
+ send("#{name}=", document)
56
+ end
57
+ end
58
+ end
59
+ end
60
+
61
+ # Defines a creator method for an embeds_one relation. This is
62
+ # defined as #create_name. After the object is built it will
63
+ # immediately save.
64
+ #
65
+ # @example
66
+ # Person.creator("name")
67
+ #
68
+ # @param [ String, Symbol ] name The name of the relation.
69
+ #
70
+ # @return [ Class ] The class being set up.
71
+ #
72
+ # @since 2.0.0.rc.1
73
+ def creator(name)
74
+ tap do
75
+ define_method("create_#{name}") do |*args|
76
+ send("build_#{name}", *args).tap { |doc| doc.save }
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module Embedded #:nodoc:
6
+ class In < Builder #:nodoc:
7
+
8
+ # This builder doesn't actually build anything, just returns the
9
+ # parent since it should already be instantiated.
10
+ #
11
+ # @example Build the document.
12
+ # Builder.new(meta, attrs).build
13
+ #
14
+ # @param [ String ] type Not used in this context.
15
+ #
16
+ # @return [ Document ] A single document.
17
+ def build(type = nil)
18
+ return object unless object.is_a?(Hash)
19
+ if _loading?
20
+ Factory.from_db(klass, object)
21
+ else
22
+ Factory.build(klass, object)
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,40 @@
1
+ # encoding: utf-8
2
+ require "mongoid/relations/embedded/sort"
3
+
4
+ module Mongoid # :nodoc:
5
+ module Relations #:nodoc:
6
+ module Builders #:nodoc:
7
+ module Embedded #:nodoc:
8
+ class Many < Builder #:nodoc:
9
+ include Relations::Embedded::Sort
10
+
11
+ # Builds the document out of the attributes using the provided
12
+ # metadata on the relation. Instantiates through the factory in order
13
+ # to make sure subclasses and allocation are used if fitting. This
14
+ # case will return many documents.
15
+ #
16
+ # @example Build the documents.
17
+ # Builder.new(meta, attrs).build
18
+ #
19
+ # @param [ String ] type Not used in this context.
20
+ #
21
+ # @return [ Array<Document ] The documents.
22
+ def build(type = nil)
23
+ return [] if object.blank?
24
+ return object if object.first.is_a?(Document)
25
+ [].tap do |docs|
26
+ object.each do |attrs|
27
+ if _loading?
28
+ docs << Factory.from_db(klass, attrs)
29
+ else
30
+ docs << Factory.build(klass, attrs)
31
+ end
32
+ end
33
+ sort_documents!(docs, metadata) if metadata.order
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module Embedded #:nodoc:
6
+ class One < Builder #:nodoc:
7
+
8
+ # Builds the document out of the attributes using the provided
9
+ # metadata on the relation. Instantiates through the factory in order
10
+ # to make sure subclasses and allocation are used if fitting.
11
+ #
12
+ # @example Build the document.
13
+ # Builder.new(meta, attrs).build
14
+ #
15
+ # @param [ String ] type Not used in this context.
16
+ #
17
+ # @return [ Document ] A single document.
18
+ def build(type = nil)
19
+ return object unless object.is_a?(Hash)
20
+ if _loading?
21
+ Factory.from_db(klass, object)
22
+ else
23
+ Factory.build(klass, object)
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,110 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module NestedAttributes #:nodoc:
6
+ class Many < NestedBuilder
7
+
8
+ # Builds the relation depending on the attributes and the options
9
+ # passed to the macro.
10
+ #
11
+ # This attempts to perform 3 operations, either one of an update of
12
+ # the existing relation, a replacement of the relation with a new
13
+ # document, or a removal of the relation.
14
+ #
15
+ # @example Build the nested attrs.
16
+ # many.build(person)
17
+ #
18
+ # @param [ Document ] parent The parent document of the relation.
19
+ #
20
+ # @return [ Array ] The attributes.
21
+ def build(parent)
22
+ @existing = parent.send(metadata.name)
23
+ if over_limit?(attributes)
24
+ raise Errors::TooManyNestedAttributeRecords.new(existing, options[:limit])
25
+ end
26
+ attributes.each do |attrs|
27
+ if attrs.respond_to?(:with_indifferent_access)
28
+ process(parent, attrs)
29
+ else
30
+ process(parent, attrs[1])
31
+ end
32
+ end
33
+ end
34
+
35
+ # Create the new builder for nested attributes on one-to-many
36
+ # relations.
37
+ #
38
+ # @example Initialize the builder.
39
+ # One.new(metadata, attributes, options)
40
+ #
41
+ # @param [ Metadata ] metadata The relation metadata.
42
+ # @param [ Hash ] attributes The attributes hash to attempt to set.
43
+ # @param [ Hash ] options The options defined.
44
+ def initialize(metadata, attributes, options = {})
45
+ if attributes.respond_to?(:with_indifferent_access)
46
+ @attributes = attributes.with_indifferent_access.sort do |a, b|
47
+ a[0].to_i <=> b[0].to_i
48
+ end
49
+ else
50
+ @attributes = attributes
51
+ end
52
+ @metadata = metadata
53
+ @options = options
54
+ end
55
+
56
+ private
57
+
58
+ # Can the existing relation potentially be deleted?
59
+ #
60
+ # @example Is the document destroyable?
61
+ # destroyable?({ :_destroy => "1" })
62
+ #
63
+ # @parma [ Hash ] attributes The attributes to pull the flag from.
64
+ #
65
+ # @return [ true, false ] If the relation can potentially be deleted.
66
+ def destroyable?(attributes)
67
+ destroy = attributes.delete(:_destroy)
68
+ [ 1, "1", true, "true" ].include?(destroy) && allow_destroy?
69
+ end
70
+
71
+ # Are the supplied attributes of greater number than the supplied
72
+ # limit?
73
+ #
74
+ # @example Are we over the set limit?
75
+ # builder.over_limit?({ "street" => "Bond" })
76
+ #
77
+ # @param [ Hash ] attributes The attributes being set.
78
+ #
79
+ # @return [ true, false ] If the attributes exceed the limit.
80
+ def over_limit?(attributes)
81
+ limit = options[:limit]
82
+ limit ? attributes.size > limit : false
83
+ end
84
+
85
+ # Process each set of attributes one at a time for each potential
86
+ # new, existing, or ignored document.
87
+ #
88
+ # @example Process the attributes
89
+ # builder.process({ "id" => 1, "street" => "Bond" })
90
+ #
91
+ # @param [ Hash ] attrs The single document attributes to process.
92
+ def process(parent, attrs)
93
+ return if reject?(parent, attrs)
94
+ if id = attrs.extract_id
95
+ doc = existing.find(convert_id(id))
96
+ if destroyable?(attrs)
97
+ existing.delete(doc)
98
+ doc.destroy unless doc.embedded?
99
+ else
100
+ metadata.embedded? ? doc.attributes = attrs : doc.update_attributes(attrs)
101
+ end
102
+ else
103
+ existing.push(Factory.build(metadata.klass, attrs)) unless destroyable?(attrs)
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+ end