mongoid 1.2.14 → 1.9.0

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