mongo_mapper 0.6.10 → 0.7.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.
- data/README.rdoc +5 -14
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/lib/mongo_mapper.rb +48 -56
- data/lib/mongo_mapper/document.rb +136 -164
- data/lib/mongo_mapper/embedded_document.rb +29 -354
- data/lib/mongo_mapper/plugins.rb +31 -0
- data/lib/mongo_mapper/plugins/associations.rb +105 -0
- data/lib/mongo_mapper/plugins/associations/base.rb +123 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +25 -0
- data/lib/mongo_mapper/plugins/associations/collection.rb +21 -0
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +50 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +139 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_as_proxy.rb +28 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +117 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy.rb +31 -0
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +23 -0
- data/lib/mongo_mapper/plugins/associations/many_polymorphic_proxy.rb +13 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/associations/proxy.rb +118 -0
- data/lib/mongo_mapper/plugins/callbacks.rb +65 -0
- data/lib/mongo_mapper/plugins/clone.rb +13 -0
- data/lib/mongo_mapper/plugins/descendants.rb +16 -0
- data/lib/mongo_mapper/plugins/dirty.rb +119 -0
- data/lib/mongo_mapper/plugins/equality.rb +23 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +122 -0
- data/lib/mongo_mapper/plugins/inspect.rb +14 -0
- data/lib/mongo_mapper/plugins/keys.rb +324 -0
- data/lib/mongo_mapper/plugins/logger.rb +17 -0
- data/lib/mongo_mapper/plugins/pagination.rb +24 -0
- data/lib/mongo_mapper/plugins/pagination/proxy.rb +68 -0
- data/lib/mongo_mapper/plugins/protected.rb +45 -0
- data/lib/mongo_mapper/plugins/rails.rb +45 -0
- data/lib/mongo_mapper/plugins/serialization.rb +105 -0
- data/lib/mongo_mapper/plugins/validations.rb +46 -0
- data/lib/mongo_mapper/query.rb +130 -0
- data/lib/mongo_mapper/support.rb +40 -17
- data/lib/mongo_mapper/support/descendant_appends.rb +46 -0
- data/lib/mongo_mapper/support/find.rb +77 -0
- data/mongo_mapper.gemspec +55 -38
- data/performance/read_write.rb +52 -0
- data/specs.watchr +23 -2
- data/test/functional/associations/test_belongs_to_proxy.rb +12 -10
- data/test/functional/associations/test_many_documents_as_proxy.rb +4 -21
- data/test/functional/associations/test_many_documents_proxy.rb +2 -8
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +59 -39
- data/test/functional/associations/test_many_embedded_proxy.rb +145 -81
- data/test/functional/associations/test_many_polymorphic_proxy.rb +2 -40
- data/test/functional/associations/test_one_proxy.rb +25 -10
- data/test/functional/test_binary.rb +2 -8
- data/test/functional/test_callbacks.rb +1 -5
- data/test/functional/test_dirty.rb +27 -23
- data/test/functional/test_document.rb +224 -165
- data/test/functional/test_embedded_document.rb +72 -82
- data/test/functional/test_identity_map.rb +508 -0
- data/test/functional/test_modifiers.rb +15 -5
- data/test/functional/test_pagination.rb +1 -3
- data/test/functional/test_protected.rb +155 -0
- data/test/functional/test_string_id_compatibility.rb +7 -12
- data/test/functional/test_validations.rb +26 -58
- data/test/models.rb +0 -39
- data/test/test_helper.rb +37 -3
- data/test/unit/associations/test_base.rb +5 -5
- data/test/unit/associations/test_proxy.rb +8 -6
- data/test/unit/test_descendant_appends.rb +71 -0
- data/test/unit/test_document.rb +71 -76
- data/test/unit/test_dynamic_finder.rb +27 -29
- data/test/unit/test_embedded_document.rb +555 -601
- data/test/unit/{test_key.rb → test_keys.rb} +2 -5
- data/test/unit/test_mongo_mapper.rb +69 -9
- data/test/unit/test_pagination.rb +40 -32
- data/test/unit/test_plugins.rb +50 -0
- data/test/unit/{test_finder_options.rb → test_query.rb} +74 -65
- data/test/unit/test_rails.rb +123 -0
- data/test/unit/{test_serializations.rb → test_serialization.rb} +1 -2
- data/test/unit/test_support.rb +23 -7
- data/test/unit/test_time_zones.rb +3 -4
- data/test/unit/test_validations.rb +58 -17
- metadata +53 -36
- data/lib/mongo_mapper/associations.rb +0 -78
- data/lib/mongo_mapper/associations/base.rb +0 -119
- data/lib/mongo_mapper/associations/belongs_to_polymorphic_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/belongs_to_proxy.rb +0 -21
- data/lib/mongo_mapper/associations/collection.rb +0 -19
- data/lib/mongo_mapper/associations/in_array_proxy.rb +0 -137
- data/lib/mongo_mapper/associations/many_documents_as_proxy.rb +0 -26
- data/lib/mongo_mapper/associations/many_documents_proxy.rb +0 -115
- data/lib/mongo_mapper/associations/many_embedded_polymorphic_proxy.rb +0 -31
- data/lib/mongo_mapper/associations/many_embedded_proxy.rb +0 -54
- data/lib/mongo_mapper/associations/many_polymorphic_proxy.rb +0 -11
- data/lib/mongo_mapper/associations/one_proxy.rb +0 -64
- data/lib/mongo_mapper/associations/proxy.rb +0 -116
- data/lib/mongo_mapper/callbacks.rb +0 -61
- data/lib/mongo_mapper/dirty.rb +0 -117
- data/lib/mongo_mapper/dynamic_finder.rb +0 -74
- data/lib/mongo_mapper/finder_options.rb +0 -145
- data/lib/mongo_mapper/key.rb +0 -36
- data/lib/mongo_mapper/mongo_mapper.rb +0 -125
- data/lib/mongo_mapper/pagination.rb +0 -66
- data/lib/mongo_mapper/rails_compatibility/document.rb +0 -15
- data/lib/mongo_mapper/rails_compatibility/embedded_document.rb +0 -28
- data/lib/mongo_mapper/serialization.rb +0 -54
- data/lib/mongo_mapper/serializers/json_serializer.rb +0 -48
- data/lib/mongo_mapper/validations.rb +0 -39
- data/test/functional/test_rails_compatibility.rb +0 -25
@@ -1,380 +1,55 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
module EmbeddedDocument
|
3
|
+
extend Support::DescendantAppends
|
4
|
+
|
3
5
|
def self.included(model)
|
4
6
|
model.class_eval do
|
5
|
-
extend ClassMethods
|
6
7
|
include InstanceMethods
|
7
|
-
|
8
|
-
extend
|
9
|
-
include Associations::InstanceMethods
|
10
|
-
|
11
|
-
include RailsCompatibility::EmbeddedDocument
|
12
|
-
include Validatable
|
13
|
-
include Serialization
|
8
|
+
extend ClassMethods
|
9
|
+
extend Plugins
|
14
10
|
|
15
|
-
|
11
|
+
plugin Plugins::Associations
|
12
|
+
plugin Plugins::Clone
|
13
|
+
plugin Plugins::Descendants
|
14
|
+
plugin Plugins::Equality
|
15
|
+
plugin Plugins::Inspect
|
16
|
+
plugin Plugins::Keys
|
17
|
+
plugin Plugins::Logger
|
18
|
+
plugin Plugins::Protected
|
19
|
+
plugin Plugins::Rails
|
20
|
+
plugin Plugins::Serialization
|
21
|
+
plugin Plugins::Validations
|
16
22
|
|
17
|
-
|
18
|
-
attr_accessor :_root_document
|
23
|
+
attr_accessor :_root_document, :_parent_document
|
19
24
|
end
|
25
|
+
|
26
|
+
super
|
20
27
|
end
|
21
28
|
|
22
29
|
module ClassMethods
|
23
|
-
def logger
|
24
|
-
MongoMapper.logger
|
25
|
-
end
|
26
|
-
|
27
|
-
def inherited(subclass)
|
28
|
-
unless subclass.embeddable?
|
29
|
-
subclass.set_collection_name(collection_name)
|
30
|
-
end
|
31
|
-
|
32
|
-
(@subclasses ||= []) << subclass
|
33
|
-
end
|
34
|
-
|
35
|
-
def subclasses
|
36
|
-
@subclasses
|
37
|
-
end
|
38
|
-
|
39
|
-
def keys
|
40
|
-
@keys ||= if parent = parent_model
|
41
|
-
parent.keys.dup
|
42
|
-
else
|
43
|
-
HashWithIndifferentAccess.new
|
44
|
-
end
|
45
|
-
end
|
46
|
-
|
47
|
-
def key(*args)
|
48
|
-
key = Key.new(*args)
|
49
|
-
keys[key.name] = key
|
50
|
-
|
51
|
-
create_accessors_for(key)
|
52
|
-
create_key_in_subclasses(*args)
|
53
|
-
create_validations_for(key)
|
54
|
-
|
55
|
-
key
|
56
|
-
end
|
57
|
-
|
58
|
-
def using_object_id?
|
59
|
-
object_id_key?(:_id)
|
60
|
-
end
|
61
|
-
|
62
|
-
def object_id_key?(name)
|
63
|
-
key = keys[name.to_s]
|
64
|
-
key && key.type == ObjectId
|
65
|
-
end
|
66
|
-
|
67
30
|
def embeddable?
|
68
|
-
|
31
|
+
true
|
69
32
|
end
|
70
33
|
|
71
|
-
def
|
72
|
-
(
|
73
|
-
parent_class.ancestors.include?(EmbeddedDocument)
|
74
|
-
end
|
75
|
-
end
|
76
|
-
|
77
|
-
def to_mongo(instance)
|
78
|
-
return nil if instance.nil?
|
79
|
-
instance.to_mongo
|
80
|
-
end
|
81
|
-
|
82
|
-
def from_mongo(value)
|
83
|
-
return nil if value.nil?
|
84
|
-
value.is_a?(self) ? value : initialize_doc(value)
|
85
|
-
end
|
86
|
-
|
87
|
-
private
|
88
|
-
def initialize_doc(doc)
|
89
|
-
begin
|
90
|
-
klass = doc['_type'].present? ? doc['_type'].constantize : self
|
91
|
-
klass.new(doc)
|
92
|
-
rescue NameError
|
93
|
-
new(doc)
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
|
-
def accessors_module
|
98
|
-
module_defined = if method(:const_defined?).arity == 1 # Ruby 1.9 compat check
|
99
|
-
const_defined?('MongoMapperKeys')
|
100
|
-
else
|
101
|
-
const_defined?('MongoMapperKeys', false)
|
102
|
-
end
|
103
|
-
|
104
|
-
if module_defined
|
105
|
-
const_get 'MongoMapperKeys'
|
106
|
-
else
|
107
|
-
const_set 'MongoMapperKeys', Module.new
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def create_accessors_for(key)
|
112
|
-
accessors_module.module_eval <<-end_eval
|
113
|
-
def #{key.name}
|
114
|
-
read_attribute(:'#{key.name}')
|
115
|
-
end
|
116
|
-
|
117
|
-
def #{key.name}_before_typecast
|
118
|
-
read_attribute_before_typecast(:'#{key.name}')
|
119
|
-
end
|
120
|
-
|
121
|
-
def #{key.name}=(value)
|
122
|
-
write_attribute(:'#{key.name}', value)
|
123
|
-
end
|
124
|
-
|
125
|
-
def #{key.name}?
|
126
|
-
read_attribute(:#{key.name}).present?
|
127
|
-
end
|
128
|
-
end_eval
|
129
|
-
include accessors_module
|
130
|
-
end
|
131
|
-
|
132
|
-
def create_key_in_subclasses(*args)
|
133
|
-
return if subclasses.blank?
|
134
|
-
|
135
|
-
subclasses.each do |subclass|
|
136
|
-
subclass.key(*args)
|
137
|
-
end
|
138
|
-
end
|
139
|
-
|
140
|
-
def create_validations_for(key)
|
141
|
-
attribute = key.name.to_sym
|
142
|
-
|
143
|
-
if key.options[:required]
|
144
|
-
validates_presence_of(attribute)
|
145
|
-
end
|
146
|
-
|
147
|
-
if key.options[:unique]
|
148
|
-
validates_uniqueness_of(attribute)
|
149
|
-
end
|
150
|
-
|
151
|
-
if key.options[:numeric]
|
152
|
-
number_options = key.type == Integer ? {:only_integer => true} : {}
|
153
|
-
validates_numericality_of(attribute, number_options)
|
154
|
-
end
|
155
|
-
|
156
|
-
if key.options[:format]
|
157
|
-
validates_format_of(attribute, :with => key.options[:format])
|
158
|
-
end
|
159
|
-
|
160
|
-
if key.options[:length]
|
161
|
-
length_options = case key.options[:length]
|
162
|
-
when Integer
|
163
|
-
{:minimum => 0, :maximum => key.options[:length]}
|
164
|
-
when Range
|
165
|
-
{:within => key.options[:length]}
|
166
|
-
when Hash
|
167
|
-
key.options[:length]
|
168
|
-
end
|
169
|
-
validates_length_of(attribute, length_options)
|
170
|
-
end
|
34
|
+
def embedded_in(owner_name)
|
35
|
+
define_method(owner_name) { _parent_document }
|
171
36
|
end
|
172
37
|
end
|
173
38
|
|
174
39
|
module InstanceMethods
|
175
|
-
def
|
176
|
-
|
177
|
-
|
178
|
-
if collection = attrs.delete(name)
|
179
|
-
if association.many? && association.klass.embeddable?
|
180
|
-
root_document = attrs[:_root_document] || self
|
181
|
-
collection.each do |doc|
|
182
|
-
doc[:_root_document] = root_document
|
183
|
-
end
|
184
|
-
end
|
185
|
-
send("#{association.name}=", collection)
|
186
|
-
end
|
187
|
-
end
|
188
|
-
|
189
|
-
self.attributes = attrs
|
190
|
-
|
191
|
-
if respond_to?(:_type=) && self['_type'].blank?
|
192
|
-
self._type = self.class.name
|
193
|
-
end
|
194
|
-
end
|
195
|
-
|
196
|
-
if self.class.embeddable?
|
197
|
-
if read_attribute(:_id).blank?
|
198
|
-
write_attribute :_id, Mongo::ObjectID.new
|
199
|
-
@new_document = true
|
200
|
-
else
|
201
|
-
@new_document = false
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
205
|
-
|
206
|
-
def new?
|
207
|
-
!!@new_document
|
208
|
-
end
|
209
|
-
|
210
|
-
def to_param
|
211
|
-
id.to_s
|
212
|
-
end
|
213
|
-
|
214
|
-
def attributes=(attrs)
|
215
|
-
return if attrs.blank?
|
216
|
-
attrs.each_pair do |name, value|
|
217
|
-
writer_method = "#{name}="
|
218
|
-
|
219
|
-
if respond_to?(writer_method)
|
220
|
-
self.send(writer_method, value)
|
221
|
-
else
|
222
|
-
self[name.to_s] = value
|
223
|
-
end
|
224
|
-
end
|
225
|
-
end
|
226
|
-
|
227
|
-
def attributes
|
228
|
-
attrs = HashWithIndifferentAccess.new
|
229
|
-
|
230
|
-
embedded_keys.each do |key|
|
231
|
-
attrs[key.name] = read_attribute(key.name).try(:attributes)
|
232
|
-
end
|
233
|
-
|
234
|
-
non_embedded_keys.each do |key|
|
235
|
-
attrs[key.name] = read_attribute(key.name)
|
236
|
-
end
|
237
|
-
|
238
|
-
embedded_associations.each do |association|
|
239
|
-
documents = instance_variable_get(association.ivar)
|
240
|
-
next if documents.nil?
|
241
|
-
attrs[association.name] = documents.collect { |doc| doc.attributes }
|
242
|
-
end
|
243
|
-
|
244
|
-
attrs
|
245
|
-
end
|
246
|
-
|
247
|
-
def to_mongo
|
248
|
-
attrs = HashWithIndifferentAccess.new
|
249
|
-
|
250
|
-
_keys.each_pair do |name, key|
|
251
|
-
value = key.set(read_attribute(key.name))
|
252
|
-
attrs[name] = value unless value.nil?
|
253
|
-
end
|
254
|
-
|
255
|
-
embedded_associations.each do |association|
|
256
|
-
if documents = instance_variable_get(association.ivar)
|
257
|
-
attrs[association.name] = documents.map { |document| document.to_mongo }
|
258
|
-
end
|
259
|
-
end
|
260
|
-
|
261
|
-
attrs
|
262
|
-
end
|
263
|
-
|
264
|
-
def clone
|
265
|
-
clone_attributes = self.attributes
|
266
|
-
clone_attributes.delete("_id")
|
267
|
-
self.class.new(clone_attributes)
|
268
|
-
end
|
269
|
-
|
270
|
-
def [](name)
|
271
|
-
read_attribute(name)
|
272
|
-
end
|
273
|
-
|
274
|
-
def []=(name, value)
|
275
|
-
ensure_key_exists(name)
|
276
|
-
write_attribute(name, value)
|
277
|
-
end
|
278
|
-
|
279
|
-
def ==(other)
|
280
|
-
other.is_a?(self.class) && _id == other._id
|
281
|
-
end
|
282
|
-
|
283
|
-
def id
|
284
|
-
self[:_id]
|
285
|
-
end
|
286
|
-
|
287
|
-
def id=(value)
|
288
|
-
if self.class.using_object_id?
|
289
|
-
value = MongoMapper.normalize_object_id(value)
|
290
|
-
else
|
291
|
-
@using_custom_id = true
|
40
|
+
def save(options={})
|
41
|
+
if result = _root_document.try(:save, options)
|
42
|
+
@new = false
|
292
43
|
end
|
293
|
-
|
294
|
-
self[:_id] = value
|
295
|
-
end
|
296
|
-
|
297
|
-
def using_custom_id?
|
298
|
-
!!@using_custom_id
|
44
|
+
result
|
299
45
|
end
|
300
46
|
|
301
|
-
def inspect
|
302
|
-
attributes_as_nice_string = key_names.collect do |name|
|
303
|
-
"#{name}: #{read_attribute(name).inspect}"
|
304
|
-
end.join(", ")
|
305
|
-
"#<#{self.class} #{attributes_as_nice_string}>"
|
306
|
-
end
|
307
|
-
|
308
|
-
def save(options={})
|
309
|
-
_root_document.try(:save, options)
|
310
|
-
end
|
311
|
-
|
312
47
|
def save!(options={})
|
313
|
-
_root_document.try(:save!, options)
|
314
|
-
|
315
|
-
|
316
|
-
def update_attributes(attrs={})
|
317
|
-
self.attributes = attrs
|
318
|
-
save
|
319
|
-
end
|
320
|
-
|
321
|
-
def update_attributes!(attrs={})
|
322
|
-
self.attributes = attrs
|
323
|
-
save!
|
324
|
-
end
|
325
|
-
|
326
|
-
def logger
|
327
|
-
self.class.logger
|
328
|
-
end
|
329
|
-
|
330
|
-
private
|
331
|
-
def _keys
|
332
|
-
self.metaclass.keys
|
333
|
-
end
|
334
|
-
|
335
|
-
def key_names
|
336
|
-
_keys.keys
|
337
|
-
end
|
338
|
-
|
339
|
-
def non_embedded_keys
|
340
|
-
_keys.values.select { |key| !key.embeddable? }
|
341
|
-
end
|
342
|
-
|
343
|
-
def embedded_keys
|
344
|
-
_keys.values.select { |key| key.embeddable? }
|
345
|
-
end
|
346
|
-
|
347
|
-
def ensure_key_exists(name)
|
348
|
-
self.metaclass.key(name) unless respond_to?("#{name}=")
|
349
|
-
end
|
350
|
-
|
351
|
-
def read_attribute(name)
|
352
|
-
if key = _keys[name]
|
353
|
-
value = key.get(instance_variable_get("@#{name}"))
|
354
|
-
instance_variable_set "@#{name}", value
|
355
|
-
value
|
356
|
-
else
|
357
|
-
raise KeyNotFound, "Could not find key: #{name.inspect}"
|
358
|
-
end
|
359
|
-
end
|
360
|
-
|
361
|
-
def read_attribute_before_typecast(name)
|
362
|
-
instance_variable_get("@#{name}_before_typecast")
|
363
|
-
end
|
364
|
-
|
365
|
-
def write_attribute(name, value)
|
366
|
-
key = _keys[name]
|
367
|
-
instance_variable_set "@#{name}_before_typecast", value
|
368
|
-
instance_variable_set "@#{name}", key.set(value)
|
369
|
-
end
|
370
|
-
|
371
|
-
def embedded_associations
|
372
|
-
associations.select do |name, association|
|
373
|
-
association.embeddable?
|
374
|
-
end.map do |name, association|
|
375
|
-
association
|
376
|
-
end
|
48
|
+
if result = _root_document.try(:save!, options)
|
49
|
+
@new = false
|
377
50
|
end
|
51
|
+
result
|
52
|
+
end
|
378
53
|
end # InstanceMethods
|
379
54
|
end # EmbeddedDocument
|
380
55
|
end # MongoMapper
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Plugins
|
3
|
+
def plugins
|
4
|
+
@plugins ||= []
|
5
|
+
end
|
6
|
+
|
7
|
+
def plugin(mod)
|
8
|
+
extend mod::ClassMethods if mod.const_defined?(:ClassMethods)
|
9
|
+
include mod::InstanceMethods if mod.const_defined?(:InstanceMethods)
|
10
|
+
mod.configure(self) if mod.respond_to?(:configure)
|
11
|
+
plugins << mod
|
12
|
+
end
|
13
|
+
|
14
|
+
autoload :Callbacks, 'mongo_mapper/plugins/callbacks'
|
15
|
+
autoload :Clone, 'mongo_mapper/plugins/clone'
|
16
|
+
autoload :Descendants, 'mongo_mapper/plugins/descendants'
|
17
|
+
autoload :Dirty, 'mongo_mapper/plugins/dirty'
|
18
|
+
autoload :Equality, 'mongo_mapper/plugins/equality'
|
19
|
+
autoload :IdentityMap, 'mongo_mapper/plugins/identity_map'
|
20
|
+
autoload :Inspect, 'mongo_mapper/plugins/inspect'
|
21
|
+
autoload :Keys, 'mongo_mapper/plugins/keys'
|
22
|
+
autoload :Logger, 'mongo_mapper/plugins/logger'
|
23
|
+
autoload :Protected, 'mongo_mapper/plugins/protected'
|
24
|
+
autoload :Rails, 'mongo_mapper/plugins/rails'
|
25
|
+
autoload :Serialization, 'mongo_mapper/plugins/serialization'
|
26
|
+
autoload :Validations, 'mongo_mapper/plugins/validations'
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'mongo_mapper/plugins/associations'
|
31
|
+
require 'mongo_mapper/plugins/pagination'
|
@@ -0,0 +1,105 @@
|
|
1
|
+
module MongoMapper
|
2
|
+
module Plugins
|
3
|
+
module Associations
|
4
|
+
module ClassMethods
|
5
|
+
def belongs_to(association_id, options={}, &extension)
|
6
|
+
create_association(:belongs_to, association_id, options, &extension)
|
7
|
+
end
|
8
|
+
|
9
|
+
def many(association_id, options={}, &extension)
|
10
|
+
create_association(:many, association_id, options, &extension)
|
11
|
+
end
|
12
|
+
|
13
|
+
def one(association_id, options={}, &extension)
|
14
|
+
create_association(:one, association_id, options, &extension)
|
15
|
+
end
|
16
|
+
|
17
|
+
def associations
|
18
|
+
@associations ||= HashWithIndifferentAccess.new
|
19
|
+
end
|
20
|
+
|
21
|
+
def associations=(hash)
|
22
|
+
@associations = hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def inherited(subclass)
|
26
|
+
subclass.associations = associations.dup
|
27
|
+
super
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
def create_association(type, name, options, &extension)
|
32
|
+
association = Associations::Base.new(type, name, options, &extension)
|
33
|
+
associations[association.name] = association
|
34
|
+
|
35
|
+
define_method(association.name) do
|
36
|
+
get_proxy(association)
|
37
|
+
end
|
38
|
+
|
39
|
+
define_method("#{association.name}=") do |value|
|
40
|
+
get_proxy(association).replace(value)
|
41
|
+
value
|
42
|
+
end
|
43
|
+
|
44
|
+
if association.one? || association.belongs_to?
|
45
|
+
define_method("#{association.name}?") do
|
46
|
+
get_proxy(association).present?
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
if association.options[:dependent] && association.many? && !association.embeddable?
|
51
|
+
after_destroy do |doc|
|
52
|
+
case association.options[:dependent]
|
53
|
+
when :destroy
|
54
|
+
doc.get_proxy(association).destroy_all
|
55
|
+
when :delete_all
|
56
|
+
doc.get_proxy(association).delete_all
|
57
|
+
when :nullify
|
58
|
+
doc.get_proxy(association).nullify
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
module InstanceMethods
|
66
|
+
def associations
|
67
|
+
self.class.associations
|
68
|
+
end
|
69
|
+
|
70
|
+
# @api private?
|
71
|
+
def embedded_associations
|
72
|
+
associations.select do |name, association|
|
73
|
+
association.embeddable?
|
74
|
+
end.map do |name, association|
|
75
|
+
association
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_proxy(association)
|
80
|
+
unless proxy = self.instance_variable_get(association.ivar)
|
81
|
+
proxy = association.proxy_class.new(self, association)
|
82
|
+
self.instance_variable_set(association.ivar, proxy)
|
83
|
+
end
|
84
|
+
|
85
|
+
proxy
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
autoload :Base, 'mongo_mapper/plugins/associations/base'
|
90
|
+
autoload :Collection, 'mongo_mapper/plugins/associations/collection'
|
91
|
+
autoload :EmbeddedCollection, 'mongo_mapper/plugins/associations/embedded_collection'
|
92
|
+
autoload :ManyDocumentsProxy, 'mongo_mapper/plugins/associations/many_documents_proxy'
|
93
|
+
autoload :BelongsToProxy, 'mongo_mapper/plugins/associations/belongs_to_proxy'
|
94
|
+
autoload :BelongsToPolymorphicProxy, 'mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy'
|
95
|
+
autoload :ManyPolymorphicProxy, 'mongo_mapper/plugins/associations/many_polymorphic_proxy'
|
96
|
+
autoload :ManyEmbeddedProxy, 'mongo_mapper/plugins/associations/many_embedded_proxy'
|
97
|
+
autoload :ManyEmbeddedPolymorphicProxy, 'mongo_mapper/plugins/associations/many_embedded_polymorphic_proxy'
|
98
|
+
autoload :ManyDocumentsAsProxy, 'mongo_mapper/plugins/associations/many_documents_as_proxy'
|
99
|
+
autoload :OneProxy, 'mongo_mapper/plugins/associations/one_proxy'
|
100
|
+
autoload :InArrayProxy, 'mongo_mapper/plugins/associations/in_array_proxy'
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
require 'mongo_mapper/plugins/associations/proxy'
|