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,306 @@
1
+ # encoding: utf-8
2
+ module Mongoid # :nodoc:
3
+ module Relations #:nodoc:
4
+
5
+ # This module contains the core macros for defining relations between
6
+ # documents. They can be either embedded or referenced (relational).
7
+ module Macros
8
+ extend ActiveSupport::Concern
9
+
10
+ included do
11
+ cattr_accessor :embedded
12
+ class_attribute :relations
13
+ self.embedded = false
14
+ self.relations = {}
15
+
16
+ # For backwards compatibility, alias the class method for associations
17
+ # and embedding as well. Fix in related gems.
18
+ #
19
+ # @todo Affected libraries: Machinist
20
+ class << self
21
+ alias :associations :relations
22
+ alias :embedded? :embedded
23
+ end
24
+
25
+ # Convenience methods for the instance to know about attributes that
26
+ # are located at the class level.
27
+ delegate :associations, :relations, :to => "self.class"
28
+ end
29
+
30
+ module ClassMethods #:nodoc:
31
+
32
+ # Adds the relation back to the parent document. This macro is
33
+ # necessary to set the references from the child back to the parent
34
+ # document. If a child does not define this relation calling
35
+ # persistence methods on the child object will cause a save to fail.
36
+ #
37
+ # @example Define the relation.
38
+ #
39
+ # class Person
40
+ # include Mongoid::Document
41
+ # embeds_many :addresses
42
+ # end
43
+ #
44
+ # class Address
45
+ # include Mongoid::Document
46
+ # embedded_in :person
47
+ # end
48
+ #
49
+ # @param [ Symbol ] name The name of the relation.
50
+ # @param [ Hash ] options The relation options.
51
+ # @param [ Proc ] block Optional block for defining extensions.
52
+ def embedded_in(name, options = {}, &block)
53
+ characterize(name, Embedded::In, options, &block).tap do |meta|
54
+ self.embedded = true
55
+ relate(name, meta)
56
+ end
57
+ end
58
+
59
+ # Adds the relation from a parent document to its children. The name
60
+ # of the relation needs to be a pluralized form of the child class
61
+ # name.
62
+ #
63
+ # @example Define the relation.
64
+ #
65
+ # class Person
66
+ # include Mongoid::Document
67
+ # embeds_many :addresses
68
+ # end
69
+ #
70
+ # class Address
71
+ # include Mongoid::Document
72
+ # embedded_in :person
73
+ # end
74
+ #
75
+ # @param [ Symbol ] name The name of the relation.
76
+ # @param [ Hash ] options The relation options.
77
+ # @param [ Proc ] block Optional block for defining extensions.
78
+ def embeds_many(name, options = {}, &block)
79
+ characterize(name, Embedded::Many, options, &block).tap do |meta|
80
+ relate(name, meta)
81
+ validate_relation(meta)
82
+ end
83
+ end
84
+
85
+ # Adds the relation from a parent document to its child. The name
86
+ # of the relation needs to be a singular form of the child class
87
+ # name.
88
+ #
89
+ # @example Define the relation.
90
+ #
91
+ # class Person
92
+ # include Mongoid::Document
93
+ # embeds_one :name
94
+ # end
95
+ #
96
+ # class Name
97
+ # include Mongoid::Document
98
+ # embedded_in :person
99
+ # end
100
+ #
101
+ # @param [ Symbol ] name The name of the relation.
102
+ # @param [ Hash ] options The relation options.
103
+ # @param [ Proc ] block Optional block for defining extensions.
104
+ def embeds_one(name, options = {}, &block)
105
+ characterize(name, Embedded::One, options, &block).tap do |meta|
106
+ relate(name, meta)
107
+ builder(name).creator(name)
108
+ validate_relation(meta)
109
+ end
110
+ end
111
+
112
+ # Adds a relational association from the child Document to a Document in
113
+ # another database or collection.
114
+ #
115
+ # @example Define the relation.
116
+ #
117
+ # class Game
118
+ # include Mongoid::Document
119
+ # referenced_in :person
120
+ # end
121
+ #
122
+ # class Person
123
+ # include Mongoid::Document
124
+ # references_one :game
125
+ # end
126
+ #
127
+ # @param [ Symbol ] name The name of the relation.
128
+ # @param [ Hash ] options The relation options.
129
+ # @param [ Proc ] block Optional block for defining extensions.
130
+ def referenced_in(name, options = {}, &block)
131
+ characterize(name, Referenced::In, options, &block).tap do |meta|
132
+ relate(name, meta)
133
+ reference(meta)
134
+ end
135
+ end
136
+ alias :belongs_to_related :referenced_in
137
+ alias :belongs_to :referenced_in
138
+
139
+ # Adds a relational association from a parent Document to many
140
+ # Documents in another database or collection.
141
+ #
142
+ # @example Define the relation.
143
+ #
144
+ # class Person
145
+ # include Mongoid::Document
146
+ # references_many :posts
147
+ # end
148
+ #
149
+ # class Game
150
+ # include Mongoid::Document
151
+ # referenced_in :person
152
+ # end
153
+ #
154
+ # @param [ Symbol ] name The name of the relation.
155
+ # @param [ Hash ] options The relation options.
156
+ # @param [ Proc ] block Optional block for defining extensions.
157
+ def references_many(name, options = {}, &block)
158
+ check_options(options)
159
+ characterize(name, Referenced::Many, options, &block).tap do |meta|
160
+ relate(name, meta)
161
+ reference(meta)
162
+ autosave(meta)
163
+ validate_relation(meta)
164
+ end
165
+ end
166
+ alias :has_many_related :references_many
167
+ alias :has_many :references_many
168
+
169
+ # Adds a relational many-to-many association between many of this
170
+ # Document and many of another Document.
171
+ #
172
+ # @example Define the relation.
173
+ #
174
+ # class Person
175
+ # include Mongoid::Document
176
+ # references_and_referenced_in_many :preferences
177
+ # end
178
+ #
179
+ # class Preference
180
+ # include Mongoid::Document
181
+ # references_and_referenced_in_many :people
182
+ # end
183
+ #
184
+ # @param [ Symbol ] name The name of the relation.
185
+ # @param [ Hash ] options The relation options.
186
+ # @param [ Proc ] block Optional block for defining extensions.
187
+ #
188
+ # @since 2.0.0.rc.1
189
+ def references_and_referenced_in_many(name, options = {}, &block)
190
+ characterize(name, Referenced::ManyToMany, options, &block).tap do |meta|
191
+ relate(name, meta)
192
+ reference(meta)
193
+ end
194
+ end
195
+ alias :has_and_belongs_to_many :references_and_referenced_in_many
196
+
197
+ # Adds a relational association from the child Document to a Document in
198
+ # another database or collection.
199
+ #
200
+ # @example Define the relation.
201
+ #
202
+ # class Game
203
+ # include Mongoid::Document
204
+ # referenced_in :person
205
+ # end
206
+ #
207
+ # class Person
208
+ # include Mongoid::Document
209
+ # references_one :game
210
+ # end
211
+ #
212
+ # @param [ Symbol ] name The name of the relation.
213
+ # @param [ Hash ] options The relation options.
214
+ # @param [ Proc ] block Optional block for defining extensions.
215
+ def references_one(name, options = {}, &block)
216
+ characterize(name, Referenced::One, options, &block).tap do |meta|
217
+ relate(name, meta)
218
+ reference(meta)
219
+ builder(name).creator(name).autosave(meta)
220
+ validate_relation(meta)
221
+ end
222
+ end
223
+ alias :has_one_related :references_one
224
+ alias :has_one :references_one
225
+
226
+ private
227
+
228
+ # Temporary check while people switch over to the new macro. Will be
229
+ # deleted in 2.0.0.
230
+ #
231
+ # @example Check the options.
232
+ # Person.check_options({})
233
+ #
234
+ # @param [ Hash ] options The options given to the relational many.
235
+ #
236
+ # @raise [ RuntimeError ] If :stored_as => :array is found.
237
+ #
238
+ # @since 2.0.0.rc.1
239
+ def check_options(options = {})
240
+ if options[:stored_as] == :array
241
+ raise RuntimeError.new(
242
+ "Macro: references_many :name, :stored_as => :array " <<
243
+ "Is no longer valid. Please use: references_and_referenced_in_many :name"
244
+ )
245
+ end
246
+ end
247
+
248
+ # Create the metadata for the relation.
249
+ #
250
+ # @example Create the metadata.
251
+ # Person.characterize(:posts, Referenced::Many, {})
252
+ #
253
+ # @param [ Symbol ] name The name of the relation.
254
+ # @param [ Object ] relation The type of relation.
255
+ # @param [ Hash ] options The relation options.
256
+ # @param [ Proc ] block Optional block for defining extensions.
257
+ #
258
+ # @return [ Metadata ] The metadata for the relation.
259
+ def characterize(name, relation, options, &block)
260
+ Metadata.new(
261
+ options.merge(
262
+ :relation => relation,
263
+ :extend => block,
264
+ :inverse_class_name => self.name,
265
+ :name => name
266
+ )
267
+ )
268
+ end
269
+
270
+ # Defines a field to be used as a foreign key in the relation and
271
+ # indexes it if defined.
272
+ #
273
+ # @example Set up the relational fields and indexes.
274
+ # Person.reference(metadata)
275
+ #
276
+ # @param [ Metadata ] metadata The metadata for the relation.
277
+ def reference(metadata)
278
+ polymorph(metadata).cascade(metadata)
279
+ if metadata.relation.stores_foreign_key?
280
+ key = metadata.foreign_key
281
+ field(
282
+ key,
283
+ :identity => true,
284
+ :metadata => metadata,
285
+ :default => metadata.foreign_key_default
286
+ )
287
+ index(key, :background => true) if metadata.indexed?
288
+ end
289
+ end
290
+
291
+ # Creates a relation for the given name, metadata and relation. It adds
292
+ # the metadata to the relations hash and has the accessors set up.
293
+ #
294
+ # @example Set up the relation and accessors.
295
+ # Person.relate(:addresses, Metadata)
296
+ #
297
+ # @param [ Symbol ] name The name of the relation.
298
+ # @param [ Metadata ] metadata The metadata for the relation.
299
+ def relate(name, metadata)
300
+ relations[name.to_s] = metadata
301
+ getter(name, metadata).setter(name, metadata)
302
+ end
303
+ end
304
+ end
305
+ end
306
+ end
@@ -0,0 +1,171 @@
1
+ # encoding: utf-8
2
+ module Mongoid #:nodoc:
3
+ module Relations #:nodoc:
4
+
5
+ # This is the superclass for all many to one and many to many relation
6
+ # proxies.
7
+ class Many < Proxy
8
+
9
+ # Appends a document or array of documents to the relation. Will set
10
+ # the parent and update the index in the process.
11
+ #
12
+ # @example Append a document.
13
+ # person.addresses << address
14
+ #
15
+ # @example Push a document.
16
+ # person.addresses.push(address)
17
+ #
18
+ # @example Concat with other documents.
19
+ # perosn.addresses.concat([ address_one, address_two ])
20
+ #
21
+ # @param [ Document, Array<Document> ] *args Any number of documents.
22
+ def <<(*args)
23
+ options = default_options(args)
24
+ args.flatten.each do |doc|
25
+ append(doc, options)
26
+ doc.save if base.persisted? && !options[:binding]
27
+ end
28
+ end
29
+ alias :concat :<<
30
+ alias :push :<<
31
+
32
+ # Builds a new document in the relation and appends it to the target.
33
+ # Takes an optional type if you want to specify a subclass.
34
+ #
35
+ # @example Build a new document on the relation.
36
+ # person.people.build(:name => "Bozo")
37
+ #
38
+ # @param [ Hash ] attributes The attributes to build the document with.
39
+ # @param [ Class ] type Optional class to build the document with.
40
+ #
41
+ # @return [ Document ] The new document.
42
+ def build(attributes = {}, type = nil)
43
+ instantiated(type).tap do |doc|
44
+ append(doc, default_options(:binding => true))
45
+ doc.write_attributes(attributes)
46
+ doc.identify
47
+ end
48
+ end
49
+ alias :new :build
50
+
51
+ # Creates a new document on the references many relation. This will
52
+ # save the document if the parent has been persisted.
53
+ #
54
+ # @example Create and save the new document.
55
+ # person.posts.create(:text => "Testing")
56
+ #
57
+ # @param [ Hash ] attributes The attributes to create with.
58
+ # @param [ Class ] type The optional type of document to create.
59
+ #
60
+ # @return [ Document ] The newly created document.
61
+ def create(attributes = nil, type = nil)
62
+ build(attributes, type).tap do |doc|
63
+ doc.save if base.persisted?
64
+ end
65
+ end
66
+
67
+ # Creates a new document on the references many relation. This will
68
+ # save the document if the parent has been persisted and will raise an
69
+ # error if validation fails.
70
+ #
71
+ # @example Create and save the new document.
72
+ # person.posts.create!(:text => "Testing")
73
+ #
74
+ # @param [ Hash ] attributes The attributes to create with.
75
+ # @param [ Class ] type The optional type of document to create.
76
+ #
77
+ # @raise [ Errors::Validations ] If validation failed.
78
+ #
79
+ # @return [ Document ] The newly created document.
80
+ def create!(attributes = nil, type = nil)
81
+ build(attributes, type).tap do |doc|
82
+ doc.save! if base.persisted?
83
+ end
84
+ end
85
+
86
+ # Determine if any documents in this relation exist in the database.
87
+ #
88
+ # @example Are there persisted documents?
89
+ # person.posts.exists?
90
+ #
91
+ # @return [ true, false ] True is persisted documents exist, false if not.
92
+ def exists?
93
+ count > 0
94
+ end
95
+
96
+ # Find the first document given the conditions, or creates a new document
97
+ # with the conditions that were supplied.
98
+ #
99
+ # @example Find or create.
100
+ # person.posts.find_or_create_by(:title => "Testing")
101
+ #
102
+ # @param [ Hash ] attrs The attributes to search or create with.
103
+ #
104
+ # @return [ Document ] An existing document or newly created one.
105
+ def find_or_create_by(attrs = {})
106
+ find_or(:create, attrs)
107
+ end
108
+
109
+ # Find the first +Document+ given the conditions, or instantiates a new document
110
+ # with the conditions that were supplied
111
+ #
112
+ # @example Find or initialize.
113
+ # person.posts.find_or_initialize_by(:title => "Test")
114
+ #
115
+ # @param [ Hash ] attrs The attributes to search or initialize with.
116
+ #
117
+ # @return [ Document ] An existing document or newly instantiated one.
118
+ def find_or_initialize_by(attrs = {})
119
+ find_or(:build, attrs)
120
+ end
121
+
122
+ # Gets the document as a serializable hash, used by ActiveModel's JSON and
123
+ # XML serializers. This override is just to be able to pass the :include
124
+ # and :except options to get associations in the hash.
125
+ #
126
+ # @example Get the serializable hash.
127
+ # relation.serializable_hash
128
+ #
129
+ # @param [ Hash ] options The options to pass.
130
+ #
131
+ # @option options [ Symbol ] :include What relations to include
132
+ # @option options [ Symbol ] :only Limit the fields to only these.
133
+ # @option options [ Symbol ] :except Dont include these fields.
134
+ #
135
+ # @return [ Hash ] The documents, ready to be serialized.
136
+ #
137
+ # @since 2.0.0.rc.6
138
+ def serializable_hash(options = {})
139
+ target.map { |document| document.serializable_hash(options) }
140
+ end
141
+
142
+ private
143
+
144
+ # Get the default options used in binding functions.
145
+ #
146
+ # @example Get the default options.
147
+ # relation.default_options(:continue => true)
148
+ #
149
+ # @param [ Hash, Array ] args The arguments to parse from.
150
+ #
151
+ # @return [ Hash ] The options merged with the actuals.
152
+ def default_options(args = {})
153
+ options = args.is_a?(Hash) ? args : args.extract_options!
154
+ Mongoid.binding_defaults.merge(options)
155
+ end
156
+
157
+ # Find the first object given the supplied attributes or create/initialize it.
158
+ #
159
+ # @example Find or create|initialize.
160
+ # person.addresses.find_or(:create, :street => "Bond")
161
+ #
162
+ # @param [ Symbol ] method The method name, create or new.
163
+ # @param [ Hash ] attrs The attributes to build with.
164
+ #
165
+ # @return [ Document ] A matching document or a new/created one.
166
+ def find_or(method, attrs = {})
167
+ find(:first, :conditions => attrs) || send(method, attrs)
168
+ end
169
+ end
170
+ end
171
+ end