mongoid 2.0.0.alpha → 2.0.0.beta.5

Sign up to get free protection for your applications and to get access to all the features.
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