chhean-mongoid 2.0.1.beta1

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 (117) hide show
  1. data/MIT_LICENSE +20 -0
  2. data/README.rdoc +49 -0
  3. data/lib/mongoid.rb +139 -0
  4. data/lib/mongoid/associations.rb +327 -0
  5. data/lib/mongoid/associations/embedded_in.rb +72 -0
  6. data/lib/mongoid/associations/embeds_many.rb +262 -0
  7. data/lib/mongoid/associations/embeds_one.rb +95 -0
  8. data/lib/mongoid/associations/foreign_key.rb +35 -0
  9. data/lib/mongoid/associations/meta_data.rb +29 -0
  10. data/lib/mongoid/associations/options.rb +73 -0
  11. data/lib/mongoid/associations/proxy.rb +33 -0
  12. data/lib/mongoid/associations/referenced_in.rb +71 -0
  13. data/lib/mongoid/associations/references_many.rb +243 -0
  14. data/lib/mongoid/associations/references_many_as_array.rb +78 -0
  15. data/lib/mongoid/associations/references_one.rb +116 -0
  16. data/lib/mongoid/attributes.rb +226 -0
  17. data/lib/mongoid/callbacks.rb +17 -0
  18. data/lib/mongoid/collection.rb +120 -0
  19. data/lib/mongoid/collections.rb +41 -0
  20. data/lib/mongoid/collections/cyclic_iterator.rb +34 -0
  21. data/lib/mongoid/collections/master.rb +29 -0
  22. data/lib/mongoid/collections/operations.rb +41 -0
  23. data/lib/mongoid/collections/slaves.rb +45 -0
  24. data/lib/mongoid/components.rb +32 -0
  25. data/lib/mongoid/config.rb +237 -0
  26. data/lib/mongoid/contexts.rb +24 -0
  27. data/lib/mongoid/contexts/enumerable.rb +151 -0
  28. data/lib/mongoid/contexts/ids.rb +25 -0
  29. data/lib/mongoid/contexts/mongo.rb +285 -0
  30. data/lib/mongoid/contexts/paging.rb +50 -0
  31. data/lib/mongoid/criteria.rb +230 -0
  32. data/lib/mongoid/criterion/complex.rb +21 -0
  33. data/lib/mongoid/criterion/exclusion.rb +65 -0
  34. data/lib/mongoid/criterion/inclusion.rb +110 -0
  35. data/lib/mongoid/criterion/optional.rb +136 -0
  36. data/lib/mongoid/cursor.rb +82 -0
  37. data/lib/mongoid/deprecation.rb +22 -0
  38. data/lib/mongoid/dirty.rb +254 -0
  39. data/lib/mongoid/document.rb +264 -0
  40. data/lib/mongoid/errors.rb +124 -0
  41. data/lib/mongoid/extensions.rb +106 -0
  42. data/lib/mongoid/extensions/array/accessors.rb +17 -0
  43. data/lib/mongoid/extensions/array/aliasing.rb +4 -0
  44. data/lib/mongoid/extensions/array/assimilation.rb +26 -0
  45. data/lib/mongoid/extensions/array/conversions.rb +27 -0
  46. data/lib/mongoid/extensions/array/parentization.rb +13 -0
  47. data/lib/mongoid/extensions/big_decimal/conversions.rb +19 -0
  48. data/lib/mongoid/extensions/binary/conversions.rb +17 -0
  49. data/lib/mongoid/extensions/boolean/conversions.rb +22 -0
  50. data/lib/mongoid/extensions/date/conversions.rb +24 -0
  51. data/lib/mongoid/extensions/datetime/conversions.rb +12 -0
  52. data/lib/mongoid/extensions/float/conversions.rb +20 -0
  53. data/lib/mongoid/extensions/hash/accessors.rb +38 -0
  54. data/lib/mongoid/extensions/hash/assimilation.rb +39 -0
  55. data/lib/mongoid/extensions/hash/conversions.rb +45 -0
  56. data/lib/mongoid/extensions/hash/criteria_helpers.rb +20 -0
  57. data/lib/mongoid/extensions/hash/scoping.rb +12 -0
  58. data/lib/mongoid/extensions/integer/conversions.rb +20 -0
  59. data/lib/mongoid/extensions/nil/assimilation.rb +17 -0
  60. data/lib/mongoid/extensions/object/conversions.rb +27 -0
  61. data/lib/mongoid/extensions/objectid/conversions.rb +15 -0
  62. data/lib/mongoid/extensions/proc/scoping.rb +12 -0
  63. data/lib/mongoid/extensions/set/conversions.rb +20 -0
  64. data/lib/mongoid/extensions/string/conversions.rb +15 -0
  65. data/lib/mongoid/extensions/string/inflections.rb +97 -0
  66. data/lib/mongoid/extensions/symbol/inflections.rb +39 -0
  67. data/lib/mongoid/extensions/time_conversions.rb +35 -0
  68. data/lib/mongoid/extras.rb +61 -0
  69. data/lib/mongoid/factory.rb +20 -0
  70. data/lib/mongoid/field.rb +80 -0
  71. data/lib/mongoid/fields.rb +61 -0
  72. data/lib/mongoid/finders.rb +144 -0
  73. data/lib/mongoid/identity.rb +39 -0
  74. data/lib/mongoid/indexes.rb +27 -0
  75. data/lib/mongoid/javascript.rb +21 -0
  76. data/lib/mongoid/javascript/functions.yml +37 -0
  77. data/lib/mongoid/matchers.rb +35 -0
  78. data/lib/mongoid/matchers/all.rb +11 -0
  79. data/lib/mongoid/matchers/default.rb +26 -0
  80. data/lib/mongoid/matchers/exists.rb +13 -0
  81. data/lib/mongoid/matchers/gt.rb +11 -0
  82. data/lib/mongoid/matchers/gte.rb +11 -0
  83. data/lib/mongoid/matchers/in.rb +11 -0
  84. data/lib/mongoid/matchers/lt.rb +11 -0
  85. data/lib/mongoid/matchers/lte.rb +11 -0
  86. data/lib/mongoid/matchers/ne.rb +11 -0
  87. data/lib/mongoid/matchers/nin.rb +11 -0
  88. data/lib/mongoid/matchers/size.rb +11 -0
  89. data/lib/mongoid/memoization.rb +33 -0
  90. data/lib/mongoid/named_scope.rb +37 -0
  91. data/lib/mongoid/observable.rb +30 -0
  92. data/lib/mongoid/paths.rb +62 -0
  93. data/lib/mongoid/persistence.rb +218 -0
  94. data/lib/mongoid/persistence/command.rb +39 -0
  95. data/lib/mongoid/persistence/insert.rb +47 -0
  96. data/lib/mongoid/persistence/insert_embedded.rb +38 -0
  97. data/lib/mongoid/persistence/remove.rb +39 -0
  98. data/lib/mongoid/persistence/remove_all.rb +37 -0
  99. data/lib/mongoid/persistence/remove_embedded.rb +50 -0
  100. data/lib/mongoid/persistence/update.rb +63 -0
  101. data/lib/mongoid/railtie.rb +54 -0
  102. data/lib/mongoid/railties/database.rake +37 -0
  103. data/lib/mongoid/scope.rb +75 -0
  104. data/lib/mongoid/state.rb +32 -0
  105. data/lib/mongoid/timestamps.rb +27 -0
  106. data/lib/mongoid/validations.rb +51 -0
  107. data/lib/mongoid/validations/associated.rb +32 -0
  108. data/lib/mongoid/validations/locale/en.yml +4 -0
  109. data/lib/mongoid/validations/uniqueness.rb +50 -0
  110. data/lib/mongoid/version.rb +4 -0
  111. data/lib/mongoid/versioning.rb +27 -0
  112. data/lib/rails/generators/mongoid/config/config_generator.rb +41 -0
  113. data/lib/rails/generators/mongoid/config/templates/mongoid.yml +24 -0
  114. data/lib/rails/generators/mongoid/model/model_generator.rb +24 -0
  115. data/lib/rails/generators/mongoid/model/templates/model.rb +15 -0
  116. data/lib/rails/generators/mongoid_generator.rb +61 -0
  117. metadata +284 -0
data/MIT_LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Durran Jordan
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,49 @@
1
+ = Overview
2
+
3
+ == About Mongoid
4
+
5
+ Mongoid is an ODM (Object-Document-Mapper) framework for MongoDB in Ruby.
6
+
7
+ == Project Tracking
8
+
9
+ * {Mongoid on Pivotal Tracker}[http://www.pivotaltracker.com/projects/27482]
10
+ * {Mongoid Google Group}[http://groups.google.com/group/mongoid]
11
+ * {Mongoid on CI Joe}[http://ci.mongoid.org/]
12
+ * {Mongoid Website and Documentation}[http://mongoid.org]
13
+
14
+ == Compatibility
15
+
16
+ Mongoid is developed against Ruby 1.8.6, 1.8.7, 1.9.1, 1.9.2
17
+
18
+ = Documentation
19
+
20
+ Please see the new Mongoid website for up-to-date documentation:
21
+ {mongoid.org}[http://mongoid.org]
22
+
23
+ = License
24
+
25
+ Copyright (c) 2009 Durran Jordan
26
+
27
+ Permission is hereby granted, free of charge, to any person obtaining
28
+ a copy of this software and associated documentation files (the
29
+ "Software"), to deal in the Software without restriction, including
30
+ without limitation the rights to use, copy, modify, merge, publish,
31
+ distribute, sublicense, and/or sell copies of the Software, and to
32
+ permit persons to whom the Software is furnished to do so, subject to
33
+ the following conditions:
34
+
35
+ The above copyright notice and this permission notice shall be
36
+ included in all copies or substantial portions of the Software.
37
+
38
+
39
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
40
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
41
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
42
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
43
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
44
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
45
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
46
+
47
+ = Credits
48
+
49
+ Durran Jordan: durran at gmail dot com
data/lib/mongoid.rb ADDED
@@ -0,0 +1,139 @@
1
+ # encoding: utf-8
2
+ # Copyright (c) 2009 Durran Jordan
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ require "rubygems"
23
+
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"
28
+
29
+ require "delegate"
30
+ require "singleton"
31
+ require "time"
32
+ require "ostruct"
33
+ require "active_support/core_ext"
34
+ require 'active_support/json'
35
+ require "active_support/inflector"
36
+ require "active_support/time_with_zone"
37
+ require "active_model"
38
+ require "active_model/callbacks"
39
+ require "active_model/conversion"
40
+ require "active_model/deprecated_error_methods"
41
+ require "active_model/errors"
42
+ require "active_model/naming"
43
+ require "active_model/serialization"
44
+ require "active_model/translation"
45
+ require "active_model/validator"
46
+ require "active_model/validations"
47
+ require "will_paginate/collection"
48
+ require "mongo"
49
+ require "mongoid/observable"
50
+ require "mongoid/associations"
51
+ require "mongoid/attributes"
52
+ require "mongoid/callbacks"
53
+ require "mongoid/collection"
54
+ require "mongoid/collections"
55
+ require "mongoid/config"
56
+ require "mongoid/contexts"
57
+ require "mongoid/criteria"
58
+ require "mongoid/cursor"
59
+ require "mongoid/deprecation"
60
+ require "mongoid/dirty"
61
+ require "mongoid/extensions"
62
+ require "mongoid/extras"
63
+ require "mongoid/errors"
64
+ require "mongoid/factory"
65
+ require "mongoid/field"
66
+ require "mongoid/fields"
67
+ require "mongoid/finders"
68
+ require "mongoid/identity"
69
+ require "mongoid/indexes"
70
+ require "mongoid/javascript"
71
+ require "mongoid/matchers"
72
+ require "mongoid/memoization"
73
+ require "mongoid/named_scope"
74
+ require "mongoid/paths"
75
+ require "mongoid/persistence"
76
+ require "mongoid/scope"
77
+ require "mongoid/state"
78
+ require "mongoid/timestamps"
79
+ require "mongoid/validations"
80
+ require "mongoid/versioning"
81
+ require "mongoid/components"
82
+ require "mongoid/document"
83
+
84
+ module Mongoid #:nodoc
85
+
86
+ MONGODB_VERSION = "1.4.0"
87
+
88
+ class << self
89
+
90
+ # Sets the Mongoid configuration options. Best used by passing a block.
91
+ #
92
+ # Example:
93
+ #
94
+ # Mongoid.configure do |config|
95
+ # name = "mongoid_test"
96
+ # host = "localhost"
97
+ # config.allow_dynamic_fields = false
98
+ # config.master = Mongo::Connection.new.db(name)
99
+ # config.slaves = [
100
+ # Mongo::Connection.new(host, 27018, :slave_ok => true).db(name),
101
+ # Mongo::Connection.new(host, 27019, :slave_ok => true).db(name)
102
+ # ]
103
+ # end
104
+ #
105
+ # Returns:
106
+ #
107
+ # The Mongoid +Config+ singleton instance.
108
+ def configure
109
+ config = Mongoid::Config.instance
110
+ block_given? ? yield(config) : config
111
+ end
112
+
113
+ # Easy convenience method for having an alert generated from the
114
+ # deprecation module.
115
+ #
116
+ # Example:
117
+ #
118
+ # <tt>Mongoid.deprecate("Method no longer used")</tt>
119
+ def deprecate(message)
120
+ Mongoid::Deprecation.instance.alert(message)
121
+ end
122
+
123
+ alias :config :configure
124
+ end
125
+
126
+ # Take all the public instance methods from the Config singleton and allow
127
+ # them to be accessed through the Mongoid module directly.
128
+ #
129
+ # Example:
130
+ #
131
+ # <tt>Mongoid.database = Mongo::Connection.new.db("test")</tt>
132
+ Mongoid::Config.public_instance_methods(false).each do |name|
133
+ (class << self; self; end).class_eval <<-EOT
134
+ def #{name}(*args)
135
+ configure.send("#{name}", *args)
136
+ end
137
+ EOT
138
+ end
139
+ end
@@ -0,0 +1,327 @@
1
+ # encoding: utf-8
2
+ require "mongoid/associations/proxy"
3
+ require "mongoid/associations/embedded_in"
4
+ require "mongoid/associations/embeds_many"
5
+ require "mongoid/associations/embeds_one"
6
+ require "mongoid/associations/foreign_key"
7
+ require "mongoid/associations/references_many"
8
+ require "mongoid/associations/references_many_as_array"
9
+ require "mongoid/associations/references_one"
10
+ require "mongoid/associations/referenced_in"
11
+ require "mongoid/associations/options"
12
+ require "mongoid/associations/meta_data"
13
+
14
+ module Mongoid # :nodoc:
15
+ module Associations #:nodoc:
16
+ extend ActiveSupport::Concern
17
+ included do
18
+ include ForeignKey
19
+
20
+ cattr_accessor :embedded
21
+ self.embedded = false
22
+
23
+ class_inheritable_accessor :associations
24
+ self.associations = {}
25
+
26
+ delegate :embedded, :embedded?, :to => "self.class"
27
+ end
28
+
29
+ module InstanceMethods
30
+ # Returns the associations for the +Document+.
31
+ def associations
32
+ self.class.associations
33
+ end
34
+
35
+ # are we in an embeds_many?
36
+ def embedded_many?
37
+ embedded? and _parent.associations[association_name].association == EmbedsMany
38
+ end
39
+
40
+ # Update all the dirty child documents after an update.
41
+ def update_embedded(name)
42
+ association = send(name)
43
+ association.to_a.each { |doc| doc.save if doc.changed? || doc.new_record? } unless association.blank?
44
+ end
45
+
46
+ # Update the one-to-one relational association for the name.
47
+ def update_association(name)
48
+ association = send(name)
49
+ association.save if new_record? && !association.nil?
50
+ end
51
+
52
+ # Updates all the one-to-many relational associations for the name.
53
+ def update_associations(name)
54
+ send(name).each { |doc| doc.save } if new_record?
55
+ end
56
+ end
57
+
58
+ module ClassMethods
59
+
60
+ # Adds a relational association from the child Document to a Document in
61
+ # another database or collection.
62
+ #
63
+ # Options:
64
+ #
65
+ # name: A +Symbol+ that is the related class name.
66
+ #
67
+ # Example:
68
+ #
69
+ # class Game
70
+ # include Mongoid::Document
71
+ # belongs_to_related :person
72
+ # end
73
+ #
74
+ def belongs_to_related(name, options = {}, &block)
75
+ opts = optionize(name, options, fk(name, options), &block)
76
+ associate(Associations::BelongsToRelated, opts)
77
+ field(opts.foreign_key, :type => Mongoid.use_object_ids ? BSON::ObjectID : String)
78
+ index(opts.foreign_key) unless embedded?
79
+
80
+ if options[:polymorphic]
81
+ field(opts.foreign_type)
82
+ index(opts.foreign_type)
83
+ end
84
+
85
+ end
86
+
87
+ # Gets whether or not the document is embedded.
88
+ #
89
+ # Example:
90
+ #
91
+ # <tt>Person.embedded?</tt>
92
+ #
93
+ # Returns:
94
+ #
95
+ # <tt>true</tt> if embedded, <tt>false</tt> if not.
96
+ def embedded?
97
+ !!self.embedded
98
+ end
99
+
100
+ # Adds the association back to the parent document. This macro is
101
+ # necessary to set the references from the child back to the parent
102
+ # document. If a child does not define this association calling
103
+ # persistence methods on the child object will cause a save to fail.
104
+ #
105
+ # Options:
106
+ #
107
+ # name: A +Symbol+ that matches the name of the parent class.
108
+ #
109
+ # Example:
110
+ #
111
+ # class Person
112
+ # include Mongoid::Document
113
+ # embeds_many :addresses
114
+ # end
115
+ #
116
+ # class Address
117
+ # include Mongoid::Document
118
+ # embedded_in :person, :inverse_of => :addresses
119
+ # end
120
+ def embedded_in(name, options = {}, &block)
121
+ unless options.has_key?(:inverse_of)
122
+ raise Errors::InvalidOptions.new("Options for embedded_in association must include :inverse_of")
123
+ end
124
+ self.embedded = true
125
+ associate(Associations::EmbeddedIn, optionize(name, options, nil, &block))
126
+ end
127
+
128
+ # Adds the association from a parent document to its children. The name
129
+ # of the association needs to be a pluralized form of the child class
130
+ # name.
131
+ #
132
+ # Options:
133
+ #
134
+ # name: A +Symbol+ that is the plural child class name.
135
+ #
136
+ # Example:
137
+ #
138
+ # class Person
139
+ # include Mongoid::Document
140
+ # embeds_many :addresses
141
+ # end
142
+ #
143
+ # class Address
144
+ # include Mongoid::Document
145
+ # embedded_in :person, :inverse_of => :addresses
146
+ # end
147
+ def embeds_many(name, options = {}, &block)
148
+ associate(Associations::EmbedsMany, optionize(name, options, nil, &block))
149
+ set_callback(:update, :after) { |document| document.update_embedded(name) } unless name == :versions
150
+ end
151
+
152
+ alias :embed_many :embeds_many
153
+
154
+ # Adds the association from a parent document to its child. The name
155
+ # of the association needs to be a singular form of the child class
156
+ # name.
157
+ #
158
+ # Options:
159
+ #
160
+ # name: A +Symbol+ that is the plural child class name.
161
+ #
162
+ # Example:
163
+ #
164
+ # class Person
165
+ # include Mongoid::Document
166
+ # embeds_one :name
167
+ # end
168
+ #
169
+ # class Name
170
+ # include Mongoid::Document
171
+ # embedded_in :person
172
+ # end
173
+ def embeds_one(name, options = {}, &block)
174
+ opts = optionize(name, options, nil, &block)
175
+ type = Associations::EmbedsOne
176
+ associate(type, opts)
177
+ add_builder(type, opts)
178
+ add_creator(type, opts)
179
+ set_callback(:update, :after) { |document| document.update_embedded(name) }
180
+ end
181
+
182
+ alias :embed_one :embeds_one
183
+
184
+ # Adds a relational association from the child Document to a Document in
185
+ # another database or collection.
186
+ #
187
+ # Options:
188
+ #
189
+ # name: A +Symbol+ that is the related class name.
190
+ #
191
+ # Example:
192
+ #
193
+ # class Game
194
+ # include Mongoid::Document
195
+ # referenced_in :person
196
+ # end
197
+ #
198
+ def referenced_in(name, options = {}, &block)
199
+ opts = optionize(name, options, constraint(name, options, :in), &block)
200
+ associate(Associations::ReferencedIn, opts)
201
+ field(opts.foreign_key, :type => Mongoid.use_object_ids ? BSON::ObjectID : String)
202
+ index(opts.foreign_key) unless embedded?
203
+ end
204
+
205
+ alias :belongs_to_related :referenced_in
206
+
207
+ # Adds a relational association from the Document to many Documents in
208
+ # another database or collection.
209
+ #
210
+ # Options:
211
+ #
212
+ # name: A +Symbol+ that is the related class name pluralized.
213
+ #
214
+ # Example:
215
+ #
216
+ # class Person
217
+ # include Mongoid::Document
218
+ # references_many :posts
219
+ # end
220
+ #
221
+ def references_many(name, options = {}, &block)
222
+ reference_many(name, options, &block)
223
+ set_callback :save, :before do |document|
224
+ document.update_associations(name)
225
+ end
226
+ end
227
+
228
+ alias :has_many_related :references_many
229
+
230
+ # Adds a relational association from the Document to one Document in
231
+ # another database or collection.
232
+ #
233
+ # Options:
234
+ #
235
+ # name: A +Symbol+ that is the related class name pluralized.
236
+ #
237
+ # Example:
238
+ #
239
+ # class Person
240
+ # include Mongoid::Document
241
+ # references_one :game
242
+ # end
243
+ def references_one(name, options = {}, &block)
244
+ opts = optionize(name, options, constraint(name, options, :one), &block)
245
+ associate(Associations::ReferencesOne, opts)
246
+ set_callback :save, :before do |document|
247
+ document.update_association(name)
248
+ end
249
+ end
250
+
251
+ alias :has_one_related :references_one
252
+
253
+ # Returns the macro associated with the supplied association name. This
254
+ # will return embeds_on, embeds_many, embedded_in or nil.
255
+ #
256
+ # Options:
257
+ #
258
+ # name: The association name.
259
+ #
260
+ # Example:
261
+ #
262
+ # <tt>Person.reflect_on_association(:addresses)</tt>
263
+ def reflect_on_association(name)
264
+ association = associations[name.to_s]
265
+ association ? association.macro : nil
266
+ end
267
+
268
+ protected
269
+ # Adds the association to the associations hash with the type as the key,
270
+ # then adds the accessors for the association. The defined setters and
271
+ # getters for the associations will perform the necessary memoization.
272
+ #
273
+ # Example:
274
+ #
275
+ # <tt>Person.associate(EmbedsMany, { :name => :addresses })</tt>
276
+ def associate(type, options)
277
+ name = options.name.to_s
278
+ associations[name] = MetaData.new(type, options)
279
+ define_method(name) { memoized(name) { type.instantiate(self, options) } }
280
+ define_method("#{name}=") do |object|
281
+ unmemoize(name)
282
+ memoized(name) { type.update(object, self, options) }
283
+ end
284
+ end
285
+
286
+ # Adds a builder for a has_one association. This comes in the form of
287
+ # build_name(attributes)
288
+ def add_builder(type, options)
289
+ name = options.name.to_s
290
+ define_method("build_#{name}") do |*params|
291
+ attrs = params[0]
292
+ attr_options = params[1] || {}
293
+ reset(name) { type.new(self, (attrs || {}).stringify_keys, options) } unless type == Associations::EmbedsOne && attr_options[:update_only]
294
+ end
295
+ end
296
+
297
+ # Adds a creator for a has_one association. This comes in the form of
298
+ # create_name(attributes)
299
+ def add_creator(type, options)
300
+ name = options.name.to_s
301
+ define_method("create_#{name}") do |*params|
302
+ attrs = params[0]
303
+ attr_options = params[1] || {}
304
+ send("build_#{name}", attrs, attr_options).tap(&:save) unless type == Associations::EmbedsOne && attr_options[:update_only]
305
+ end
306
+ end
307
+
308
+ # build the options given the params.
309
+ def optionize(name, options, foreign_key, &block)
310
+ Associations::Options.new(
311
+ options.merge(:name => name, :foreign_key => foreign_key, :extend => block)
312
+ )
313
+ end
314
+
315
+ def reference_many(name, options, &block)
316
+ if (options[:stored_as] == :array)
317
+ opts = optionize(name, options, constraint(name, options, :many_as_array), &block)
318
+ field "#{name.to_s.singularize}_ids", :type => Array, :default => []
319
+ associate(Associations::ReferencesManyAsArray, opts)
320
+ else
321
+ opts = optionize(name, options, constraint(name, options, :many), &block)
322
+ associate(Associations::ReferencesMany, opts)
323
+ end
324
+ end
325
+ end
326
+ end
327
+ end