mongoid-braxton 2.0.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (226) hide show
  1. data/LICENSE +20 -0
  2. data/README.rdoc +50 -0
  3. data/Rakefile +51 -0
  4. data/lib/config/locales/bg.yml +41 -0
  5. data/lib/config/locales/de.yml +41 -0
  6. data/lib/config/locales/en.yml +45 -0
  7. data/lib/config/locales/es.yml +41 -0
  8. data/lib/config/locales/fr.yml +42 -0
  9. data/lib/config/locales/hu.yml +44 -0
  10. data/lib/config/locales/id.yml +46 -0
  11. data/lib/config/locales/it.yml +39 -0
  12. data/lib/config/locales/ja.yml +40 -0
  13. data/lib/config/locales/kr.yml +65 -0
  14. data/lib/config/locales/nl.yml +39 -0
  15. data/lib/config/locales/pl.yml +39 -0
  16. data/lib/config/locales/pt-BR.yml +40 -0
  17. data/lib/config/locales/pt.yml +40 -0
  18. data/lib/config/locales/ro.yml +46 -0
  19. data/lib/config/locales/ru.yml +41 -0
  20. data/lib/config/locales/sv.yml +40 -0
  21. data/lib/config/locales/vi.yml +45 -0
  22. data/lib/config/locales/zh-CN.yml +33 -0
  23. data/lib/mongoid.rb +140 -0
  24. data/lib/mongoid/atomicity.rb +111 -0
  25. data/lib/mongoid/attributes.rb +185 -0
  26. data/lib/mongoid/attributes/processing.rb +145 -0
  27. data/lib/mongoid/callbacks.rb +23 -0
  28. data/lib/mongoid/collection.rb +137 -0
  29. data/lib/mongoid/collections.rb +71 -0
  30. data/lib/mongoid/collections/master.rb +37 -0
  31. data/lib/mongoid/collections/operations.rb +42 -0
  32. data/lib/mongoid/collections/retry.rb +39 -0
  33. data/lib/mongoid/components.rb +45 -0
  34. data/lib/mongoid/config.rb +349 -0
  35. data/lib/mongoid/config/database.rb +167 -0
  36. data/lib/mongoid/config/replset_database.rb +78 -0
  37. data/lib/mongoid/contexts.rb +19 -0
  38. data/lib/mongoid/contexts/enumerable.rb +275 -0
  39. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  40. data/lib/mongoid/contexts/mongo.rb +345 -0
  41. data/lib/mongoid/copyable.rb +46 -0
  42. data/lib/mongoid/criteria.rb +357 -0
  43. data/lib/mongoid/criterion/builder.rb +34 -0
  44. data/lib/mongoid/criterion/complex.rb +34 -0
  45. data/lib/mongoid/criterion/creational.rb +34 -0
  46. data/lib/mongoid/criterion/exclusion.rb +108 -0
  47. data/lib/mongoid/criterion/inclusion.rb +198 -0
  48. data/lib/mongoid/criterion/inspection.rb +22 -0
  49. data/lib/mongoid/criterion/optional.rb +193 -0
  50. data/lib/mongoid/criterion/selector.rb +143 -0
  51. data/lib/mongoid/criterion/unconvertable.rb +20 -0
  52. data/lib/mongoid/cursor.rb +86 -0
  53. data/lib/mongoid/default_scope.rb +36 -0
  54. data/lib/mongoid/dirty.rb +253 -0
  55. data/lib/mongoid/document.rb +284 -0
  56. data/lib/mongoid/errors.rb +13 -0
  57. data/lib/mongoid/errors/document_not_found.rb +29 -0
  58. data/lib/mongoid/errors/invalid_collection.rb +19 -0
  59. data/lib/mongoid/errors/invalid_database.rb +20 -0
  60. data/lib/mongoid/errors/invalid_field.rb +19 -0
  61. data/lib/mongoid/errors/invalid_options.rb +16 -0
  62. data/lib/mongoid/errors/invalid_type.rb +26 -0
  63. data/lib/mongoid/errors/mixed_relations.rb +37 -0
  64. data/lib/mongoid/errors/mongoid_error.rb +27 -0
  65. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +21 -0
  66. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  67. data/lib/mongoid/errors/unsupported_version.rb +21 -0
  68. data/lib/mongoid/errors/validations.rb +24 -0
  69. data/lib/mongoid/extensions.rb +123 -0
  70. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  71. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  72. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  73. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  74. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  75. data/lib/mongoid/extensions/date/conversions.rb +25 -0
  76. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  77. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  78. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  79. data/lib/mongoid/extensions/hash/conversions.rb +19 -0
  80. data/lib/mongoid/extensions/hash/criteria_helpers.rb +22 -0
  81. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  82. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  83. data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
  84. data/lib/mongoid/extensions/object/checks.rb +32 -0
  85. data/lib/mongoid/extensions/object/conversions.rb +25 -0
  86. data/lib/mongoid/extensions/object/reflections.rb +17 -0
  87. data/lib/mongoid/extensions/object/yoda.rb +27 -0
  88. data/lib/mongoid/extensions/object_id/conversions.rb +96 -0
  89. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  90. data/lib/mongoid/extensions/range/conversions.rb +25 -0
  91. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  92. data/lib/mongoid/extensions/string/conversions.rb +34 -0
  93. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  94. data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
  95. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  96. data/lib/mongoid/extensions/time_conversions.rb +38 -0
  97. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  98. data/lib/mongoid/extras.rb +42 -0
  99. data/lib/mongoid/factory.rb +37 -0
  100. data/lib/mongoid/field.rb +162 -0
  101. data/lib/mongoid/fields.rb +183 -0
  102. data/lib/mongoid/finders.rb +127 -0
  103. data/lib/mongoid/hierarchy.rb +85 -0
  104. data/lib/mongoid/identity.rb +92 -0
  105. data/lib/mongoid/indexes.rb +38 -0
  106. data/lib/mongoid/inspection.rb +54 -0
  107. data/lib/mongoid/javascript.rb +21 -0
  108. data/lib/mongoid/javascript/functions.yml +37 -0
  109. data/lib/mongoid/json.rb +16 -0
  110. data/lib/mongoid/keys.rb +131 -0
  111. data/lib/mongoid/logger.rb +18 -0
  112. data/lib/mongoid/matchers.rb +32 -0
  113. data/lib/mongoid/matchers/all.rb +11 -0
  114. data/lib/mongoid/matchers/default.rb +70 -0
  115. data/lib/mongoid/matchers/exists.rb +13 -0
  116. data/lib/mongoid/matchers/gt.rb +11 -0
  117. data/lib/mongoid/matchers/gte.rb +11 -0
  118. data/lib/mongoid/matchers/in.rb +11 -0
  119. data/lib/mongoid/matchers/lt.rb +11 -0
  120. data/lib/mongoid/matchers/lte.rb +11 -0
  121. data/lib/mongoid/matchers/ne.rb +11 -0
  122. data/lib/mongoid/matchers/nin.rb +11 -0
  123. data/lib/mongoid/matchers/or.rb +30 -0
  124. data/lib/mongoid/matchers/size.rb +11 -0
  125. data/lib/mongoid/matchers/strategies.rb +63 -0
  126. data/lib/mongoid/multi_database.rb +11 -0
  127. data/lib/mongoid/multi_parameter_attributes.rb +82 -0
  128. data/lib/mongoid/named_scope.rb +137 -0
  129. data/lib/mongoid/nested_attributes.rb +51 -0
  130. data/lib/mongoid/observer.rb +67 -0
  131. data/lib/mongoid/paranoia.rb +103 -0
  132. data/lib/mongoid/paths.rb +61 -0
  133. data/lib/mongoid/persistence.rb +240 -0
  134. data/lib/mongoid/persistence/atomic.rb +88 -0
  135. data/lib/mongoid/persistence/atomic/add_to_set.rb +32 -0
  136. data/lib/mongoid/persistence/atomic/inc.rb +28 -0
  137. data/lib/mongoid/persistence/atomic/operation.rb +44 -0
  138. data/lib/mongoid/persistence/atomic/pull_all.rb +33 -0
  139. data/lib/mongoid/persistence/atomic/push.rb +28 -0
  140. data/lib/mongoid/persistence/command.rb +71 -0
  141. data/lib/mongoid/persistence/insert.rb +53 -0
  142. data/lib/mongoid/persistence/insert_embedded.rb +43 -0
  143. data/lib/mongoid/persistence/remove.rb +44 -0
  144. data/lib/mongoid/persistence/remove_all.rb +40 -0
  145. data/lib/mongoid/persistence/remove_embedded.rb +48 -0
  146. data/lib/mongoid/persistence/update.rb +77 -0
  147. data/lib/mongoid/railtie.rb +139 -0
  148. data/lib/mongoid/railties/database.rake +171 -0
  149. data/lib/mongoid/railties/document.rb +12 -0
  150. data/lib/mongoid/relations.rb +107 -0
  151. data/lib/mongoid/relations/accessors.rb +175 -0
  152. data/lib/mongoid/relations/auto_save.rb +34 -0
  153. data/lib/mongoid/relations/binding.rb +26 -0
  154. data/lib/mongoid/relations/bindings.rb +9 -0
  155. data/lib/mongoid/relations/bindings/embedded/in.rb +82 -0
  156. data/lib/mongoid/relations/bindings/embedded/many.rb +98 -0
  157. data/lib/mongoid/relations/bindings/embedded/one.rb +66 -0
  158. data/lib/mongoid/relations/bindings/referenced/in.rb +74 -0
  159. data/lib/mongoid/relations/bindings/referenced/many.rb +96 -0
  160. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +103 -0
  161. data/lib/mongoid/relations/bindings/referenced/one.rb +66 -0
  162. data/lib/mongoid/relations/builder.rb +42 -0
  163. data/lib/mongoid/relations/builders.rb +79 -0
  164. data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
  165. data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
  166. data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
  167. data/lib/mongoid/relations/builders/nested_attributes/many.rb +126 -0
  168. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  169. data/lib/mongoid/relations/builders/referenced/in.rb +29 -0
  170. data/lib/mongoid/relations/builders/referenced/many.rb +47 -0
  171. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
  172. data/lib/mongoid/relations/builders/referenced/one.rb +27 -0
  173. data/lib/mongoid/relations/cascading.rb +55 -0
  174. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  175. data/lib/mongoid/relations/cascading/destroy.rb +19 -0
  176. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  177. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  178. data/lib/mongoid/relations/constraint.rb +42 -0
  179. data/lib/mongoid/relations/cyclic.rb +103 -0
  180. data/lib/mongoid/relations/embedded/atomic.rb +86 -0
  181. data/lib/mongoid/relations/embedded/atomic/operation.rb +63 -0
  182. data/lib/mongoid/relations/embedded/atomic/pull.rb +65 -0
  183. data/lib/mongoid/relations/embedded/atomic/push_all.rb +59 -0
  184. data/lib/mongoid/relations/embedded/atomic/set.rb +61 -0
  185. data/lib/mongoid/relations/embedded/atomic/unset.rb +41 -0
  186. data/lib/mongoid/relations/embedded/in.rb +173 -0
  187. data/lib/mongoid/relations/embedded/many.rb +499 -0
  188. data/lib/mongoid/relations/embedded/one.rb +170 -0
  189. data/lib/mongoid/relations/macros.rb +310 -0
  190. data/lib/mongoid/relations/many.rb +215 -0
  191. data/lib/mongoid/relations/metadata.rb +539 -0
  192. data/lib/mongoid/relations/nested_builder.rb +68 -0
  193. data/lib/mongoid/relations/one.rb +47 -0
  194. data/lib/mongoid/relations/polymorphic.rb +54 -0
  195. data/lib/mongoid/relations/proxy.rb +143 -0
  196. data/lib/mongoid/relations/referenced/batch.rb +71 -0
  197. data/lib/mongoid/relations/referenced/batch/insert.rb +57 -0
  198. data/lib/mongoid/relations/referenced/in.rb +216 -0
  199. data/lib/mongoid/relations/referenced/many.rb +516 -0
  200. data/lib/mongoid/relations/referenced/many_to_many.rb +396 -0
  201. data/lib/mongoid/relations/referenced/one.rb +222 -0
  202. data/lib/mongoid/relations/reflections.rb +45 -0
  203. data/lib/mongoid/safe.rb +23 -0
  204. data/lib/mongoid/safety.rb +207 -0
  205. data/lib/mongoid/scope.rb +31 -0
  206. data/lib/mongoid/serialization.rb +99 -0
  207. data/lib/mongoid/sharding.rb +51 -0
  208. data/lib/mongoid/state.rb +67 -0
  209. data/lib/mongoid/timestamps.rb +14 -0
  210. data/lib/mongoid/timestamps/created.rb +31 -0
  211. data/lib/mongoid/timestamps/updated.rb +33 -0
  212. data/lib/mongoid/validations.rb +124 -0
  213. data/lib/mongoid/validations/associated.rb +44 -0
  214. data/lib/mongoid/validations/referenced.rb +58 -0
  215. data/lib/mongoid/validations/uniqueness.rb +85 -0
  216. data/lib/mongoid/version.rb +4 -0
  217. data/lib/mongoid/versioning.rb +113 -0
  218. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  219. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +20 -0
  220. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  221. data/lib/rails/generators/mongoid/model/templates/model.rb +19 -0
  222. data/lib/rails/generators/mongoid/observer/observer_generator.rb +17 -0
  223. data/lib/rails/generators/mongoid/observer/templates/observer.rb +4 -0
  224. data/lib/rails/generators/mongoid_generator.rb +70 -0
  225. data/lib/rails/mongoid.rb +58 -0
  226. metadata +406 -0
@@ -0,0 +1,103 @@
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 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 all the documents.
17
+ # person.preferences.bind
18
+ # person.preferences = [ Preference.new ]
19
+ #
20
+ # @param [ Hash ] options The binding options.
21
+ #
22
+ # @option options [ true, false ] :continue Continue binding the inverse.
23
+ # @option options [ true, false ] :binding Are we in build mode?
24
+ #
25
+ # @since 2.0.0.rc.1
26
+ def bind(options = {})
27
+ target.each { |doc| bind_one(doc, options) }
28
+ end
29
+
30
+ # Binds a single document with the inverse relation. Used
31
+ # specifically when appending to the proxy.
32
+ #
33
+ # @example Bind one document.
34
+ # person.preferences.bind_one(preference)
35
+ #
36
+ # @param [ Document ] doc The single document to bind.
37
+ # @param [ Hash ] options The binding options.
38
+ #
39
+ # @option options [ true, false ] :continue Continue binding the inverse.
40
+ # @option options [ true, false ] :binding Are we in build mode?
41
+ #
42
+ # @since 2.0.0.rc.1
43
+ def bind_one(doc, options = {})
44
+ if options[:continue]
45
+ inverse = metadata.inverse(target)
46
+ if inverse
47
+ doc.do_or_do_not(
48
+ inverse,
49
+ false,
50
+ OPTIONS
51
+ ).push(base, :binding => true, :continue => false)
52
+ end
53
+ end
54
+ end
55
+
56
+ # Unbinds the base object and the inverse, caused by setting the
57
+ # reference to nil.
58
+ #
59
+ # @example Unbind the documents.
60
+ # person.preferences.unbind
61
+ # person.preferences = nil
62
+ #
63
+ # @param [ Hash ] options The binding options.
64
+ #
65
+ # @option options [ true, false ] :continue Continue binding the inverse.
66
+ # @option options [ true, false ] :binding Are we in build mode?
67
+ #
68
+ # @since 2.0.0.rc.1
69
+ def unbind(options = {})
70
+ target.each { |doc| unbind_one(doc, options) }
71
+ end
72
+
73
+ # Unbind a single document.
74
+ #
75
+ # @example Unbind the document.
76
+ # person.preferences.unbind_one(document)
77
+ #
78
+ # @todo Durran: Get rid of persistence operation in this method.
79
+ #
80
+ # @param [ Hash ] options The binding options.
81
+ #
82
+ # @option options [ true, false ] :continue Continue binding the inverse.
83
+ # @option options [ true, false ] :binding Are we in build mode?
84
+ #
85
+ # @since 2.0.0.rc.1
86
+ def unbind_one(doc, options = {})
87
+ base.do_or_do_not(metadata.foreign_key).delete(doc.id)
88
+ if options[:continue]
89
+ inverse = metadata.inverse(target)
90
+ if inverse
91
+ doc.do_or_do_not(
92
+ inverse, false, OPTIONS
93
+ ).delete(base, :binding => true, :continue => false)
94
+ end
95
+ else
96
+ base.save if base.persisted?
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
102
+ end
103
+ end
@@ -0,0 +1,66 @@
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
+ # @param [ Hash ] options The options to pass through.
21
+ #
22
+ # @option options [ true, false ] :continue Do we continue binding?
23
+ # @option options [ true, false ] :binding Are we in build mode?
24
+ #
25
+ # @since 2.0.0.rc.1
26
+ def bind(options = {})
27
+ if options[:continue]
28
+ target.do_or_do_not(metadata.foreign_key_setter, base.id)
29
+ target.do_or_do_not(
30
+ metadata.inverse_setter,
31
+ base,
32
+ OPTIONS
33
+ )
34
+ end
35
+ end
36
+ alias :bind_one :bind
37
+
38
+ # Unbinds the base object and the inverse, caused by setting the
39
+ # reference to nil.
40
+ #
41
+ # @example Unbind the document.
42
+ # person.game.unbind(:continue => true)
43
+ # person.game = nil
44
+ #
45
+ # @param [ Hash ] options The options to pass through.
46
+ #
47
+ # @option options [ true, false ] :continue Do we continue unbinding?
48
+ # @option options [ true, false ] :binding Are we in build mode?
49
+ #
50
+ # @since 2.0.0.rc.1
51
+ def unbind(options = {})
52
+ if options[:continue]
53
+ target.do_or_do_not(metadata.foreign_key_setter, nil)
54
+ target.do_or_do_not(
55
+ metadata.inverse_setter,
56
+ nil,
57
+ OPTIONS
58
+ )
59
+ end
60
+ end
61
+ alias :unbind_one :unbind
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,42 @@
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
+
10
+ attr_reader :metadata, :object
11
+ # Instantiate the new builder for a relation.
12
+ #
13
+ # @example Create the builder.
14
+ # Builder.new(metadata, { :field => "value })
15
+ #
16
+ # @param [ Metdata ] metadata The metadata for the relation.
17
+ # @param [ Hash, BSON::ObjectId ] object The attributes to build from or
18
+ # id to query with.
19
+ #
20
+ # @since 2.0.0.rc.1
21
+ def initialize(metadata, object)
22
+ @metadata, @object = metadata, object
23
+ end
24
+
25
+ protected
26
+ # Do we need to perform a database query? It will be so if the object we
27
+ # have is not a document.
28
+ #
29
+ # @example Should we query the database?
30
+ # builder.query?
31
+ #
32
+ # @return [ true, false ] Whether a database query should happen.
33
+ #
34
+ # @since 2.0.0.rc.1
35
+ def query?
36
+ return true unless object.respond_to?(:to_a)
37
+ obj = object.to_a.first
38
+ !obj.respond_to?(:attributes) && !obj.nil?
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,79 @@
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
+ document = Factory.build(metadata.klass, args.first || {})
52
+ send("#{name}=", document, :binding => true)
53
+ end
54
+ end
55
+ end
56
+
57
+ # Defines a creator method for an embeds_one relation. This is
58
+ # defined as #create_name. After the object is built it will
59
+ # immediately save.
60
+ #
61
+ # @example
62
+ # Person.creator("name")
63
+ #
64
+ # @param [ String, Symbol ] name The name of the relation.
65
+ #
66
+ # @return [ Class ] The class being set up.
67
+ #
68
+ # @since 2.0.0.rc.1
69
+ def creator(name)
70
+ tap do
71
+ define_method("create_#{name}") do |*args|
72
+ send("build_#{name}", *args).tap(&:save)
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,25 @@
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
+ Mongoid::Factory.from_db(metadata.klass, object)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module Embedded #:nodoc:
6
+ class Many < 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. This
11
+ # case will return many documents.
12
+ #
13
+ # @example Build the documents.
14
+ # Builder.new(meta, attrs).build
15
+ #
16
+ # @param [ String ] type Not used in this context.
17
+ #
18
+ # @return [ Array<Document ] The documents.
19
+ def build(type = nil)
20
+ return [] if object.blank?
21
+ return object if object.first.is_a?(Document)
22
+ object.inject([]) do |documents, attrs|
23
+ documents.tap do |docs|
24
+ docs << Mongoid::Factory.from_db(metadata.klass, attrs)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,26 @@
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
+ Mongoid::Factory.from_db(metadata.klass, object)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,126 @@
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:
16
+ #
17
+ # <tt>many.build(person)</tt>
18
+ #
19
+ # Options:
20
+ #
21
+ # parent: The parent document of the relation.
22
+ def build(parent)
23
+ @existing = parent.send(metadata.name)
24
+ if over_limit?(attributes)
25
+ raise Errors::TooManyNestedAttributeRecords.new(existing, options[:limit])
26
+ end
27
+ attributes.each do |attrs|
28
+ if attrs.respond_to?(:with_indifferent_access)
29
+ process(attrs)
30
+ else
31
+ process(attrs[1])
32
+ end
33
+ end
34
+ end
35
+
36
+ # Create the new builder for nested attributes on one-to-many
37
+ # relations.
38
+ #
39
+ # Example:
40
+ #
41
+ # <tt>One.new(metadata, attributes, options)</tt>
42
+ #
43
+ # Options:
44
+ #
45
+ # metadata: The relation metadata
46
+ # attributes: The attributes hash to attempt to set.
47
+ # options: The options defined.
48
+ #
49
+ # Returns:
50
+ #
51
+ # A new builder.
52
+ def initialize(metadata, attributes, options = {})
53
+ if attributes.respond_to?(:with_indifferent_access)
54
+ @attributes = attributes.with_indifferent_access.sort do |a, b|
55
+ a[0].to_i <=> b[0].to_i
56
+ end
57
+ else
58
+ @attributes = attributes
59
+ end
60
+ @metadata = metadata
61
+ @options = options
62
+ end
63
+
64
+ private
65
+
66
+ # Can the existing relation potentially be deleted?
67
+ #
68
+ # Example:
69
+ #
70
+ # <tt>destroyable?({ :_destroy => "1" })</tt>
71
+ #
72
+ # Options:
73
+ #
74
+ # attributes: The attributes to pull the flag from.
75
+ #
76
+ # Returns:
77
+ #
78
+ # True if the relation can potentially be deleted.
79
+ def destroyable?(attributes)
80
+ destroy = attributes.delete(:_destroy)
81
+ [ 1, "1", true, "true" ].include?(destroy) && allow_destroy?
82
+ end
83
+
84
+ # Are the supplied attributes of greater number than the supplied
85
+ # limit?
86
+ #
87
+ # Example:
88
+ #
89
+ # <tt>builder.over_limit?({ "street" => "Bond" })</tt>
90
+ #
91
+ # Options:
92
+ #
93
+ # attributes: The attributes being set.
94
+ #
95
+ # Returns:
96
+ #
97
+ # True if a limit supplied and the attributes are of greater number.
98
+ def over_limit?(attributes)
99
+ limit = options[:limit]
100
+ limit ? attributes.size > limit : false
101
+ end
102
+
103
+ # Process each set of attributes one at a time for each potential
104
+ # new, existing, or ignored document.
105
+ #
106
+ # Example:
107
+ #
108
+ # <tt>builder.process({ "id" => 1, "street" => "Bond" })
109
+ #
110
+ # Options:
111
+ #
112
+ # attrs: The single document attributes to process.
113
+ def process(attrs)
114
+ return if reject?(attrs)
115
+ if id = attrs[:id] || attrs["id"] || attrs["_id"]
116
+ document = existing.find(convert_id(id))
117
+ destroyable?(attrs) ? document.destroy : document.update_attributes(attrs)
118
+ else
119
+ existing.push(metadata.klass.new(attrs)) unless destroyable?(attrs)
120
+ end
121
+ end
122
+ end
123
+ end
124
+ end
125
+ end
126
+ end