stonegao-mongoid 2.0.0.rc.6

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 (199) 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 +44 -0
  5. data/lib/config/locales/de.yml +44 -0
  6. data/lib/config/locales/en.yml +45 -0
  7. data/lib/config/locales/es.yml +44 -0
  8. data/lib/config/locales/fr.yml +45 -0
  9. data/lib/config/locales/hu.yml +47 -0
  10. data/lib/config/locales/it.yml +42 -0
  11. data/lib/config/locales/kr.yml +68 -0
  12. data/lib/config/locales/nl.yml +42 -0
  13. data/lib/config/locales/pl.yml +42 -0
  14. data/lib/config/locales/pt-br.yml +43 -0
  15. data/lib/config/locales/pt.yml +43 -0
  16. data/lib/config/locales/ro.yml +49 -0
  17. data/lib/config/locales/sv.yml +43 -0
  18. data/lib/config/locales/zh-CN.yml +34 -0
  19. data/lib/mongoid/atomicity.rb +111 -0
  20. data/lib/mongoid/attributes.rb +251 -0
  21. data/lib/mongoid/callbacks.rb +13 -0
  22. data/lib/mongoid/collection.rb +137 -0
  23. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  24. data/lib/mongoid/collections/master.rb +29 -0
  25. data/lib/mongoid/collections/operations.rb +42 -0
  26. data/lib/mongoid/collections/slaves.rb +45 -0
  27. data/lib/mongoid/collections.rb +70 -0
  28. data/lib/mongoid/components.rb +45 -0
  29. data/lib/mongoid/config/database.rb +167 -0
  30. data/lib/mongoid/config/replset_database.rb +48 -0
  31. data/lib/mongoid/config.rb +343 -0
  32. data/lib/mongoid/contexts/enumerable/sort.rb +43 -0
  33. data/lib/mongoid/contexts/enumerable.rb +226 -0
  34. data/lib/mongoid/contexts/ids.rb +25 -0
  35. data/lib/mongoid/contexts/mongo.rb +345 -0
  36. data/lib/mongoid/contexts/paging.rb +50 -0
  37. data/lib/mongoid/contexts.rb +21 -0
  38. data/lib/mongoid/copyable.rb +44 -0
  39. data/lib/mongoid/criteria.rb +325 -0
  40. data/lib/mongoid/criterion/complex.rb +34 -0
  41. data/lib/mongoid/criterion/creational.rb +34 -0
  42. data/lib/mongoid/criterion/exclusion.rb +67 -0
  43. data/lib/mongoid/criterion/inclusion.rb +134 -0
  44. data/lib/mongoid/criterion/inspection.rb +20 -0
  45. data/lib/mongoid/criterion/optional.rb +213 -0
  46. data/lib/mongoid/criterion/selector.rb +74 -0
  47. data/lib/mongoid/cursor.rb +81 -0
  48. data/lib/mongoid/default_scope.rb +28 -0
  49. data/lib/mongoid/dirty.rb +251 -0
  50. data/lib/mongoid/document.rb +256 -0
  51. data/lib/mongoid/errors/document_not_found.rb +29 -0
  52. data/lib/mongoid/errors/invalid_collection.rb +19 -0
  53. data/lib/mongoid/errors/invalid_database.rb +20 -0
  54. data/lib/mongoid/errors/invalid_field.rb +19 -0
  55. data/lib/mongoid/errors/invalid_options.rb +16 -0
  56. data/lib/mongoid/errors/invalid_type.rb +26 -0
  57. data/lib/mongoid/errors/mongoid_error.rb +27 -0
  58. data/lib/mongoid/errors/too_many_nested_attribute_records.rb +21 -0
  59. data/lib/mongoid/errors/unsaved_document.rb +23 -0
  60. data/lib/mongoid/errors/unsupported_version.rb +21 -0
  61. data/lib/mongoid/errors/validations.rb +24 -0
  62. data/lib/mongoid/errors.rb +12 -0
  63. data/lib/mongoid/extensions/array/conversions.rb +23 -0
  64. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  65. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  66. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  67. data/lib/mongoid/extensions/boolean/conversions.rb +27 -0
  68. data/lib/mongoid/extensions/date/conversions.rb +25 -0
  69. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  70. data/lib/mongoid/extensions/false_class/equality.rb +13 -0
  71. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  72. data/lib/mongoid/extensions/hash/conversions.rb +19 -0
  73. data/lib/mongoid/extensions/hash/criteria_helpers.rb +22 -0
  74. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  75. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  76. data/lib/mongoid/extensions/nil/collectionization.rb +12 -0
  77. data/lib/mongoid/extensions/object/conversions.rb +25 -0
  78. data/lib/mongoid/extensions/object/reflections.rb +17 -0
  79. data/lib/mongoid/extensions/object/yoda.rb +27 -0
  80. data/lib/mongoid/extensions/object_id/conversions.rb +57 -0
  81. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  82. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  83. data/lib/mongoid/extensions/string/conversions.rb +34 -0
  84. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  85. data/lib/mongoid/extensions/symbol/conversions.rb +21 -0
  86. data/lib/mongoid/extensions/symbol/inflections.rb +40 -0
  87. data/lib/mongoid/extensions/time_conversions.rb +38 -0
  88. data/lib/mongoid/extensions/true_class/equality.rb +13 -0
  89. data/lib/mongoid/extensions.rb +116 -0
  90. data/lib/mongoid/extras.rb +61 -0
  91. data/lib/mongoid/factory.rb +20 -0
  92. data/lib/mongoid/field.rb +95 -0
  93. data/lib/mongoid/fields.rb +138 -0
  94. data/lib/mongoid/finders.rb +173 -0
  95. data/lib/mongoid/hierarchy.rb +85 -0
  96. data/lib/mongoid/identity.rb +89 -0
  97. data/lib/mongoid/indexes.rb +38 -0
  98. data/lib/mongoid/inspection.rb +58 -0
  99. data/lib/mongoid/javascript/functions.yml +37 -0
  100. data/lib/mongoid/javascript.rb +21 -0
  101. data/lib/mongoid/json.rb +16 -0
  102. data/lib/mongoid/keys.rb +77 -0
  103. data/lib/mongoid/logger.rb +18 -0
  104. data/lib/mongoid/matchers/all.rb +11 -0
  105. data/lib/mongoid/matchers/default.rb +27 -0
  106. data/lib/mongoid/matchers/exists.rb +13 -0
  107. data/lib/mongoid/matchers/gt.rb +11 -0
  108. data/lib/mongoid/matchers/gte.rb +11 -0
  109. data/lib/mongoid/matchers/in.rb +11 -0
  110. data/lib/mongoid/matchers/lt.rb +11 -0
  111. data/lib/mongoid/matchers/lte.rb +11 -0
  112. data/lib/mongoid/matchers/ne.rb +11 -0
  113. data/lib/mongoid/matchers/nin.rb +11 -0
  114. data/lib/mongoid/matchers/size.rb +11 -0
  115. data/lib/mongoid/matchers.rb +55 -0
  116. data/lib/mongoid/modifiers/command.rb +18 -0
  117. data/lib/mongoid/modifiers/inc.rb +24 -0
  118. data/lib/mongoid/modifiers.rb +24 -0
  119. data/lib/mongoid/multi_database.rb +11 -0
  120. data/lib/mongoid/multi_parameter_attributes.rb +80 -0
  121. data/lib/mongoid/named_scope.rb +36 -0
  122. data/lib/mongoid/nested_attributes.rb +43 -0
  123. data/lib/mongoid/paranoia.rb +103 -0
  124. data/lib/mongoid/paths.rb +61 -0
  125. data/lib/mongoid/persistence/command.rb +59 -0
  126. data/lib/mongoid/persistence/insert.rb +53 -0
  127. data/lib/mongoid/persistence/insert_embedded.rb +42 -0
  128. data/lib/mongoid/persistence/remove.rb +44 -0
  129. data/lib/mongoid/persistence/remove_all.rb +40 -0
  130. data/lib/mongoid/persistence/remove_embedded.rb +48 -0
  131. data/lib/mongoid/persistence/update.rb +76 -0
  132. data/lib/mongoid/persistence.rb +237 -0
  133. data/lib/mongoid/railtie.rb +129 -0
  134. data/lib/mongoid/railties/database.rake +171 -0
  135. data/lib/mongoid/railties/document.rb +12 -0
  136. data/lib/mongoid/relations/accessors.rb +157 -0
  137. data/lib/mongoid/relations/auto_save.rb +34 -0
  138. data/lib/mongoid/relations/binding.rb +26 -0
  139. data/lib/mongoid/relations/bindings/embedded/in.rb +82 -0
  140. data/lib/mongoid/relations/bindings/embedded/many.rb +98 -0
  141. data/lib/mongoid/relations/bindings/embedded/one.rb +66 -0
  142. data/lib/mongoid/relations/bindings/referenced/in.rb +74 -0
  143. data/lib/mongoid/relations/bindings/referenced/many.rb +96 -0
  144. data/lib/mongoid/relations/bindings/referenced/many_to_many.rb +99 -0
  145. data/lib/mongoid/relations/bindings/referenced/one.rb +66 -0
  146. data/lib/mongoid/relations/bindings.rb +9 -0
  147. data/lib/mongoid/relations/builder.rb +42 -0
  148. data/lib/mongoid/relations/builders/embedded/in.rb +25 -0
  149. data/lib/mongoid/relations/builders/embedded/many.rb +32 -0
  150. data/lib/mongoid/relations/builders/embedded/one.rb +26 -0
  151. data/lib/mongoid/relations/builders/nested_attributes/many.rb +116 -0
  152. data/lib/mongoid/relations/builders/nested_attributes/one.rb +135 -0
  153. data/lib/mongoid/relations/builders/referenced/in.rb +32 -0
  154. data/lib/mongoid/relations/builders/referenced/many.rb +26 -0
  155. data/lib/mongoid/relations/builders/referenced/many_to_many.rb +29 -0
  156. data/lib/mongoid/relations/builders/referenced/one.rb +30 -0
  157. data/lib/mongoid/relations/builders.rb +79 -0
  158. data/lib/mongoid/relations/cascading/delete.rb +19 -0
  159. data/lib/mongoid/relations/cascading/destroy.rb +19 -0
  160. data/lib/mongoid/relations/cascading/nullify.rb +18 -0
  161. data/lib/mongoid/relations/cascading/strategy.rb +26 -0
  162. data/lib/mongoid/relations/cascading.rb +55 -0
  163. data/lib/mongoid/relations/constraint.rb +45 -0
  164. data/lib/mongoid/relations/cyclic.rb +97 -0
  165. data/lib/mongoid/relations/embedded/in.rb +173 -0
  166. data/lib/mongoid/relations/embedded/many.rb +483 -0
  167. data/lib/mongoid/relations/embedded/one.rb +170 -0
  168. data/lib/mongoid/relations/macros.rb +306 -0
  169. data/lib/mongoid/relations/many.rb +171 -0
  170. data/lib/mongoid/relations/metadata.rb +533 -0
  171. data/lib/mongoid/relations/nested_builder.rb +68 -0
  172. data/lib/mongoid/relations/one.rb +47 -0
  173. data/lib/mongoid/relations/polymorphic.rb +54 -0
  174. data/lib/mongoid/relations/proxy.rb +128 -0
  175. data/lib/mongoid/relations/referenced/in.rb +216 -0
  176. data/lib/mongoid/relations/referenced/many.rb +443 -0
  177. data/lib/mongoid/relations/referenced/many_to_many.rb +344 -0
  178. data/lib/mongoid/relations/referenced/one.rb +206 -0
  179. data/lib/mongoid/relations/reflections.rb +45 -0
  180. data/lib/mongoid/relations.rb +105 -0
  181. data/lib/mongoid/safe.rb +23 -0
  182. data/lib/mongoid/safety.rb +207 -0
  183. data/lib/mongoid/scope.rb +31 -0
  184. data/lib/mongoid/serialization.rb +99 -0
  185. data/lib/mongoid/state.rb +66 -0
  186. data/lib/mongoid/timestamps.rb +38 -0
  187. data/lib/mongoid/validations/associated.rb +42 -0
  188. data/lib/mongoid/validations/uniqueness.rb +85 -0
  189. data/lib/mongoid/validations.rb +117 -0
  190. data/lib/mongoid/version.rb +4 -0
  191. data/lib/mongoid/versioning.rb +51 -0
  192. data/lib/mongoid.rb +139 -0
  193. data/lib/rails/generators/mongoid/config/config_generator.rb +25 -0
  194. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +23 -0
  195. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  196. data/lib/rails/generators/mongoid/model/templates/model.rb +17 -0
  197. data/lib/rails/generators/mongoid_generator.rb +61 -0
  198. data/lib/rails/mongoid.rb +57 -0
  199. metadata +380 -0
@@ -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.build(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.build(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.build(metadata.klass, object)
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,116 @@
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 { |attrs| process(attrs[1]) }
28
+ end
29
+
30
+ # Create the new builder for nested attributes on one-to-one
31
+ # relations.
32
+ #
33
+ # Example:
34
+ #
35
+ # <tt>One.new(metadata, attributes, options)</tt>
36
+ #
37
+ # Options:
38
+ #
39
+ # metadata: The relation metadata
40
+ # attributes: The attributes hash to attempt to set.
41
+ # options: The options defined.
42
+ #
43
+ # Returns:
44
+ #
45
+ # A new builder.
46
+ def initialize(metadata, attributes, options = {})
47
+ @attributes = attributes.with_indifferent_access.sort do |a, b|
48
+ a[0] <=> b[0]
49
+ end
50
+ @metadata = metadata
51
+ @options = options
52
+ end
53
+
54
+ private
55
+
56
+ # Can the existing relation potentially be deleted?
57
+ #
58
+ # Example:
59
+ #
60
+ # <tt>destroyable?({ :_destroy => "1" })</tt>
61
+ #
62
+ # Options:
63
+ #
64
+ # attributes: The attributes to pull the flag from.
65
+ #
66
+ # Returns:
67
+ #
68
+ # True if the relation can potentially be deleted.
69
+ def destroyable?(attributes)
70
+ destroy = attributes.delete(:_destroy)
71
+ [ 1, "1", true, "true" ].include?(destroy) && allow_destroy?
72
+ end
73
+
74
+ # Are the supplied attributes of greater number than the supplied
75
+ # limit?
76
+ #
77
+ # Example:
78
+ #
79
+ # <tt>builder.over_limit?({ "street" => "Bond" })</tt>
80
+ #
81
+ # Options:
82
+ #
83
+ # attributes: The attributes being set.
84
+ #
85
+ # Returns:
86
+ #
87
+ # True if a limit supplied and the attributes are of greater number.
88
+ def over_limit?(attributes)
89
+ limit = options[:limit]
90
+ limit ? attributes.size > limit : false
91
+ end
92
+
93
+ # Process each set of attributes one at a time for each potential
94
+ # new, existing, or ignored document.
95
+ #
96
+ # Example:
97
+ #
98
+ # <tt>builder.process({ "id" => 1, "street" => "Bond" })
99
+ #
100
+ # Options:
101
+ #
102
+ # attrs: The single document attributes to process.
103
+ def process(attrs)
104
+ return if reject?(attrs)
105
+ if attrs[:id]
106
+ document = existing.find(convert_id(attrs[:id]))
107
+ destroyable?(attrs) ? document.destroy : document.update_attributes(attrs)
108
+ else
109
+ existing.push(metadata.klass.new(attrs)) unless destroyable?(attrs)
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,135 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module NestedAttributes #:nodoc:
6
+ class One < NestedBuilder
7
+
8
+ attr_accessor :destroy
9
+
10
+ # Builds the relation depending on the attributes and the options
11
+ # passed to the macro.
12
+ #
13
+ # This attempts to perform 3 operations, either one of an update of
14
+ # the existing relation, a replacement of the relation with a new
15
+ # document, or a removal of the relation.
16
+ #
17
+ # Example:
18
+ #
19
+ # <tt>one.build(person)</tt>
20
+ #
21
+ # Options:
22
+ #
23
+ # parent: The parent document of the relation.
24
+ def build(parent)
25
+ return if reject?(attributes)
26
+ @existing = parent.send(metadata.name)
27
+ if update?
28
+ existing.attributes = attributes
29
+ elsif replace?
30
+ parent.send(metadata.setter, metadata.klass.new(attributes))
31
+ elsif delete?
32
+ parent.send(metadata.setter, nil)
33
+ end
34
+ end
35
+
36
+ # Create the new builder for nested attributes on one-to-one
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
+ @attributes = attributes.with_indifferent_access
54
+ @metadata = metadata
55
+ @options = options
56
+ @destroy = @attributes.delete(:_destroy)
57
+ end
58
+
59
+ private
60
+
61
+ # Is the id in the attribtues acceptable for allowing an update to
62
+ # the existing relation?
63
+ #
64
+ # Example:
65
+ #
66
+ # <tt>acceptable_id?</tt>
67
+ #
68
+ # Returns:
69
+ #
70
+ # True if the id part of the logic will allow an update.
71
+ def acceptable_id?
72
+ id = convert_id(attributes[:id])
73
+ existing.id == id || id.nil? || (existing.id != id && update_only?)
74
+ end
75
+
76
+ # Can the existing relation be deleted?
77
+ #
78
+ # Example:
79
+ #
80
+ # <tt>delete?</tt>
81
+ #
82
+ # Returns:
83
+ #
84
+ # True if the relation should be deleted.
85
+ def delete?
86
+ destroyable? && !attributes[:id].nil?
87
+ end
88
+
89
+ # Can the existing relation potentially be deleted?
90
+ #
91
+ # Example:
92
+ #
93
+ # <tt>destroyable?({ :_destroy => "1" })</tt>
94
+ #
95
+ # Options:
96
+ #
97
+ # attributes: The attributes to pull the flag from.
98
+ #
99
+ # Returns:
100
+ #
101
+ # True if the relation can potentially be deleted.
102
+ def destroyable?
103
+ [ 1, "1", true, "true" ].include?(destroy) && allow_destroy?
104
+ end
105
+
106
+ # Is the document to be replaced?
107
+ #
108
+ # Example:
109
+ #
110
+ # <tt>replace?</tt>
111
+ #
112
+ # Returns:
113
+ #
114
+ # True if the document should be replaced.
115
+ def replace?
116
+ !existing && !destroyable? && !attributes.blank?
117
+ end
118
+
119
+ # Should the document be updated?
120
+ #
121
+ # Example:
122
+ #
123
+ # <tt>update?</tt>
124
+ #
125
+ # Returns:
126
+ #
127
+ # True if the object should have its attributes updated.
128
+ def update?
129
+ existing && !destroyable? && acceptable_id?
130
+ end
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module Referenced #:nodoc:
6
+ class In < Builder
7
+
8
+ # This builder either takes a foreign key and queries for the
9
+ # object or a document, where it will just return it.
10
+ #
11
+ # @example Build the document.
12
+ # Builder.new(meta, attrs).build
13
+ #
14
+ # @param [ String ] type The type of document to query for.
15
+ #
16
+ # @return [ Document ] A single document.
17
+ def build(type = nil)
18
+ return object unless query?
19
+ if object.is_a?(Hash)
20
+ return Mongoid::Factory.build(metadata.klass, object)
21
+ end
22
+ begin
23
+ (type ? type.constantize : metadata.klass).find(object)
24
+ rescue Errors::DocumentNotFound
25
+ return nil
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 Referenced #:nodoc:
6
+ class Many < Builder
7
+
8
+ # This builder either takes a hash and queries for the
9
+ # object or an array of documents, where it will just return tem.
10
+ #
11
+ # @example Build the documents.
12
+ # Builder.new(meta, attrs).build
13
+ #
14
+ # @param [ String ] type The type of document to query for.
15
+ #
16
+ # @return [ Array<Document> ] The documents.
17
+ def build(type = nil)
18
+ return object unless query?
19
+ key = metadata.foreign_key
20
+ metadata.klass.find(:conditions => { key => object })
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module Referenced #:nodoc:
6
+ class ManyToMany < Builder
7
+
8
+ # This builder either takes a hash and queries for the
9
+ # object or an array of documents, where it will just return them.
10
+ #
11
+ # @example Build the documents.
12
+ # Builder.new(meta, attrs).build
13
+ #
14
+ # @param [ String ] type The type of document to query for.
15
+ #
16
+ # @return [ Array<Document> ] The documents.
17
+ def build(type = nil)
18
+ return object.try(:dup) unless query?
19
+ begin
20
+ metadata.klass.find(object)
21
+ rescue Errors::DocumentNotFound
22
+ return []
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,30 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Builders #:nodoc:
5
+ module Referenced #:nodoc:
6
+ class One < Builder
7
+
8
+ # This builder either takes an _id or an object and queries for the
9
+ # inverse side using the id or sets the object.
10
+ #
11
+ # @example Build the document.
12
+ # Builder.new(meta, attrs).build
13
+ #
14
+ # @param [ String ] type The type of document to query for.
15
+ #
16
+ # @return [ Document ] A single document.
17
+ def build(type = nil)
18
+ return object unless query?
19
+ if object.is_a?(Hash)
20
+ return Mongoid::Factory.build(metadata.klass, object)
21
+ end
22
+ metadata.klass.first(
23
+ :conditions => { metadata.foreign_key => object }
24
+ )
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ 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)
49
+ tap do
50
+ define_method("build_#{name}") do |*args|
51
+ attributes = (args.any? ? args : []) + [{:binding => true}]
52
+ send("#{name}=", *attributes)
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,19 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Cascading #:nodoc:
5
+ class Delete < Strategy
6
+
7
+ # Execute the cascading deletion for the relation if it already exists.
8
+ # This should be optimized in the future potentially not to load all
9
+ # objects from the db.
10
+ #
11
+ # @example Perform the cascading delete.
12
+ # strategy.cascade
13
+ def cascade
14
+ relation.to_a.each { |doc| doc.delete } if relation
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Cascading #:nodoc:
5
+ class Destroy < Strategy
6
+
7
+ # Execute the cascading deletion for the relation if it already exists.
8
+ # This should be optimized in the future potentially not to load all
9
+ # objects from the db.
10
+ #
11
+ # @example Perform the cascading destroy.
12
+ # strategy.cascade
13
+ def cascade
14
+ relation.to_a.each { |doc| doc.destroy } if relation
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Cascading #:nodoc:
5
+ class Nullify < Strategy
6
+
7
+ # This cascade does not delete the referenced relations, but instead
8
+ # sets the foreign key values to nil.
9
+ #
10
+ # @example Nullify the reference.
11
+ # strategy.cascade
12
+ def cascade
13
+ relation.nullify
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,26 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+ module Cascading #:nodoc:
5
+ class Strategy
6
+
7
+ attr_accessor :document, :relation, :metadata
8
+
9
+ # Initialize the new cascade strategy, which will set up the relation
10
+ # and the metadata.
11
+ #
12
+ # @example Instantiate the strategy
13
+ # Strategy.new(document, metadata)
14
+ #
15
+ # @param [ Document ] document The document to cascade from.
16
+ # @param [ Metadata ] metadata The relation's metadata.
17
+ #
18
+ # @return [ Strategy ] The new strategy.
19
+ def initialize(document, metadata)
20
+ @document, @metadata = document, metadata
21
+ @relation = document.send(metadata.name)
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,55 @@
1
+ # encoding: utf-8
2
+ require "mongoid/relations/cascading/strategy"
3
+ require "mongoid/relations/cascading/delete"
4
+ require "mongoid/relations/cascading/destroy"
5
+ require "mongoid/relations/cascading/nullify"
6
+
7
+ module Mongoid # :nodoc:
8
+ module Relations #:nodoc:
9
+
10
+ # This module defines the behaviour for setting up cascading deletes and
11
+ # nullifies for relations, and how to delegate to the approriate strategy.
12
+ module Cascading
13
+ extend ActiveSupport::Concern
14
+
15
+ included do
16
+ class_attribute :cascades
17
+ self.cascades = []
18
+ delegate :cascades, :to => "self.class"
19
+ end
20
+
21
+ # Perform all cascading deletes, destroys, or nullifies. Will delegate to
22
+ # the appropriate strategy to perform the operation.
23
+ #
24
+ # @example Execute cascades.
25
+ # document.cascade!
26
+ #
27
+ # @since 2.0.0.rc.1
28
+ def cascade!
29
+ cascades.each do |name|
30
+ metadata = relations[name]
31
+ strategy = metadata.cascade_strategy
32
+ strategy.new(self, metadata).cascade
33
+ end
34
+ end
35
+
36
+ module ClassMethods #:nodoc:
37
+
38
+ # Attempt to add the cascading information for the document to know how
39
+ # to handle associated documents on a removal.
40
+ #
41
+ # @example Set up cascading information
42
+ # Movie.cascade(metadata)
43
+ #
44
+ # @param [ Metadata ] metadata The metadata for the relation.
45
+ #
46
+ # @return [ Class ] The class of the document.
47
+ #
48
+ # @since 2.0.0.rc.1
49
+ def cascade(metadata)
50
+ tap { cascades << metadata.name.to_s if metadata.dependent? }
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end