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
@@ -21,13 +21,15 @@
21
21
  # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
22
  require "rubygems"
23
23
 
24
- gem "activemodel", ">= 3.0.pre"
25
- gem "will_paginate", ">= 3.0.pre"
26
- gem "mongo", ">= 0.19.1"
24
+ gem "activemodel", "3.0.0.beta3"
25
+ gem "will_paginate", "3.0.pre"
26
+ gem "mongo", "~>1.0.1"
27
+ gem "bson", "~>1.0.1"
27
28
 
28
29
  require "delegate"
29
30
  require "singleton"
30
31
  require "time"
32
+ require "ostruct"
31
33
  require "active_support/core_ext"
32
34
  require 'active_support/json'
33
35
  require "active_support/inflector"
@@ -44,16 +46,18 @@ require "active_model/validator"
44
46
  require "active_model/validations"
45
47
  require "will_paginate/collection"
46
48
  require "mongo"
49
+ require "mongoid/observable"
47
50
  require "mongoid/associations"
48
51
  require "mongoid/attributes"
49
52
  require "mongoid/callbacks"
50
53
  require "mongoid/collection"
51
- require "mongoid/commands"
54
+ require "mongoid/collections"
52
55
  require "mongoid/config"
53
56
  require "mongoid/contexts"
54
57
  require "mongoid/criteria"
55
58
  require "mongoid/cursor"
56
59
  require "mongoid/deprecation"
60
+ require "mongoid/dirty"
57
61
  require "mongoid/extensions"
58
62
  require "mongoid/extras"
59
63
  require "mongoid/errors"
@@ -67,8 +71,8 @@ require "mongoid/javascript"
67
71
  require "mongoid/matchers"
68
72
  require "mongoid/memoization"
69
73
  require "mongoid/named_scope"
70
- require "mongoid/observable"
71
74
  require "mongoid/paths"
75
+ require "mongoid/persistence"
72
76
  require "mongoid/scope"
73
77
  require "mongoid/state"
74
78
  require "mongoid/timestamps"
@@ -79,6 +83,8 @@ require "mongoid/document"
79
83
 
80
84
  module Mongoid #:nodoc
81
85
 
86
+ MONGODB_VERSION = "1.4.0"
87
+
82
88
  class << self
83
89
 
84
90
  # Sets the Mongoid configuration options. Best used by passing a block.
@@ -2,8 +2,8 @@
2
2
  require "mongoid/associations/proxy"
3
3
  require "mongoid/associations/belongs_to_related"
4
4
  require "mongoid/associations/embedded_in"
5
- require "mongoid/associations/embed_many"
6
- require "mongoid/associations/embed_one"
5
+ require "mongoid/associations/embeds_many"
6
+ require "mongoid/associations/embeds_one"
7
7
  require "mongoid/associations/has_many_related"
8
8
  require "mongoid/associations/has_one_related"
9
9
  require "mongoid/associations/options"
@@ -13,9 +13,13 @@ module Mongoid # :nodoc:
13
13
  module Associations #:nodoc:
14
14
  extend ActiveSupport::Concern
15
15
  included do
16
- # Associations need to inherit down the chain.
16
+ cattr_accessor :embedded
17
+ self.embedded = false
18
+
17
19
  class_inheritable_accessor :associations
18
20
  self.associations = {}
21
+
22
+ delegate :embedded, :embedded?, :to => "self.class"
19
23
  end
20
24
 
21
25
  module InstanceMethods
@@ -24,9 +28,15 @@ module Mongoid # :nodoc:
24
28
  self.class.associations
25
29
  end
26
30
 
27
- # Updates all the one-to-many relational associations for the name.
28
- def update_associations(name)
29
- 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?
30
40
  end
31
41
 
32
42
  # Update the one-to-one relational association for the name.
@@ -34,14 +44,46 @@ module Mongoid # :nodoc:
34
44
  association = send(name)
35
45
  association.save if new_record? && !association.nil?
36
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
37
52
  end
38
53
 
39
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
40
75
 
41
- # Deprecated: Document.belongs_to will become Document.embedded_in
42
- def belongs_to(name, options = {}, &block)
43
- Mongoid.deprecate("Document.belongs_to will become Document.embedded_in")
44
- embedded_in(name, options, &block)
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
45
87
  end
46
88
 
47
89
  # Adds the association back to the parent document. This macro is
@@ -57,7 +99,7 @@ module Mongoid # :nodoc:
57
99
  #
58
100
  # class Person
59
101
  # include Mongoid::Document
60
- # embed_many :addresses
102
+ # embeds_many :addresses
61
103
  # end
62
104
  #
63
105
  # class Address
@@ -66,48 +108,40 @@ module Mongoid # :nodoc:
66
108
  # end
67
109
  def embedded_in(name, options = {}, &block)
68
110
  unless options.has_key?(:inverse_of)
69
- 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")
70
112
  end
71
113
  self.embedded = true
72
- add_association(
73
- Associations::EmbeddedIn,
74
- Associations::Options.new(
75
- options.merge(:name => name, :extend => block)
76
- )
77
- )
114
+ associate(Associations::EmbeddedIn, optionize(name, options, nil, &block))
78
115
  end
79
116
 
80
- # Adds a relational association from the child Document to a Document in
81
- # another database or collection.
117
+ # Adds the association from a parent document to its children. The name
118
+ # of the association needs to be a pluralized form of the child class
119
+ # name.
82
120
  #
83
121
  # Options:
84
122
  #
85
- # name: A +Symbol+ that is the related class name.
123
+ # name: A +Symbol+ that is the plural child class name.
86
124
  #
87
125
  # Example:
88
126
  #
89
- # class Game
127
+ # class Person
90
128
  # include Mongoid::Document
91
- # belongs_to_related :person
129
+ # embeds_many :addresses
92
130
  # end
93
131
  #
94
- def belongs_to_related(name, options = {}, &block)
95
- opts = Associations::Options.new(
96
- options.merge(:name => name, :extend => block, :foreign_key => foreign_key(name, options))
97
- )
98
- add_association(Associations::BelongsToRelated, opts)
99
- field(opts.foreign_key, :type => Mongoid.use_object_ids ? Mongo::ObjectID : String)
100
- index(opts.foreign_key) unless self.embedded
132
+ # class Address
133
+ # include Mongoid::Document
134
+ # embedded_in :person, :inverse_of => :addresses
135
+ # end
136
+ def embeds_many(name, options = {}, &block)
137
+ associate(Associations::EmbedsMany, optionize(name, options, nil, &block))
138
+ set_callback(:update, :after) { |document| document.update_embedded(name) } unless name == :versions
101
139
  end
102
140
 
103
- # Deprecated: Document.has_many will become Document.embed_many
104
- def has_many(name, options = {}, &block)
105
- Mongoid.deprecate("Document.has_many will become Document.embed_many")
106
- embed_many(name, options, &block)
107
- end
141
+ alias :embed_many :embeds_many
108
142
 
109
- # Adds the association from a parent document to its children. The name
110
- # of the association needs to be a pluralized form of the child class
143
+ # Adds the association from a parent document to its child. The name
144
+ # of the association needs to be a singular form of the child class
111
145
  # name.
112
146
  #
113
147
  # Options:
@@ -118,22 +152,24 @@ module Mongoid # :nodoc:
118
152
  #
119
153
  # class Person
120
154
  # include Mongoid::Document
121
- # embed_many :addresses
155
+ # embeds_one :name
122
156
  # end
123
157
  #
124
- # class Address
158
+ # class Name
125
159
  # include Mongoid::Document
126
- # embedded_in :person, :inverse_of => :addresses
160
+ # embedded_in :person
127
161
  # end
128
- def embed_many(name, options = {}, &block)
129
- add_association(
130
- Associations::EmbedMany,
131
- Associations::Options.new(
132
- options.merge(:name => name, :extend => block)
133
- )
134
- )
162
+ def embeds_one(name, options = {}, &block)
163
+ opts = optionize(name, options, nil, &block)
164
+ type = Associations::EmbedsOne
165
+ associate(type, opts)
166
+ add_builder(type, opts)
167
+ add_creator(type, opts)
168
+ set_callback(:update, :after) { |document| document.update_embedded(name) }
135
169
  end
136
170
 
171
+ alias :embed_one :embeds_one
172
+
137
173
  # Adds a relational association from the Document to many Documents in
138
174
  # another database or collection.
139
175
  #
@@ -149,51 +185,12 @@ module Mongoid # :nodoc:
149
185
  # end
150
186
  #
151
187
  def has_many_related(name, options = {}, &block)
152
- add_association(Associations::HasManyRelated,
153
- Associations::Options.new(
154
- options.merge(:name => name, :foreign_key => foreign_key(self.name, options), :extend => block)
155
- )
156
- )
157
- before_save do |document|
188
+ associate(Associations::HasManyRelated, optionize(name, options, fk(self.name, options), &block))
189
+ set_callback :save, :before do |document|
158
190
  document.update_associations(name)
159
191
  end
160
192
  end
161
193
 
162
- # Deprecated: Document.has_one will become Document.embed_one
163
- def has_one(name, options = {}, &block)
164
- Mongoid.deprecate("Document.has_one will become Document.embed_one")
165
- embed_one(name, options, &block)
166
- end
167
-
168
- # Adds the association from a parent document to its child. The name
169
- # of the association needs to be a singular form of the child class
170
- # name.
171
- #
172
- # Options:
173
- #
174
- # name: A +Symbol+ that is the plural child class name.
175
- #
176
- # Example:
177
- #
178
- # class Person
179
- # include Mongoid::Document
180
- # embed_one :name
181
- # end
182
- #
183
- # class Name
184
- # include Mongoid::Document
185
- # embedded_in :person
186
- # end
187
- def embed_one(name, options = {}, &block)
188
- opts = Associations::Options.new(
189
- options.merge(:name => name, :extend => block)
190
- )
191
- type = Associations::EmbedOne
192
- add_association(type, opts)
193
- add_builder(type, opts)
194
- add_creator(type, opts)
195
- end
196
-
197
194
  # Adds a relational association from the Document to one Document in
198
195
  # another database or collection.
199
196
  #
@@ -208,19 +205,14 @@ module Mongoid # :nodoc:
208
205
  # has_one_related :game
209
206
  # end
210
207
  def has_one_related(name, options = {}, &block)
211
- add_association(
212
- Associations::HasOneRelated,
213
- Associations::Options.new(
214
- options.merge(:name => name, :foreign_key => foreign_key(name, options), :extend => block)
215
- )
216
- )
217
- before_save do |document|
208
+ associate(Associations::HasOneRelated, optionize(name, options, fk(self.name, options), &block))
209
+ set_callback :save, :before do |document|
218
210
  document.update_association(name)
219
211
  end
220
212
  end
221
213
 
222
214
  # Returns the macro associated with the supplied association name. This
223
- # will return has_one, has_many, belongs_to or nil.
215
+ # will return embeds_on, embeds_many, embedded_in or nil.
224
216
  #
225
217
  # Options:
226
218
  #
@@ -238,14 +230,17 @@ module Mongoid # :nodoc:
238
230
  # Adds the association to the associations hash with the type as the key,
239
231
  # then adds the accessors for the association. The defined setters and
240
232
  # getters for the associations will perform the necessary memoization.
241
- def add_association(type, options)
233
+ #
234
+ # Example:
235
+ #
236
+ # <tt>Person.associate(EmbedsMany, { :name => :addresses })</tt>
237
+ def associate(type, options)
242
238
  name = options.name.to_s
243
239
  associations[name] = MetaData.new(type, options)
244
- define_method(name) do
245
- memoized(name) { type.instantiate(self, options) }
246
- end
240
+ define_method(name) { memoized(name) { type.instantiate(self, options) } }
247
241
  define_method("#{name}=") do |object|
248
- reset(name) { type.update(object, self, options) }
242
+ unmemoize(name)
243
+ memoized(name) { type.update(object, self, options) }
249
244
  end
250
245
  end
251
246
 
@@ -253,8 +248,10 @@ module Mongoid # :nodoc:
253
248
  # build_name(attributes)
254
249
  def add_builder(type, options)
255
250
  name = options.name.to_s
256
- define_method("build_#{name}") do |attrs|
257
- reset(name) { type.new(self, (attrs || {}).stringify_keys, options) }
251
+ define_method("build_#{name}") do |*params|
252
+ attrs = params[0]
253
+ attr_options = params[1] || {}
254
+ reset(name) { type.new(self, (attrs || {}).stringify_keys, options) } unless type == Associations::EmbedsOne && attr_options[:update_only]
258
255
  end
259
256
  end
260
257
 
@@ -262,14 +259,22 @@ module Mongoid # :nodoc:
262
259
  # create_name(attributes)
263
260
  def add_creator(type, options)
264
261
  name = options.name.to_s
265
- define_method("create_#{name}") do |attrs|
266
- document = send("build_#{name}", attrs)
267
- document.run_callbacks(:create) { document.save }; document
262
+ define_method("create_#{name}") do |*params|
263
+ attrs = params[0]
264
+ attr_options = params[1] || {}
265
+ send("build_#{name}", attrs, attr_options).tap(&:save) unless type == Associations::EmbedsOne && attr_options[:update_only]
268
266
  end
269
267
  end
270
268
 
269
+ # build the options given the params.
270
+ def optionize(name, options, foreign_key, &block)
271
+ Associations::Options.new(
272
+ options.merge(:name => name, :foreign_key => foreign_key, :extend => block)
273
+ )
274
+ end
275
+
271
276
  # Find the foreign key.
272
- def foreign_key(name, options)
277
+ def fk(name, options)
273
278
  options[:foreign_key] || name.to_s.foreign_key
274
279
  end
275
280
  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 EmbeddedIn #: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
@@ -48,16 +49,23 @@ module Mongoid #:nodoc:
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 an embed_one or an embed_many.
52
+ # +Document+. Will properly set an embeds_one or an embeds_many.
52
53
  #
53
54
  # Returns:
54
55
  #
55
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