mongoid 2.0.0.alpha → 2.0.0.beta.5

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 (216) hide show
  1. data/lib/mongoid.rb +11 -5
  2. data/lib/mongoid/associations.rb +112 -107
  3. data/lib/mongoid/associations/belongs_to_related.rb +2 -3
  4. data/lib/mongoid/associations/embedded_in.rb +12 -4
  5. data/lib/mongoid/associations/{embed_many.rb → embeds_many.rb} +101 -32
  6. data/lib/mongoid/associations/{embed_one.rb → embeds_one.rb} +10 -10
  7. data/lib/mongoid/associations/has_many_related.rb +51 -5
  8. data/lib/mongoid/associations/has_one_related.rb +9 -5
  9. data/lib/mongoid/associations/meta_data.rb +2 -1
  10. data/lib/mongoid/associations/options.rb +15 -6
  11. data/lib/mongoid/associations/proxy.rb +14 -21
  12. data/lib/mongoid/attributes.rb +34 -13
  13. data/lib/mongoid/callbacks.rb +1 -2
  14. data/lib/mongoid/collection.rb +4 -3
  15. data/lib/mongoid/collections.rb +41 -0
  16. data/lib/mongoid/collections/master.rb +3 -2
  17. data/lib/mongoid/collections/slaves.rb +3 -2
  18. data/lib/mongoid/components.rb +4 -1
  19. data/lib/mongoid/config.rb +163 -13
  20. data/lib/mongoid/contexts.rb +1 -2
  21. data/lib/mongoid/contexts/enumerable.rb +1 -1
  22. data/lib/mongoid/contexts/mongo.rb +1 -1
  23. data/lib/mongoid/contexts/paging.rb +10 -2
  24. data/lib/mongoid/criteria.rb +13 -22
  25. data/lib/mongoid/criterion/exclusion.rb +3 -3
  26. data/lib/mongoid/criterion/inclusion.rb +17 -0
  27. data/lib/mongoid/criterion/optional.rb +1 -1
  28. data/lib/mongoid/dirty.rb +253 -0
  29. data/lib/mongoid/document.rb +40 -85
  30. data/lib/mongoid/errors.rb +48 -1
  31. data/lib/mongoid/extensions.rb +11 -9
  32. data/lib/mongoid/extensions/big_decimal/conversions.rb +2 -2
  33. data/lib/mongoid/extensions/boolean/conversions.rb +8 -2
  34. data/lib/mongoid/extensions/date/conversions.rb +13 -4
  35. data/lib/mongoid/extensions/datetime/conversions.rb +1 -6
  36. data/lib/mongoid/extensions/float/conversions.rb +5 -1
  37. data/lib/mongoid/extensions/hash/assimilation.rb +12 -3
  38. data/lib/mongoid/extensions/hash/conversions.rb +34 -4
  39. data/lib/mongoid/extensions/integer/conversions.rb +5 -1
  40. data/lib/mongoid/extensions/nil/assimilation.rb +4 -0
  41. data/lib/mongoid/extensions/object/conversions.rb +3 -3
  42. data/lib/mongoid/extensions/string/conversions.rb +1 -1
  43. data/lib/mongoid/extensions/symbol/inflections.rb +5 -2
  44. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  45. data/lib/mongoid/factory.rb +2 -1
  46. data/lib/mongoid/field.rb +15 -2
  47. data/lib/mongoid/fields.rb +1 -1
  48. data/lib/mongoid/identity.rb +3 -3
  49. data/lib/mongoid/indexes.rb +3 -3
  50. data/lib/mongoid/matchers.rb +1 -2
  51. data/lib/mongoid/memoization.rb +8 -2
  52. data/lib/mongoid/named_scope.rb +0 -5
  53. data/lib/mongoid/observable.rb +1 -1
  54. data/lib/mongoid/paths.rb +30 -22
  55. data/lib/mongoid/persistence.rb +218 -0
  56. data/lib/mongoid/persistence/command.rb +39 -0
  57. data/lib/mongoid/persistence/insert.rb +47 -0
  58. data/lib/mongoid/persistence/insert_embedded.rb +38 -0
  59. data/lib/mongoid/persistence/remove.rb +39 -0
  60. data/lib/mongoid/persistence/remove_all.rb +37 -0
  61. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  62. data/lib/mongoid/persistence/update.rb +63 -0
  63. data/lib/mongoid/railtie.rb +53 -0
  64. data/lib/mongoid/railties/database.rake +37 -0
  65. data/lib/mongoid/timestamps.rb +2 -2
  66. data/lib/mongoid/validations.rb +2 -2
  67. data/lib/mongoid/validations/associated.rb +2 -2
  68. data/lib/mongoid/validations/uniqueness.rb +13 -2
  69. data/lib/mongoid/version.rb +4 -0
  70. data/lib/mongoid/versioning.rb +3 -2
  71. data/lib/rails/generators/mongoid/config/config_generator.rb +41 -0
  72. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
  73. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  74. data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
  75. data/lib/rails/generators/mongoid_generator.rb +61 -0
  76. metadata +76 -301
  77. data/.gitignore +0 -6
  78. data/.watchr +0 -29
  79. data/Rakefile +0 -52
  80. data/VERSION +0 -1
  81. data/caliper.yml +0 -4
  82. data/lib/mongoid/collections/mimic.rb +0 -46
  83. data/lib/mongoid/commands.rb +0 -161
  84. data/lib/mongoid/commands/create.rb +0 -19
  85. data/lib/mongoid/commands/delete.rb +0 -16
  86. data/lib/mongoid/commands/delete_all.rb +0 -23
  87. data/lib/mongoid/commands/deletion.rb +0 -18
  88. data/lib/mongoid/commands/destroy.rb +0 -17
  89. data/lib/mongoid/commands/destroy_all.rb +0 -23
  90. data/lib/mongoid/commands/save.rb +0 -29
  91. data/lib/mongoid/extensions/time/conversions.rb +0 -18
  92. data/mongoid.gemspec +0 -408
  93. data/perf/benchmark.rb +0 -77
  94. data/spec/integration/mongoid/associations_spec.rb +0 -340
  95. data/spec/integration/mongoid/attributes_spec.rb +0 -22
  96. data/spec/integration/mongoid/commands_spec.rb +0 -227
  97. data/spec/integration/mongoid/contexts/enumerable_spec.rb +0 -33
  98. data/spec/integration/mongoid/criteria_spec.rb +0 -272
  99. data/spec/integration/mongoid/document_spec.rb +0 -650
  100. data/spec/integration/mongoid/extensions_spec.rb +0 -22
  101. data/spec/integration/mongoid/finders_spec.rb +0 -119
  102. data/spec/integration/mongoid/inheritance_spec.rb +0 -137
  103. data/spec/integration/mongoid/named_scope_spec.rb +0 -46
  104. data/spec/models/address.rb +0 -39
  105. data/spec/models/animal.rb +0 -6
  106. data/spec/models/callbacks.rb +0 -18
  107. data/spec/models/comment.rb +0 -8
  108. data/spec/models/country_code.rb +0 -6
  109. data/spec/models/employer.rb +0 -5
  110. data/spec/models/game.rb +0 -7
  111. data/spec/models/inheritance.rb +0 -56
  112. data/spec/models/location.rb +0 -5
  113. data/spec/models/mixed_drink.rb +0 -4
  114. data/spec/models/name.rb +0 -13
  115. data/spec/models/namespacing.rb +0 -11
  116. data/spec/models/patient.rb +0 -4
  117. data/spec/models/person.rb +0 -99
  118. data/spec/models/pet.rb +0 -7
  119. data/spec/models/pet_owner.rb +0 -6
  120. data/spec/models/phone.rb +0 -7
  121. data/spec/models/post.rb +0 -15
  122. data/spec/models/translation.rb +0 -5
  123. data/spec/models/vet_visit.rb +0 -5
  124. data/spec/spec.opts +0 -3
  125. data/spec/spec_helper.rb +0 -31
  126. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +0 -145
  127. data/spec/unit/mongoid/associations/embed_many_spec.rb +0 -516
  128. data/spec/unit/mongoid/associations/embed_one_spec.rb +0 -282
  129. data/spec/unit/mongoid/associations/embedded_in_spec.rb +0 -193
  130. data/spec/unit/mongoid/associations/has_many_related_spec.rb +0 -418
  131. data/spec/unit/mongoid/associations/has_one_related_spec.rb +0 -179
  132. data/spec/unit/mongoid/associations/meta_data_spec.rb +0 -88
  133. data/spec/unit/mongoid/associations/options_spec.rb +0 -192
  134. data/spec/unit/mongoid/associations_spec.rb +0 -595
  135. data/spec/unit/mongoid/attributes_spec.rb +0 -507
  136. data/spec/unit/mongoid/callbacks_spec.rb +0 -55
  137. data/spec/unit/mongoid/collection_spec.rb +0 -187
  138. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +0 -75
  139. data/spec/unit/mongoid/collections/master_spec.rb +0 -41
  140. data/spec/unit/mongoid/collections/mimic_spec.rb +0 -43
  141. data/spec/unit/mongoid/collections/slaves_spec.rb +0 -81
  142. data/spec/unit/mongoid/commands/create_spec.rb +0 -31
  143. data/spec/unit/mongoid/commands/delete_all_spec.rb +0 -58
  144. data/spec/unit/mongoid/commands/delete_spec.rb +0 -38
  145. data/spec/unit/mongoid/commands/destroy_all_spec.rb +0 -21
  146. data/spec/unit/mongoid/commands/destroy_spec.rb +0 -51
  147. data/spec/unit/mongoid/commands/save_spec.rb +0 -107
  148. data/spec/unit/mongoid/commands_spec.rb +0 -270
  149. data/spec/unit/mongoid/config_spec.rb +0 -172
  150. data/spec/unit/mongoid/contexts/enumerable_spec.rb +0 -421
  151. data/spec/unit/mongoid/contexts/mongo_spec.rb +0 -682
  152. data/spec/unit/mongoid/contexts_spec.rb +0 -25
  153. data/spec/unit/mongoid/criteria_spec.rb +0 -824
  154. data/spec/unit/mongoid/criterion/complex_spec.rb +0 -19
  155. data/spec/unit/mongoid/criterion/exclusion_spec.rb +0 -91
  156. data/spec/unit/mongoid/criterion/inclusion_spec.rb +0 -219
  157. data/spec/unit/mongoid/criterion/optional_spec.rb +0 -319
  158. data/spec/unit/mongoid/cursor_spec.rb +0 -74
  159. data/spec/unit/mongoid/deprecation_spec.rb +0 -24
  160. data/spec/unit/mongoid/document_spec.rb +0 -818
  161. data/spec/unit/mongoid/errors_spec.rb +0 -103
  162. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +0 -50
  163. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +0 -24
  164. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +0 -35
  165. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +0 -20
  166. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +0 -22
  167. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +0 -22
  168. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +0 -49
  169. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +0 -102
  170. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +0 -67
  171. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +0 -61
  172. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +0 -184
  173. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +0 -46
  174. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +0 -21
  175. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +0 -17
  176. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +0 -14
  177. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +0 -61
  178. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +0 -24
  179. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +0 -57
  180. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +0 -34
  181. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +0 -17
  182. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +0 -208
  183. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +0 -91
  184. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +0 -70
  185. data/spec/unit/mongoid/extras_spec.rb +0 -102
  186. data/spec/unit/mongoid/factory_spec.rb +0 -31
  187. data/spec/unit/mongoid/field_spec.rb +0 -143
  188. data/spec/unit/mongoid/fields_spec.rb +0 -181
  189. data/spec/unit/mongoid/finders_spec.rb +0 -404
  190. data/spec/unit/mongoid/identity_spec.rb +0 -109
  191. data/spec/unit/mongoid/indexes_spec.rb +0 -93
  192. data/spec/unit/mongoid/javascript_spec.rb +0 -48
  193. data/spec/unit/mongoid/matchers/all_spec.rb +0 -27
  194. data/spec/unit/mongoid/matchers/default_spec.rb +0 -27
  195. data/spec/unit/mongoid/matchers/exists_spec.rb +0 -56
  196. data/spec/unit/mongoid/matchers/gt_spec.rb +0 -39
  197. data/spec/unit/mongoid/matchers/gte_spec.rb +0 -49
  198. data/spec/unit/mongoid/matchers/in_spec.rb +0 -27
  199. data/spec/unit/mongoid/matchers/lt_spec.rb +0 -39
  200. data/spec/unit/mongoid/matchers/lte_spec.rb +0 -49
  201. data/spec/unit/mongoid/matchers/ne_spec.rb +0 -27
  202. data/spec/unit/mongoid/matchers/nin_spec.rb +0 -27
  203. data/spec/unit/mongoid/matchers/size_spec.rb +0 -27
  204. data/spec/unit/mongoid/matchers_spec.rb +0 -329
  205. data/spec/unit/mongoid/memoization_spec.rb +0 -75
  206. data/spec/unit/mongoid/named_scope_spec.rb +0 -123
  207. data/spec/unit/mongoid/observable_spec.rb +0 -46
  208. data/spec/unit/mongoid/paths_spec.rb +0 -124
  209. data/spec/unit/mongoid/scope_spec.rb +0 -240
  210. data/spec/unit/mongoid/state_spec.rb +0 -83
  211. data/spec/unit/mongoid/timestamps_spec.rb +0 -25
  212. data/spec/unit/mongoid/validations/associated_spec.rb +0 -103
  213. data/spec/unit/mongoid/validations/uniqueness_spec.rb +0 -47
  214. data/spec/unit/mongoid/validations_spec.rb +0 -190
  215. data/spec/unit/mongoid/versioning_spec.rb +0 -41
  216. data/spec/unit/mongoid_spec.rb +0 -46
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class EmbedMany
5
- include Proxy
4
+ # Represents embedding many documents within a parent document, which will
5
+ # be an array as the underlying storage mechanism.
6
+ class EmbedsMany < Proxy
6
7
 
7
8
  attr_accessor :association_name, :klass
8
9
 
@@ -12,6 +13,7 @@ module Mongoid #:nodoc:
12
13
  documents.flatten.each do |doc|
13
14
  doc.parentize(@parent, @association_name)
14
15
  @target << doc
16
+ doc._index = @target.size - 1
15
17
  doc.notify
16
18
  end
17
19
  end
@@ -19,15 +21,6 @@ module Mongoid #:nodoc:
19
21
  alias :concat :<<
20
22
  alias :push :<<
21
23
 
22
- # Clears the association, and notifies the parents of the removal.
23
- def clear
24
- unless @target.empty?
25
- document = @target.first
26
- document.notify_observers(document, true)
27
- @target.clear
28
- end
29
- end
30
-
31
24
  # Builds a new Document and adds it to the association collection. The
32
25
  # document created will be of the same class as the others in the
33
26
  # association, and the attributes will be passed into the constructor.
@@ -40,9 +33,19 @@ module Mongoid #:nodoc:
40
33
  document.parentize(@parent, @association_name)
41
34
  document.write_attributes(attrs)
42
35
  @target << document
36
+ document._index = @target.size - 1
43
37
  document
44
38
  end
45
39
 
40
+ # Clears the association, and notifies the parents of the removal.
41
+ def clear
42
+ unless @target.empty?
43
+ document = @target.first
44
+ document.notify_observers(document, true)
45
+ @target.clear
46
+ end
47
+ end
48
+
46
49
  # Creates a new Document and adds it to the association collection. The
47
50
  # document created will be of the same class as the others in the
48
51
  # association, and the attributes will be passed into the constructor and
@@ -52,8 +55,7 @@ module Mongoid #:nodoc:
52
55
  #
53
56
  # The newly created Document.
54
57
  def create(attrs = {}, type = nil)
55
- object = build(attrs, type)
56
- object.run_callbacks(:create) { object.save }; object
58
+ build(attrs, type).tap(&:save)
57
59
  end
58
60
 
59
61
  # Creates a new Document and adds it to the association collection. The
@@ -72,6 +74,32 @@ module Mongoid #:nodoc:
72
74
  document
73
75
  end
74
76
 
77
+ # Delete all the documents in the association without running callbacks.
78
+ #
79
+ # Example:
80
+ #
81
+ # <tt>addresses.delete_all</tt>
82
+ #
83
+ # Returns:
84
+ #
85
+ # The number of documents deleted.
86
+ def delete_all(conditions = {})
87
+ remove(:delete, conditions)
88
+ end
89
+
90
+ # Delete all the documents in the association and run destroy callbacks.
91
+ #
92
+ # Example:
93
+ #
94
+ # <tt>addresses.destroy_all</tt>
95
+ #
96
+ # Returns:
97
+ #
98
+ # The number of documents destroyed.
99
+ def destroy_all(conditions = {})
100
+ remove(:destroy, conditions)
101
+ end
102
+
75
103
  # Finds a document in this association.
76
104
  #
77
105
  # If :all is passed, returns all the documents
@@ -98,13 +126,19 @@ module Mongoid #:nodoc:
98
126
  #
99
127
  # parent: The parent document to the association.
100
128
  # options: The association options.
101
- def initialize(parent, options)
129
+ def initialize(parent, options, target_array = nil)
102
130
  @parent, @association_name = parent, options.name
103
131
  @klass, @options = options.klass, options
104
- initialize_each(parent.raw_attributes[@association_name])
132
+ if target_array
133
+ build_children_from_target_array(target_array)
134
+ else
135
+ build_children_from_attributes(parent.raw_attributes[@association_name])
136
+ end
105
137
  extends(options)
106
138
  end
107
139
 
140
+
141
+
108
142
  # If the target array does not respond to the supplied method then try to
109
143
  # find a named scope or criteria on the class and send the call there.
110
144
  #
@@ -128,9 +162,18 @@ module Mongoid #:nodoc:
128
162
  # Returns:
129
163
  #
130
164
  # The newly build target Document.
131
- def nested_build(attributes)
132
- attributes.values.each do |attrs|
133
- build(attrs)
165
+ def nested_build(attributes, options = {})
166
+ attributes.each do |index, attrs|
167
+ if document = detect { |document| document._index == index.to_i }
168
+ if options && options[:allow_destroy] && attrs['_destroy']
169
+ @target.delete(document)
170
+ document.destroy
171
+ else
172
+ document.write_attributes(attrs)
173
+ end
174
+ else
175
+ build(attrs)
176
+ end
134
177
  end
135
178
  end
136
179
 
@@ -147,45 +190,71 @@ module Mongoid #:nodoc:
147
190
  def paginate(options)
148
191
  criteria = Mongoid::Criteria.translate(@klass, options)
149
192
  criteria.documents = @target
150
- criteria.paginate
193
+ criteria.paginate(options)
151
194
  end
152
195
 
153
196
  protected
154
197
  # Initializes each of the attributes in the hash.
155
- def initialize_each(attributes)
156
- @target = attributes ? attributes.collect do |attrs|
157
- klass = attrs.klass
158
- child = klass ? klass.instantiate(attrs) : @klass.instantiate(attrs)
159
- child.parentize(@parent, @association_name)
160
- child
161
- end : []
198
+ def build_children_from_attributes(attributes)
199
+ @target = []
200
+ if attributes
201
+ attributes.each_with_index do |attrs, index|
202
+ klass = attrs.klass
203
+ child = klass ? klass.instantiate(attrs) : @klass.instantiate(attrs)
204
+ child.parentize(@parent, @association_name)
205
+ child._index = index
206
+ @target << child
207
+ end
208
+ end
209
+ end
210
+
211
+ # Initializes the target array from an existing array of documents.
212
+ def build_children_from_target_array(target_array)
213
+ @target = target_array
214
+ @target.each_with_index do |child, index|
215
+ child._index = index
216
+ end
217
+ end
218
+
219
+ # Removes documents based on a method.
220
+ def remove(method, conditions)
221
+ criteria = @klass.find(conditions || {})
222
+ criteria.documents = @target
223
+ count = criteria.size
224
+ criteria.each do |doc|
225
+ @target.delete(doc); doc.send(method)
226
+ end; count
162
227
  end
163
228
 
164
229
  class << self
165
230
 
166
- # Preferred method of creating a new +EmbedMany+ association. It will
231
+ # Preferred method of creating a new +EmbedsMany+ association. It will
167
232
  # delegate to new.
168
233
  #
169
234
  # Options:
170
235
  #
171
236
  # document: The parent +Document+
172
237
  # options: The association options
173
- def instantiate(document, options)
174
- new(document, options)
238
+ def instantiate(document, options, target_array = nil)
239
+ new(document, options, target_array)
175
240
  end
176
241
 
177
242
  # Returns the macro used to create the association.
178
243
  def macro
179
- :embed_many
244
+ :embeds_many
180
245
  end
181
246
 
182
247
  # Perform an update of the relationship of the parent and child. This
183
248
  # is initialized by setting the has_many to the supplied +Enumerable+
184
249
  # and setting up the parentization.
185
250
  def update(children, parent, options)
186
- parent.remove_attribute(options.name)
251
+ parent.raw_attributes.delete(options.name)
187
252
  children.assimilate(parent, options)
188
- instantiate(parent, options)
253
+ if children && children.first.is_a?(Mongoid::Document)
254
+ instantiate(parent, options, children)
255
+ else
256
+ instantiate(parent, options)
257
+ end
189
258
  end
190
259
  end
191
260
  end
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class EmbedOne #:nodoc:
5
- include Proxy
4
+ # Represents an association that is embedded in a parent document as a
5
+ # one-to-one relationship.
6
+ class EmbedsOne < Proxy
6
7
 
7
8
  # Build a new object for the association.
8
9
  def build(attrs = {}, type = nil)
@@ -41,12 +42,12 @@ module Mongoid #:nodoc:
41
42
  # Returns:
42
43
  #
43
44
  # A new target document.
44
- def nested_build(attributes)
45
- build(attributes)
45
+ def nested_build(attributes, options = nil)
46
+ build(attributes) unless @target.blank? && options[:update_only]
46
47
  end
47
48
 
48
49
  class << self
49
- # Preferred method of instantiating a new +EmbedOne+, since nil values
50
+ # Preferred method of instantiating a new +EmbedsOne+, since nil values
50
51
  # will be handled properly.
51
52
  #
52
53
  # Options:
@@ -56,7 +57,7 @@ module Mongoid #:nodoc:
56
57
  #
57
58
  # Returns:
58
59
  #
59
- # A new +EmbedOne+ association proxy.
60
+ # A new +EmbedsOne+ association proxy.
60
61
  def instantiate(document, options)
61
62
  attributes = document.raw_attributes[options.name]
62
63
  return nil if attributes.blank?
@@ -65,7 +66,7 @@ module Mongoid #:nodoc:
65
66
 
66
67
  # Returns the macro used to create the association.
67
68
  def macro
68
- :embed_one
69
+ :embeds_one
69
70
  end
70
71
 
71
72
  # Perform an update of the relationship of the parent and child. This
@@ -79,17 +80,16 @@ module Mongoid #:nodoc:
79
80
  #
80
81
  # Example:
81
82
  #
82
- # <tt>EmbedOne.update({:first_name => "Hank"}, person, options)</tt>
83
+ # <tt>EmbedsOne.update({:first_name => "Hank"}, person, options)</tt>
83
84
  #
84
85
  # Returns:
85
86
  #
86
- # A new +EmbedOne+ association proxy.
87
+ # A new +EmbedsOne+ association proxy.
87
88
  def update(child, parent, options)
88
89
  child.assimilate(parent, options)
89
90
  instantiate(parent, options)
90
91
  end
91
92
  end
92
-
93
93
  end
94
94
  end
95
95
  end
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class HasManyRelated #:nodoc:
5
- include Proxy
4
+ # Represents an relational one-to-many association with an object in a
5
+ # separate collection or database.
6
+ class HasManyRelated < Proxy
6
7
 
7
8
  # Appends the object to the +Array+, setting its parent in
8
9
  # the process.
@@ -40,8 +41,41 @@ module Mongoid #:nodoc:
40
41
  #
41
42
  # Returns the newly created object.
42
43
  def create(attributes)
43
- object = build(attributes)
44
- object.run_callbacks(:create) { object.save }; object
44
+ build(attributes).tap(&:save)
45
+ end
46
+
47
+ # Creates a new Document and adds it to the association collection. If
48
+ # validation fails an error is raised.
49
+ #
50
+ # Returns the newly created object.
51
+ def create!(attributes)
52
+ build(attributes).tap(&:save!)
53
+ end
54
+
55
+ # Delete all the associated objects.
56
+ #
57
+ # Example:
58
+ #
59
+ # <tt>person.posts.delete_all</tt>
60
+ #
61
+ # Returns:
62
+ #
63
+ # The number of objects deleted.
64
+ def delete_all(conditions = {})
65
+ remove(:delete_all, conditions[:conditions])
66
+ end
67
+
68
+ # Destroy all the associated objects.
69
+ #
70
+ # Example:
71
+ #
72
+ # <tt>person.posts.destroy_all</tt>
73
+ #
74
+ # Returns:
75
+ #
76
+ # The number of objects destroyed.
77
+ def destroy_all(conditions = {})
78
+ remove(:destroy_all, conditions[:conditions])
45
79
  end
46
80
 
47
81
  # Finds a document in this association.
@@ -59,7 +93,7 @@ module Mongoid #:nodoc:
59
93
  # document: The +Document+ that contains the relationship.
60
94
  # options: The association +Options+.
61
95
  def initialize(document, options, target = nil)
62
- @parent, @klass = document, options.klass
96
+ @parent, @klass, @options = document, options.klass, options
63
97
  @foreign_key = options.foreign_key
64
98
  @base = lambda { @klass.all(:conditions => { @foreign_key => document.id }) }
65
99
  @target = target || @base.call
@@ -93,6 +127,18 @@ module Mongoid #:nodoc:
93
127
  @target = @target.entries if @parent.new_record?
94
128
  end
95
129
 
130
+ # Remove the objects based on conditions.
131
+ def remove(method, conditions)
132
+ selector = { @foreign_key => @parent.id }.merge(conditions || {})
133
+ removed = @klass.send(method, :conditions => selector)
134
+ reset; removed
135
+ end
136
+
137
+ # Reset the memoized association on the parent.
138
+ def reset
139
+ @parent.send(:reset, @options.name) { @base.call }
140
+ end
141
+
96
142
  class << self
97
143
  # Preferred method for creating the new +HasManyRelated+ association.
98
144
  #
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class HasOneRelated #:nodoc:
5
- include Proxy
4
+ # Represents an relational one-to-one association with an object in a
5
+ # separate collection or database.
6
+ class HasOneRelated < Proxy
6
7
 
7
8
  delegate :nil?, :to => :target
8
9
 
@@ -11,7 +12,10 @@ module Mongoid #:nodoc:
11
12
  # Returns the newly created object.
12
13
  def build(attributes = {})
13
14
  @target = @klass.instantiate(attributes)
14
- name = @parent.class.to_s.underscore
15
+ inverse = @target.associations.values.detect do |metadata|
16
+ metadata.options.klass == @parent.class
17
+ end
18
+ name = inverse.name
15
19
  @target.send("#{name}=", @parent)
16
20
  @target
17
21
  end
@@ -21,7 +25,7 @@ module Mongoid #:nodoc:
21
25
  #
22
26
  # Returns the newly created object.
23
27
  def create(attributes)
24
- build(attributes); @target.save; @target
28
+ build(attributes).tap(&:save)
25
29
  end
26
30
 
27
31
  # Initializing a related association only requires looking up the objects
@@ -33,7 +37,7 @@ module Mongoid #:nodoc:
33
37
  # options: The association +Options+.
34
38
  def initialize(document, options, target = nil)
35
39
  @parent, @klass = document, options.klass
36
- @foreign_key = document.class.to_s.foreign_key
40
+ @foreign_key = options.foreign_key
37
41
  @target = target || @klass.first(:conditions => { @foreign_key => @parent.id })
38
42
  extends(options)
39
43
  end
@@ -1,7 +1,8 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class MetaData #:nodoc:
4
+ # This class contains metadata about association proxies.
5
+ class MetaData
5
6
 
6
7
  attr_reader :association, :options
7
8
 
@@ -21,7 +21,8 @@ module Mongoid #:nodoc:
21
21
 
22
22
  # Return the foreign key based off the association name.
23
23
  def foreign_key
24
- @attributes[:foreign_key] || klass.name.to_s.foreign_key
24
+ key = @attributes[:foreign_key] || klass.name.to_s.foreign_key
25
+ key.to_s
25
26
  end
26
27
 
27
28
  # Returns the name of the inverse_of association
@@ -29,12 +30,16 @@ module Mongoid #:nodoc:
29
30
  @attributes[:inverse_of]
30
31
  end
31
32
 
32
- # Return a +Class+ for the options. If a class_name was provided, then the
33
- # constantized class_name will be returned. If not, a constant based on the
34
- # association name will be returned.
33
+ # Return a +Class+ for the options. See #class_name
35
34
  def klass
36
- class_name = @attributes[:class_name]
37
- class_name ? class_name.constantize : name.to_s.classify.constantize
35
+ class_name.constantize
36
+ end
37
+
38
+ # Return a +String+ representing the associated class_name. If a class_name
39
+ # was provided, then the constantized class_name will be returned. If not,
40
+ # a constant based on the association name will be returned.
41
+ def class_name
42
+ @attributes[:class_name] || name.to_s.classify
38
43
  end
39
44
 
40
45
  # Returns the association name of the options.
@@ -47,6 +52,10 @@ module Mongoid #:nodoc:
47
52
  @attributes[:polymorphic] == true
48
53
  end
49
54
 
55
+ # Used with has_many_related to save as array of ids.
56
+ def stored_as
57
+ @attributes[:stored_as]
58
+ end
50
59
  end
51
60
  end
52
61
  end