mongoid 1.2.14 → 1.9.0

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 (200) hide show
  1. data/lib/mongoid.rb +10 -3
  2. data/lib/mongoid/associations.rb +133 -97
  3. data/lib/mongoid/associations/belongs_to_related.rb +2 -3
  4. data/lib/mongoid/associations/{belongs_to.rb → embedded_in.rb} +14 -6
  5. data/lib/mongoid/associations/{has_many.rb → embeds_many.rb} +89 -31
  6. data/lib/mongoid/associations/{has_one.rb → embeds_one.rb} +8 -7
  7. data/lib/mongoid/associations/has_many_related.rb +52 -7
  8. data/lib/mongoid/associations/has_one_related.rb +8 -4
  9. data/lib/mongoid/associations/meta_data.rb +2 -1
  10. data/lib/mongoid/associations/options.rb +6 -1
  11. data/lib/mongoid/associations/proxy.rb +14 -21
  12. data/lib/mongoid/attributes.rb +27 -12
  13. data/lib/mongoid/collection.rb +4 -3
  14. data/lib/mongoid/collections.rb +41 -0
  15. data/lib/mongoid/collections/master.rb +3 -2
  16. data/lib/mongoid/collections/slaves.rb +3 -2
  17. data/lib/mongoid/components.rb +21 -19
  18. data/lib/mongoid/concern.rb +31 -0
  19. data/lib/mongoid/config.rb +117 -12
  20. data/lib/mongoid/contexts.rb +1 -1
  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/criterion/inclusion.rb +17 -0
  25. data/lib/mongoid/criterion/optional.rb +1 -1
  26. data/lib/mongoid/dirty.rb +253 -0
  27. data/lib/mongoid/document.rb +81 -52
  28. data/lib/mongoid/errors.rb +32 -1
  29. data/lib/mongoid/extensions.rb +11 -9
  30. data/lib/mongoid/extensions/big_decimal/conversions.rb +2 -2
  31. data/lib/mongoid/extensions/boolean/conversions.rb +8 -2
  32. data/lib/mongoid/extensions/date/conversions.rb +13 -4
  33. data/lib/mongoid/extensions/datetime/conversions.rb +1 -6
  34. data/lib/mongoid/extensions/float/conversions.rb +5 -1
  35. data/lib/mongoid/extensions/hash/assimilation.rb +12 -3
  36. data/lib/mongoid/extensions/hash/conversions.rb +34 -4
  37. data/lib/mongoid/extensions/integer/conversions.rb +5 -1
  38. data/lib/mongoid/extensions/nil/assimilation.rb +4 -0
  39. data/lib/mongoid/extensions/object/conversions.rb +1 -1
  40. data/lib/mongoid/extensions/string/conversions.rb +1 -1
  41. data/lib/mongoid/extensions/symbol/inflections.rb +1 -1
  42. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  43. data/lib/mongoid/extras.rb +6 -9
  44. data/lib/mongoid/factory.rb +2 -1
  45. data/lib/mongoid/field.rb +9 -2
  46. data/lib/mongoid/fields.rb +1 -0
  47. data/lib/mongoid/identity.rb +3 -3
  48. data/lib/mongoid/indexes.rb +3 -3
  49. data/lib/mongoid/memoization.rb +8 -2
  50. data/lib/mongoid/named_scope.rb +0 -3
  51. data/lib/mongoid/observable.rb +30 -0
  52. data/lib/mongoid/paths.rb +62 -0
  53. data/lib/mongoid/persistence.rb +222 -0
  54. data/lib/mongoid/persistence/command.rb +39 -0
  55. data/lib/mongoid/persistence/insert.rb +50 -0
  56. data/lib/mongoid/persistence/insert_embedded.rb +38 -0
  57. data/lib/mongoid/persistence/remove.rb +39 -0
  58. data/lib/mongoid/persistence/remove_all.rb +37 -0
  59. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  60. data/lib/mongoid/persistence/update.rb +63 -0
  61. data/lib/mongoid/state.rb +28 -21
  62. data/lib/mongoid/timestamps.rb +5 -8
  63. data/lib/mongoid/version.rb +4 -0
  64. data/lib/mongoid/versioning.rb +6 -7
  65. metadata +81 -300
  66. data/.gitignore +0 -6
  67. data/.watchr +0 -29
  68. data/Rakefile +0 -53
  69. data/VERSION +0 -1
  70. data/caliper.yml +0 -4
  71. data/lib/mongoid/collections/mimic.rb +0 -46
  72. data/lib/mongoid/commands.rb +0 -174
  73. data/lib/mongoid/commands/create.rb +0 -21
  74. data/lib/mongoid/commands/delete.rb +0 -16
  75. data/lib/mongoid/commands/delete_all.rb +0 -23
  76. data/lib/mongoid/commands/deletion.rb +0 -18
  77. data/lib/mongoid/commands/destroy.rb +0 -19
  78. data/lib/mongoid/commands/destroy_all.rb +0 -23
  79. data/lib/mongoid/commands/save.rb +0 -27
  80. data/lib/mongoid/extensions/time/conversions.rb +0 -18
  81. data/mongoid.gemspec +0 -395
  82. data/perf/benchmark.rb +0 -77
  83. data/spec/integration/mongoid/associations_spec.rb +0 -340
  84. data/spec/integration/mongoid/attributes_spec.rb +0 -22
  85. data/spec/integration/mongoid/commands_spec.rb +0 -218
  86. data/spec/integration/mongoid/contexts/enumerable_spec.rb +0 -33
  87. data/spec/integration/mongoid/criteria_spec.rb +0 -272
  88. data/spec/integration/mongoid/document_spec.rb +0 -593
  89. data/spec/integration/mongoid/extensions_spec.rb +0 -26
  90. data/spec/integration/mongoid/finders_spec.rb +0 -119
  91. data/spec/integration/mongoid/inheritance_spec.rb +0 -137
  92. data/spec/integration/mongoid/named_scope_spec.rb +0 -46
  93. data/spec/models/address.rb +0 -39
  94. data/spec/models/animal.rb +0 -6
  95. data/spec/models/callbacks.rb +0 -18
  96. data/spec/models/comment.rb +0 -8
  97. data/spec/models/country_code.rb +0 -6
  98. data/spec/models/employer.rb +0 -5
  99. data/spec/models/game.rb +0 -7
  100. data/spec/models/inheritance.rb +0 -56
  101. data/spec/models/location.rb +0 -5
  102. data/spec/models/mixed_drink.rb +0 -4
  103. data/spec/models/name.rb +0 -13
  104. data/spec/models/namespacing.rb +0 -11
  105. data/spec/models/patient.rb +0 -4
  106. data/spec/models/person.rb +0 -99
  107. data/spec/models/pet.rb +0 -7
  108. data/spec/models/pet_owner.rb +0 -6
  109. data/spec/models/phone.rb +0 -7
  110. data/spec/models/post.rb +0 -15
  111. data/spec/models/translation.rb +0 -5
  112. data/spec/models/vet_visit.rb +0 -5
  113. data/spec/spec.opts +0 -3
  114. data/spec/spec_helper.rb +0 -31
  115. data/spec/unit/mongoid/associations/belongs_to_related_spec.rb +0 -145
  116. data/spec/unit/mongoid/associations/belongs_to_spec.rb +0 -193
  117. data/spec/unit/mongoid/associations/has_many_related_spec.rb +0 -420
  118. data/spec/unit/mongoid/associations/has_many_spec.rb +0 -519
  119. data/spec/unit/mongoid/associations/has_one_related_spec.rb +0 -179
  120. data/spec/unit/mongoid/associations/has_one_spec.rb +0 -282
  121. data/spec/unit/mongoid/associations/meta_data_spec.rb +0 -88
  122. data/spec/unit/mongoid/associations/options_spec.rb +0 -192
  123. data/spec/unit/mongoid/associations_spec.rb +0 -595
  124. data/spec/unit/mongoid/attributes_spec.rb +0 -507
  125. data/spec/unit/mongoid/callbacks_spec.rb +0 -55
  126. data/spec/unit/mongoid/collection_spec.rb +0 -187
  127. data/spec/unit/mongoid/collections/cyclic_iterator_spec.rb +0 -75
  128. data/spec/unit/mongoid/collections/master_spec.rb +0 -41
  129. data/spec/unit/mongoid/collections/mimic_spec.rb +0 -43
  130. data/spec/unit/mongoid/collections/slaves_spec.rb +0 -81
  131. data/spec/unit/mongoid/commands/create_spec.rb +0 -30
  132. data/spec/unit/mongoid/commands/delete_all_spec.rb +0 -58
  133. data/spec/unit/mongoid/commands/delete_spec.rb +0 -38
  134. data/spec/unit/mongoid/commands/destroy_all_spec.rb +0 -23
  135. data/spec/unit/mongoid/commands/destroy_spec.rb +0 -50
  136. data/spec/unit/mongoid/commands/save_spec.rb +0 -105
  137. data/spec/unit/mongoid/commands_spec.rb +0 -275
  138. data/spec/unit/mongoid/config_spec.rb +0 -172
  139. data/spec/unit/mongoid/contexts/enumerable_spec.rb +0 -421
  140. data/spec/unit/mongoid/contexts/mongo_spec.rb +0 -682
  141. data/spec/unit/mongoid/contexts_spec.rb +0 -25
  142. data/spec/unit/mongoid/criteria_spec.rb +0 -824
  143. data/spec/unit/mongoid/criterion/complex_spec.rb +0 -19
  144. data/spec/unit/mongoid/criterion/exclusion_spec.rb +0 -91
  145. data/spec/unit/mongoid/criterion/inclusion_spec.rb +0 -219
  146. data/spec/unit/mongoid/criterion/optional_spec.rb +0 -319
  147. data/spec/unit/mongoid/cursor_spec.rb +0 -74
  148. data/spec/unit/mongoid/deprecation_spec.rb +0 -24
  149. data/spec/unit/mongoid/document_spec.rb +0 -952
  150. data/spec/unit/mongoid/errors_spec.rb +0 -103
  151. data/spec/unit/mongoid/extensions/array/accessors_spec.rb +0 -50
  152. data/spec/unit/mongoid/extensions/array/assimilation_spec.rb +0 -24
  153. data/spec/unit/mongoid/extensions/array/conversions_spec.rb +0 -35
  154. data/spec/unit/mongoid/extensions/array/parentization_spec.rb +0 -20
  155. data/spec/unit/mongoid/extensions/big_decimal/conversions_spec.rb +0 -22
  156. data/spec/unit/mongoid/extensions/binary/conversions_spec.rb +0 -22
  157. data/spec/unit/mongoid/extensions/boolean/conversions_spec.rb +0 -49
  158. data/spec/unit/mongoid/extensions/date/conversions_spec.rb +0 -102
  159. data/spec/unit/mongoid/extensions/datetime/conversions_spec.rb +0 -70
  160. data/spec/unit/mongoid/extensions/float/conversions_spec.rb +0 -61
  161. data/spec/unit/mongoid/extensions/hash/accessors_spec.rb +0 -184
  162. data/spec/unit/mongoid/extensions/hash/assimilation_spec.rb +0 -46
  163. data/spec/unit/mongoid/extensions/hash/conversions_spec.rb +0 -21
  164. data/spec/unit/mongoid/extensions/hash/criteria_helpers_spec.rb +0 -17
  165. data/spec/unit/mongoid/extensions/hash/scoping_spec.rb +0 -14
  166. data/spec/unit/mongoid/extensions/integer/conversions_spec.rb +0 -61
  167. data/spec/unit/mongoid/extensions/nil/assimilation_spec.rb +0 -24
  168. data/spec/unit/mongoid/extensions/object/conversions_spec.rb +0 -57
  169. data/spec/unit/mongoid/extensions/proc/scoping_spec.rb +0 -34
  170. data/spec/unit/mongoid/extensions/string/conversions_spec.rb +0 -17
  171. data/spec/unit/mongoid/extensions/string/inflections_spec.rb +0 -208
  172. data/spec/unit/mongoid/extensions/symbol/inflections_spec.rb +0 -91
  173. data/spec/unit/mongoid/extensions/time/conversions_spec.rb +0 -70
  174. data/spec/unit/mongoid/extras_spec.rb +0 -102
  175. data/spec/unit/mongoid/factory_spec.rb +0 -31
  176. data/spec/unit/mongoid/field_spec.rb +0 -143
  177. data/spec/unit/mongoid/fields_spec.rb +0 -181
  178. data/spec/unit/mongoid/finders_spec.rb +0 -404
  179. data/spec/unit/mongoid/identity_spec.rb +0 -109
  180. data/spec/unit/mongoid/indexes_spec.rb +0 -93
  181. data/spec/unit/mongoid/javascript_spec.rb +0 -48
  182. data/spec/unit/mongoid/matchers/all_spec.rb +0 -27
  183. data/spec/unit/mongoid/matchers/default_spec.rb +0 -27
  184. data/spec/unit/mongoid/matchers/exists_spec.rb +0 -56
  185. data/spec/unit/mongoid/matchers/gt_spec.rb +0 -39
  186. data/spec/unit/mongoid/matchers/gte_spec.rb +0 -49
  187. data/spec/unit/mongoid/matchers/in_spec.rb +0 -27
  188. data/spec/unit/mongoid/matchers/lt_spec.rb +0 -39
  189. data/spec/unit/mongoid/matchers/lte_spec.rb +0 -49
  190. data/spec/unit/mongoid/matchers/ne_spec.rb +0 -27
  191. data/spec/unit/mongoid/matchers/nin_spec.rb +0 -27
  192. data/spec/unit/mongoid/matchers/size_spec.rb +0 -27
  193. data/spec/unit/mongoid/matchers_spec.rb +0 -329
  194. data/spec/unit/mongoid/memoization_spec.rb +0 -75
  195. data/spec/unit/mongoid/named_scope_spec.rb +0 -123
  196. data/spec/unit/mongoid/scope_spec.rb +0 -240
  197. data/spec/unit/mongoid/state_spec.rb +0 -83
  198. data/spec/unit/mongoid/timestamps_spec.rb +0 -25
  199. data/spec/unit/mongoid/versioning_spec.rb +0 -41
  200. 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 HasMany
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,16 +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.changed(true)
27
- document.notify_observers(document, true)
28
- @target.clear
29
- end
30
- end
31
-
32
24
  # Builds a new Document and adds it to the association collection. The
33
25
  # document created will be of the same class as the others in the
34
26
  # association, and the attributes will be passed into the constructor.
@@ -41,9 +33,19 @@ module Mongoid #:nodoc:
41
33
  document.parentize(@parent, @association_name)
42
34
  document.write_attributes(attrs)
43
35
  @target << document
36
+ document._index = @target.size - 1
44
37
  document
45
38
  end
46
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
+
47
49
  # Creates a new Document and adds it to the association collection. The
48
50
  # document created will be of the same class as the others in the
49
51
  # association, and the attributes will be passed into the constructor and
@@ -54,9 +56,7 @@ module Mongoid #:nodoc:
54
56
  # The newly created Document.
55
57
  def create(attrs = {}, type = nil)
56
58
  document = build(attrs, type)
57
- document.run_callbacks(:before_create)
58
- document.run_callbacks(:after_create) if document.save
59
- document
59
+ document.save; document
60
60
  end
61
61
 
62
62
  # Creates a new Document and adds it to the association collection. The
@@ -75,6 +75,32 @@ module Mongoid #:nodoc:
75
75
  document
76
76
  end
77
77
 
78
+ # Delete all the documents in the association without running callbacks.
79
+ #
80
+ # Example:
81
+ #
82
+ # <tt>addresses.delete_all</tt>
83
+ #
84
+ # Returns:
85
+ #
86
+ # The number of documents deleted.
87
+ def delete_all(conditions = {})
88
+ remove(:delete, conditions)
89
+ end
90
+
91
+ # Delete all the documents in the association and run destroy callbacks.
92
+ #
93
+ # Example:
94
+ #
95
+ # <tt>addresses.destroy_all</tt>
96
+ #
97
+ # Returns:
98
+ #
99
+ # The number of documents destroyed.
100
+ def destroy_all(conditions = {})
101
+ remove(:destroy, conditions)
102
+ end
103
+
78
104
  # Finds a document in this association.
79
105
  #
80
106
  # If :all is passed, returns all the documents
@@ -101,13 +127,19 @@ module Mongoid #:nodoc:
101
127
  #
102
128
  # parent: The parent document to the association.
103
129
  # options: The association options.
104
- def initialize(parent, options)
130
+ def initialize(parent, options, target_array = nil)
105
131
  @parent, @association_name = parent, options.name
106
132
  @klass, @options = options.klass, options
107
- initialize_each(parent.raw_attributes[@association_name])
133
+ if target_array
134
+ build_children_from_target_array(target_array)
135
+ else
136
+ build_children_from_attributes(parent.raw_attributes[@association_name])
137
+ end
108
138
  extends(options)
109
139
  end
110
140
 
141
+
142
+
111
143
  # If the target array does not respond to the supplied method then try to
112
144
  # find a named scope or criteria on the class and send the call there.
113
145
  #
@@ -150,45 +182,71 @@ module Mongoid #:nodoc:
150
182
  def paginate(options)
151
183
  criteria = Mongoid::Criteria.translate(@klass, options)
152
184
  criteria.documents = @target
153
- criteria.paginate
185
+ criteria.paginate(options)
154
186
  end
155
187
 
156
188
  protected
157
189
  # Initializes each of the attributes in the hash.
158
- def initialize_each(attributes)
159
- @target = attributes ? attributes.collect do |attrs|
160
- klass = attrs.klass
161
- child = klass ? klass.instantiate(attrs) : @klass.instantiate(attrs)
162
- child.parentize(@parent, @association_name)
163
- child
164
- end : []
190
+ def build_children_from_attributes(attributes)
191
+ @target = []
192
+ if attributes
193
+ attributes.each_with_index do |attrs, index|
194
+ klass = attrs.klass
195
+ child = klass ? klass.instantiate(attrs) : @klass.instantiate(attrs)
196
+ child.parentize(@parent, @association_name)
197
+ child._index = index
198
+ @target << child
199
+ end
200
+ end
201
+ end
202
+
203
+ # Initializes the target array from an existing array of documents.
204
+ def build_children_from_target_array(target_array)
205
+ @target = target_array
206
+ @target.each_with_index do |child, index|
207
+ child._index = index
208
+ end
209
+ end
210
+
211
+ # Removes documents based on a method.
212
+ def remove(method, conditions)
213
+ criteria = @klass.find(conditions || {})
214
+ criteria.documents = @target
215
+ count = criteria.size
216
+ criteria.each do |doc|
217
+ @target.delete(doc); doc.send(method)
218
+ end; count
165
219
  end
166
220
 
167
221
  class << self
168
222
 
169
- # Preferred method of creating a new +HasMany+ association. It will
223
+ # Preferred method of creating a new +EmbedsMany+ association. It will
170
224
  # delegate to new.
171
225
  #
172
226
  # Options:
173
227
  #
174
228
  # document: The parent +Document+
175
229
  # options: The association options
176
- def instantiate(document, options)
177
- new(document, options)
230
+ def instantiate(document, options, target_array = nil)
231
+ new(document, options, target_array)
178
232
  end
179
233
 
180
234
  # Returns the macro used to create the association.
181
235
  def macro
182
- :has_many
236
+ :embeds_many
183
237
  end
184
238
 
185
239
  # Perform an update of the relationship of the parent and child. This
186
240
  # is initialized by setting the has_many to the supplied +Enumerable+
187
241
  # and setting up the parentization.
188
242
  def update(children, parent, options)
189
- parent.remove_attribute(options.name)
243
+ parent.raw_attributes.delete(options.name)
190
244
  children.assimilate(parent, options)
191
- instantiate(parent, options)
245
+ if children && children.first.is_a?(Mongoid::Document)
246
+ instantiate(parent, options, children)
247
+ else
248
+ instantiate(parent, options)
249
+ end
192
250
  end
193
251
  end
194
252
  end
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class HasOne #: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)
@@ -46,7 +47,7 @@ module Mongoid #:nodoc:
46
47
  end
47
48
 
48
49
  class << self
49
- # Preferred method of instantiating a new +HasOne+, 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 +HasOne+ 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
- :has_one
69
+ :embeds_one
69
70
  end
70
71
 
71
72
  # Perform an update of the relationship of the parent and child. This
@@ -79,11 +80,11 @@ module Mongoid #:nodoc:
79
80
  #
80
81
  # Example:
81
82
  #
82
- # <tt>HasOne.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 +HasOne+ 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)
@@ -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.
@@ -41,10 +42,42 @@ module Mongoid #:nodoc:
41
42
  # Returns the newly created object.
42
43
  def create(attributes)
43
44
  object = build(attributes)
44
- object.run_callbacks(:before_create)
45
- object.save
46
- object.run_callbacks(:after_create)
47
- object
45
+ object.save; object
46
+ end
47
+
48
+ # Creates a new Document and adds it to the association collection. If
49
+ # validation fails an error is raised.
50
+ #
51
+ # Returns the newly created object.
52
+ def create!(attributes)
53
+ object = build(attributes)
54
+ object.save!; object
55
+ end
56
+
57
+ # Delete all the associated objects.
58
+ #
59
+ # Example:
60
+ #
61
+ # <tt>person.posts.delete_all</tt>
62
+ #
63
+ # Returns:
64
+ #
65
+ # The number of objects deleted.
66
+ def delete_all(conditions = {})
67
+ remove(:delete_all, conditions[:conditions])
68
+ end
69
+
70
+ # Destroy all the associated objects.
71
+ #
72
+ # Example:
73
+ #
74
+ # <tt>person.posts.destroy_all</tt>
75
+ #
76
+ # Returns:
77
+ #
78
+ # The number of objects destroyed.
79
+ def destroy_all(conditions = {})
80
+ remove(:destroy_all, conditions[:conditions])
48
81
  end
49
82
 
50
83
  # Finds a document in this association.
@@ -62,7 +95,7 @@ module Mongoid #:nodoc:
62
95
  # document: The +Document+ that contains the relationship.
63
96
  # options: The association +Options+.
64
97
  def initialize(document, options, target = nil)
65
- @parent, @klass = document, options.klass
98
+ @parent, @klass, @options = document, options.klass, options
66
99
  @foreign_key = options.foreign_key
67
100
  @base = lambda { @klass.all(:conditions => { @foreign_key => document.id }) }
68
101
  @target = target || @base.call
@@ -96,6 +129,18 @@ module Mongoid #:nodoc:
96
129
  @target = @target.entries if @parent.new_record?
97
130
  end
98
131
 
132
+ # Remove the objects based on conditions.
133
+ def remove(method, conditions)
134
+ selector = { @foreign_key => @parent.id }.merge(conditions || {})
135
+ removed = @klass.send(method, :conditions => selector)
136
+ reset; removed
137
+ end
138
+
139
+ # Reset the memoized association on the parent.
140
+ def reset
141
+ @parent.send(:reset, @options.name) { @base.call }
142
+ end
143
+
99
144
  class << self
100
145
  # Preferred method for creating the new +HasManyRelated+ association.
101
146
  #
@@ -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
@@ -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
@@ -47,6 +48,10 @@ module Mongoid #:nodoc:
47
48
  @attributes[:polymorphic] == true
48
49
  end
49
50
 
51
+ # Used with has_many_related to save as array of ids.
52
+ def stored_as
53
+ @attributes[:stored_as]
54
+ end
50
55
  end
51
56
  end
52
57
  end
@@ -1,30 +1,23 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc
3
3
  module Associations #:nodoc
4
- module Proxy #:nodoc
5
- def self.included(base)
6
- base.class_eval do
7
- instance_methods.each do |method|
8
- undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$)/
9
- end
10
- include InstanceMethods
11
- end
4
+ class Proxy #:nodoc
5
+ instance_methods.each do |method|
6
+ undef_method(method) unless method =~ /(^__|^nil\?$|^send$|^object_id$|^extend$)/
12
7
  end
13
- module InstanceMethods #:nodoc:
14
- attr_reader \
15
- :options,
16
- :target
8
+ attr_reader \
9
+ :options,
10
+ :target
17
11
 
18
- # Default behavior of method missing should be to delegate all calls
19
- # to the target of the proxy. This can be overridden in special cases.
20
- def method_missing(name, *args, &block)
21
- @target.send(name, *args, &block)
22
- end
12
+ # Default behavior of method missing should be to delegate all calls
13
+ # to the target of the proxy. This can be overridden in special cases.
14
+ def method_missing(name, *args, &block)
15
+ @target.send(name, *args, &block)
16
+ end
23
17
 
24
- # If anonymous extensions are added this will take care of them.
25
- def extends(options)
26
- extend Module.new(&options.extension) if options.extension?
27
- end
18
+ # If anonymous extensions are added this will take care of them.
19
+ def extends(options)
20
+ extend Module.new(&options.extension) if options.extension?
28
21
  end
29
22
  end
30
23
  end