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
@@ -22,12 +22,12 @@
22
22
  require "rubygems"
23
23
 
24
24
  gem "activesupport", ">= 2.2.2", "<3.0.pre"
25
- gem "mongo", ">= 0.19.1"
25
+ gem "mongo", "~>1.0"
26
+ gem "bson", "~>1.0"
26
27
  gem "durran-validatable", ">= 2.0.1"
27
28
  gem "will_paginate", ">= 2.3.11", "< 2.9"
28
29
 
29
30
  require "delegate"
30
- require "observer"
31
31
  require "singleton"
32
32
  require "time"
33
33
  require "validatable"
@@ -37,16 +37,19 @@ require "active_support/inflector"
37
37
  require "active_support/time_with_zone"
38
38
  require "will_paginate/collection"
39
39
  require "mongo"
40
+ require "mongoid/concern"
41
+ require "mongoid/observable"
40
42
  require "mongoid/associations"
41
43
  require "mongoid/attributes"
42
44
  require "mongoid/callbacks"
43
45
  require "mongoid/collection"
44
- require "mongoid/commands"
46
+ require "mongoid/collections"
45
47
  require "mongoid/config"
46
48
  require "mongoid/contexts"
47
49
  require "mongoid/criteria"
48
50
  require "mongoid/cursor"
49
51
  require "mongoid/deprecation"
52
+ require "mongoid/dirty"
50
53
  require "mongoid/extensions"
51
54
  require "mongoid/extras"
52
55
  require "mongoid/errors"
@@ -60,6 +63,8 @@ require "mongoid/javascript"
60
63
  require "mongoid/matchers"
61
64
  require "mongoid/memoization"
62
65
  require "mongoid/named_scope"
66
+ require "mongoid/paths"
67
+ require "mongoid/persistence"
63
68
  require "mongoid/scope"
64
69
  require "mongoid/state"
65
70
  require "mongoid/timestamps"
@@ -69,6 +74,8 @@ require "mongoid/document"
69
74
 
70
75
  module Mongoid #:nodoc
71
76
 
77
+ MONGODB_VERSION = "1.4.0"
78
+
72
79
  class << self
73
80
 
74
81
  # Sets the Mongoid configuration options. Best used by passing a block.
@@ -1,25 +1,25 @@
1
1
  # encoding: utf-8
2
2
  require "mongoid/associations/proxy"
3
- require "mongoid/associations/belongs_to"
4
3
  require "mongoid/associations/belongs_to_related"
5
- require "mongoid/associations/has_many"
4
+ require "mongoid/associations/embedded_in"
5
+ require "mongoid/associations/embeds_many"
6
+ require "mongoid/associations/embeds_one"
6
7
  require "mongoid/associations/has_many_related"
7
- require "mongoid/associations/has_one"
8
8
  require "mongoid/associations/has_one_related"
9
9
  require "mongoid/associations/options"
10
10
  require "mongoid/associations/meta_data"
11
11
 
12
12
  module Mongoid # :nodoc:
13
13
  module Associations #:nodoc:
14
- def self.included(base)
15
- base.class_eval do
16
- # Associations need to inherit down the chain.
17
- class_inheritable_accessor :associations
18
- self.associations = {}
14
+ extend ActiveSupport::Concern
15
+ included do
16
+ cattr_accessor :embedded
17
+ self.embedded = false
19
18
 
20
- include InstanceMethods
21
- extend ClassMethods
22
- end
19
+ class_inheritable_accessor :associations
20
+ self.associations = {}
21
+
22
+ delegate :embedded, :embedded?, :to => "self.class"
23
23
  end
24
24
 
25
25
  module InstanceMethods
@@ -28,9 +28,15 @@ module Mongoid # :nodoc:
28
28
  self.class.associations
29
29
  end
30
30
 
31
- # Updates all the one-to-many relational associations for the name.
32
- def update_associations(name)
33
- send(name).each { |doc| doc.save } if new_record?
31
+ # are we in an embeds_many?
32
+ def embedded_many?
33
+ embedded? and _parent.associations[association_name].association == EmbedsMany
34
+ end
35
+
36
+ # Update all the dirty child documents after an update.
37
+ def update_embedded(name)
38
+ association = send(name)
39
+ association.to_a.each { |doc| doc.save if doc.changed? || doc.new_record? } unless association.blank?
34
40
  end
35
41
 
36
42
  # Update the one-to-one relational association for the name.
@@ -38,9 +44,48 @@ module Mongoid # :nodoc:
38
44
  association = send(name)
39
45
  association.save if new_record? && !association.nil?
40
46
  end
47
+
48
+ # Updates all the one-to-many relational associations for the name.
49
+ def update_associations(name)
50
+ send(name).each { |doc| doc.save } if new_record?
51
+ end
41
52
  end
42
53
 
43
54
  module ClassMethods
55
+ # Adds a relational association from the child Document to a Document in
56
+ # another database or collection.
57
+ #
58
+ # Options:
59
+ #
60
+ # name: A +Symbol+ that is the related class name.
61
+ #
62
+ # Example:
63
+ #
64
+ # class Game
65
+ # include Mongoid::Document
66
+ # belongs_to_related :person
67
+ # end
68
+ #
69
+ def belongs_to_related(name, options = {}, &block)
70
+ opts = optionize(name, options, fk(name, options), &block)
71
+ associate(Associations::BelongsToRelated, opts)
72
+ field(opts.foreign_key, :type => Mongoid.use_object_ids ? BSON::ObjectID : String)
73
+ index(opts.foreign_key) unless embedded?
74
+ end
75
+
76
+ # Gets whether or not the document is embedded.
77
+ #
78
+ # Example:
79
+ #
80
+ # <tt>Person.embedded?</tt>
81
+ #
82
+ # Returns:
83
+ #
84
+ # <tt>true</tt> if embedded, <tt>false</tt> if not.
85
+ def embedded?
86
+ !!self.embedded
87
+ end
88
+
44
89
  # Adds the association back to the parent document. This macro is
45
90
  # necessary to set the references from the child back to the parent
46
91
  # document. If a child does not define this association calling
@@ -54,51 +99,56 @@ module Mongoid # :nodoc:
54
99
  #
55
100
  # class Person
56
101
  # include Mongoid::Document
57
- # has_many :addresses
102
+ # embeds_many :addresses
58
103
  # end
59
104
  #
60
105
  # class Address
61
106
  # include Mongoid::Document
62
- # belongs_to :person, :inverse_of => :addresses
107
+ # embedded_in :person, :inverse_of => :addresses
63
108
  # end
64
- def belongs_to(name, options = {}, &block)
109
+ def embedded_in(name, options = {}, &block)
65
110
  unless options.has_key?(:inverse_of)
66
- raise Errors::InvalidOptions.new("Options for belongs_to association must include :inverse_of")
111
+ raise Errors::InvalidOptions.new("Options for embedded_in association must include :inverse_of")
67
112
  end
68
113
  self.embedded = true
69
- add_association(
70
- Associations::BelongsTo,
71
- Associations::Options.new(
72
- options.merge(:name => name, :extend => block)
73
- )
74
- )
114
+ associate(Associations::EmbeddedIn, optionize(name, options, nil, &block))
75
115
  end
76
116
 
77
- # Adds a relational association from the child Document to a Document in
78
- # another database or collection.
117
+ alias :belongs_to :embedded_in
118
+
119
+ # Adds the association from a parent document to its children. The name
120
+ # of the association needs to be a pluralized form of the child class
121
+ # name.
79
122
  #
80
123
  # Options:
81
124
  #
82
- # name: A +Symbol+ that is the related class name.
125
+ # name: A +Symbol+ that is the plural child class name.
83
126
  #
84
127
  # Example:
85
128
  #
86
- # class Game
129
+ # class Person
87
130
  # include Mongoid::Document
88
- # belongs_to_related :person
131
+ # embeds_many :addresses
89
132
  # end
90
133
  #
91
- def belongs_to_related(name, options = {}, &block)
92
- opts = Associations::Options.new(
93
- options.merge(:name => name, :extend => block, :foreign_key => foreign_key(name, options))
94
- )
95
- add_association(Associations::BelongsToRelated, opts)
96
- field(opts.foreign_key, :type => Mongoid.use_object_ids ? Mongo::ObjectID : String)
97
- index(opts.foreign_key) unless self.embedded
134
+ # class Address
135
+ # include Mongoid::Document
136
+ # embedded_in :person, :inverse_of => :addresses
137
+ # end
138
+ def embeds_many(name, options = {}, &block)
139
+ associate(Associations::EmbedsMany, optionize(name, options, nil, &block))
140
+ unless name == :versions
141
+ after_update do |document|
142
+ document.update_embedded(name)
143
+ end
144
+ end
98
145
  end
99
146
 
100
- # Adds the association from a parent document to its children. The name
101
- # of the association needs to be a pluralized form of the child class
147
+ alias :embed_many :embeds_many
148
+ alias :has_many :embeds_many
149
+
150
+ # Adds the association from a parent document to its child. The name
151
+ # of the association needs to be a singular form of the child class
102
152
  # name.
103
153
  #
104
154
  # Options:
@@ -109,22 +159,27 @@ module Mongoid # :nodoc:
109
159
  #
110
160
  # class Person
111
161
  # include Mongoid::Document
112
- # has_many :addresses
162
+ # embeds_one :name
113
163
  # end
114
164
  #
115
- # class Address
165
+ # class Name
116
166
  # include Mongoid::Document
117
- # belongs_to :person, :inverse_of => :addresses
167
+ # embedded_in :person
118
168
  # end
119
- def has_many(name, options = {}, &block)
120
- add_association(
121
- Associations::HasMany,
122
- Associations::Options.new(
123
- options.merge(:name => name, :extend => block)
124
- )
125
- )
169
+ def embeds_one(name, options = {}, &block)
170
+ opts = optionize(name, options, nil, &block)
171
+ type = Associations::EmbedsOne
172
+ associate(type, opts)
173
+ add_builder(type, opts)
174
+ add_creator(type, opts)
175
+ after_update do |document|
176
+ document.update_embedded(name)
177
+ end
126
178
  end
127
179
 
180
+ alias :embed_one :embeds_one
181
+ alias :has_one :embeds_one
182
+
128
183
  # Adds a relational association from the Document to many Documents in
129
184
  # another database or collection.
130
185
  #
@@ -140,45 +195,12 @@ module Mongoid # :nodoc:
140
195
  # end
141
196
  #
142
197
  def has_many_related(name, options = {}, &block)
143
- add_association(Associations::HasManyRelated,
144
- Associations::Options.new(
145
- options.merge(:name => name, :foreign_key => foreign_key(self.name, options), :extend => block)
146
- )
147
- )
198
+ associate(Associations::HasManyRelated, optionize(name, options, fk(self.name, options), &block))
148
199
  before_save do |document|
149
200
  document.update_associations(name)
150
201
  end
151
202
  end
152
203
 
153
- # Adds the association from a parent document to its child. The name
154
- # of the association needs to be a singular form of the child class
155
- # name.
156
- #
157
- # Options:
158
- #
159
- # name: A +Symbol+ that is the plural child class name.
160
- #
161
- # Example:
162
- #
163
- # class Person
164
- # include Mongoid::Document
165
- # has_many :addresses
166
- # end
167
- #
168
- # class Address
169
- # include Mongoid::Document
170
- # belongs_to :person
171
- # end
172
- def has_one(name, options = {}, &block)
173
- opts = Associations::Options.new(
174
- options.merge(:name => name, :extend => block)
175
- )
176
- type = Associations::HasOne
177
- add_association(type, opts)
178
- add_builder(type, opts)
179
- add_creator(type, opts)
180
- end
181
-
182
204
  # Adds a relational association from the Document to one Document in
183
205
  # another database or collection.
184
206
  #
@@ -193,12 +215,7 @@ module Mongoid # :nodoc:
193
215
  # has_one_related :game
194
216
  # end
195
217
  def has_one_related(name, options = {}, &block)
196
- add_association(
197
- Associations::HasOneRelated,
198
- Associations::Options.new(
199
- options.merge(:name => name, :foreign_key => foreign_key(name, options), :extend => block)
200
- )
201
- )
218
+ associate(Associations::HasOneRelated, optionize(name, options, fk(self.name, options), &block))
202
219
  before_save do |document|
203
220
  document.update_association(name)
204
221
  end
@@ -223,14 +240,17 @@ module Mongoid # :nodoc:
223
240
  # Adds the association to the associations hash with the type as the key,
224
241
  # then adds the accessors for the association. The defined setters and
225
242
  # getters for the associations will perform the necessary memoization.
226
- def add_association(type, options)
243
+ #
244
+ # Example:
245
+ #
246
+ # <tt>Person.associate(EmbedsMany, { :name => :addresses })</tt>
247
+ def associate(type, options)
227
248
  name = options.name.to_s
228
249
  associations[name] = MetaData.new(type, options)
229
- define_method(name) do
230
- memoized(name) { type.instantiate(self, options) }
231
- end
250
+ define_method(name) { memoized(name) { type.instantiate(self, options) } }
232
251
  define_method("#{name}=") do |object|
233
- reset(name) { type.update(object, self, options) }
252
+ unmemoize(name)
253
+ memoized(name) { type.update(object, self, options) }
234
254
  end
235
255
  end
236
256
 
@@ -249,16 +269,32 @@ module Mongoid # :nodoc:
249
269
  name = options.name.to_s
250
270
  define_method("create_#{name}") do |attrs|
251
271
  document = send("build_#{name}", attrs)
252
- document.run_callbacks(:before_create)
253
- document.save
254
- document.run_callbacks(:after_create); document
272
+ document.save; document
255
273
  end
256
274
  end
257
275
 
276
+ # build the options given the params.
277
+ def optionize(name, options, foreign_key, &block)
278
+ Associations::Options.new(
279
+ options.merge(:name => name, :foreign_key => foreign_key, :extend => block)
280
+ )
281
+ end
282
+
258
283
  # Find the foreign key.
259
- def foreign_key(name, options)
284
+ def fk(name, options)
260
285
  options[:foreign_key] || name.to_s.foreign_key
261
286
  end
287
+
288
+ # Build the association options.
289
+ def build_options(name, options, &block)
290
+ Associations::Options.new(
291
+ options.merge(
292
+ :name => name,
293
+ :foreign_key => foreign_key(name, options),
294
+ :extend => block
295
+ )
296
+ )
297
+ end
262
298
  end
263
299
  end
264
300
  end
@@ -1,8 +1,8 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class BelongsToRelated #:nodoc:
5
- include Proxy
4
+ # Represents a relational association to a "parent" object.
5
+ class BelongsToRelated < Proxy
6
6
 
7
7
  # Initializing a related association only requires looking up the object
8
8
  # by its id.
@@ -53,7 +53,6 @@ module Mongoid #:nodoc:
53
53
  instantiate(document, options, target)
54
54
  end
55
55
  end
56
-
57
56
  end
58
57
  end
59
58
  end
@@ -1,8 +1,9 @@
1
1
  # encoding: utf-8
2
2
  module Mongoid #:nodoc:
3
3
  module Associations #:nodoc:
4
- class BelongsTo #:nodoc:
5
- include Proxy
4
+ # Represents an association that is embedded within another document in the
5
+ # database, either as one or many.
6
+ class EmbeddedIn < Proxy
6
7
 
7
8
  # Creates the new association by setting the internal
8
9
  # target as the passed in Document. This should be the
@@ -43,21 +44,28 @@ module Mongoid #:nodoc:
43
44
 
44
45
  # Returns the macro used to create the association.
45
46
  def macro
46
- :belongs_to
47
+ :embedded_in
47
48
  end
48
49
 
49
50
  # Perform an update of the relationship of the parent and child. This
50
51
  # is initialized by setting a parent object as the association on the
51
- # +Document+. Will properly set a has_one or a has_many.
52
+ # +Document+. Will properly set an embeds_one or an embeds_many.
52
53
  #
53
54
  # Returns:
54
55
  #
55
- # A new +BelongsTo+ association proxy.
56
+ # A new +EmbeddedIn+ association proxy.
56
57
  def update(target, child, options)
57
- child.parentize(target, options.inverse_of)
58
+ child.parentize(target, determine_name(target, options))
58
59
  child.notify
59
60
  instantiate(child, options)
60
61
  end
62
+
63
+ protected
64
+ def determine_name(target, options)
65
+ inverse = options.inverse_of
66
+ return inverse unless inverse.is_a?(Array)
67
+ inverse.detect { |name| target.respond_to?(name) }
68
+ end
61
69
  end
62
70
  end
63
71
  end