mongo_mapper 0.8.6 → 0.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.
- data/UPGRADES +10 -0
- data/bin/mmconsole +0 -1
- data/examples/identity_map/automatic.rb +1 -7
- data/examples/plugins.rb +9 -9
- data/examples/safe.rb +43 -0
- data/lib/mongo_mapper.rb +46 -33
- data/lib/mongo_mapper/document.rb +33 -32
- data/lib/mongo_mapper/embedded_document.rb +22 -22
- data/lib/mongo_mapper/locale/en.yml +5 -0
- data/lib/mongo_mapper/middleware/identity_map.rb +16 -0
- data/lib/mongo_mapper/plugins.rb +16 -3
- data/lib/mongo_mapper/plugins/accessible.rb +2 -0
- data/lib/mongo_mapper/plugins/active_model.rb +18 -0
- data/lib/mongo_mapper/plugins/associations.rb +37 -42
- data/lib/mongo_mapper/plugins/associations/base.rb +14 -50
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +58 -0
- data/lib/mongo_mapper/plugins/associations/belongs_to_polymorphic_proxy.rb +6 -1
- data/lib/mongo_mapper/plugins/associations/belongs_to_proxy.rb +30 -2
- data/lib/mongo_mapper/plugins/associations/embedded_collection.rb +4 -0
- data/lib/mongo_mapper/plugins/associations/in_array_proxy.rb +12 -6
- data/lib/mongo_mapper/plugins/associations/many_association.rb +67 -0
- data/lib/mongo_mapper/plugins/associations/many_documents_proxy.rb +5 -5
- data/lib/mongo_mapper/plugins/associations/many_embedded_proxy.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/one_association.rb +20 -0
- data/lib/mongo_mapper/plugins/associations/one_embedded_proxy.rb +5 -0
- data/lib/mongo_mapper/plugins/associations/one_proxy.rb +7 -7
- data/lib/mongo_mapper/plugins/associations/proxy.rb +2 -2
- data/lib/mongo_mapper/plugins/caching.rb +3 -1
- data/lib/mongo_mapper/plugins/callbacks.rb +12 -221
- data/lib/mongo_mapper/plugins/clone.rb +3 -1
- data/lib/mongo_mapper/plugins/dirty.rb +38 -91
- data/lib/mongo_mapper/plugins/document.rb +4 -2
- data/lib/mongo_mapper/plugins/dynamic_querying.rb +2 -0
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +43 -0
- data/lib/mongo_mapper/plugins/embedded_document.rb +16 -9
- data/lib/mongo_mapper/plugins/equality.rb +2 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +4 -2
- data/lib/mongo_mapper/plugins/indexes.rb +2 -0
- data/lib/mongo_mapper/plugins/inspect.rb +3 -1
- data/lib/mongo_mapper/plugins/keys.rb +28 -22
- data/lib/mongo_mapper/plugins/keys/key.rb +12 -6
- data/lib/mongo_mapper/plugins/logger.rb +2 -0
- data/lib/mongo_mapper/plugins/modifiers.rb +3 -1
- data/lib/mongo_mapper/plugins/pagination.rb +2 -0
- data/lib/mongo_mapper/plugins/persistence.rb +2 -0
- data/lib/mongo_mapper/plugins/protected.rb +2 -0
- data/lib/mongo_mapper/plugins/querying.rb +5 -4
- data/lib/mongo_mapper/plugins/rails.rb +3 -5
- data/lib/mongo_mapper/plugins/safe.rb +2 -0
- data/lib/mongo_mapper/plugins/sci.rb +2 -0
- data/lib/mongo_mapper/plugins/scopes.rb +2 -0
- data/lib/mongo_mapper/plugins/serialization.rb +67 -46
- data/lib/mongo_mapper/plugins/timestamps.rb +3 -1
- data/lib/mongo_mapper/plugins/userstamps.rb +2 -0
- data/lib/mongo_mapper/plugins/validations.rb +40 -24
- data/lib/mongo_mapper/railtie.rb +49 -0
- data/lib/mongo_mapper/railtie/database.rake +60 -0
- data/lib/mongo_mapper/support/descendant_appends.rb +11 -11
- data/lib/mongo_mapper/translation.rb +10 -0
- data/lib/mongo_mapper/version.rb +1 -1
- data/lib/rails/generators/mongo_mapper/config/config_generator.rb +24 -0
- data/lib/rails/generators/mongo_mapper/config/templates/mongo.yml +18 -0
- data/lib/rails/generators/mongo_mapper/model/model_generator.rb +23 -0
- data/lib/rails/generators/mongo_mapper/model/templates/model.rb +11 -0
- data/test/functional/associations/test_belongs_to_polymorphic_proxy.rb +1 -0
- data/test/functional/associations/test_belongs_to_proxy.rb +131 -1
- data/test/functional/associations/test_in_array_proxy.rb +30 -0
- data/test/functional/associations/test_many_documents_proxy.rb +30 -2
- data/test/functional/associations/test_many_embedded_proxy.rb +33 -0
- data/test/functional/associations/test_many_polymorphic_proxy.rb +1 -0
- data/test/functional/associations/test_one_embedded_proxy.rb +21 -2
- data/test/functional/associations/test_one_proxy.rb +49 -9
- data/test/functional/test_associations.rb +2 -0
- data/test/functional/test_caching.rb +3 -2
- data/test/functional/test_callbacks.rb +25 -18
- data/test/functional/test_dirty.rb +123 -1
- data/test/functional/test_document.rb +26 -2
- data/test/functional/test_embedded_document.rb +68 -2
- data/test/functional/test_identity_map.rb +3 -4
- data/test/functional/test_querying.rb +11 -0
- data/test/functional/test_userstamps.rb +2 -2
- data/test/functional/test_validations.rb +31 -29
- data/test/models.rb +10 -0
- data/test/test_active_model_lint.rb +1 -1
- data/test/test_helper.rb +9 -10
- data/test/unit/associations/test_base.rb +24 -100
- data/test/unit/associations/test_belongs_to_association.rb +29 -0
- data/test/unit/associations/test_many_association.rb +63 -0
- data/test/unit/associations/test_one_association.rb +18 -0
- data/test/unit/serializers/test_json_serializer.rb +0 -1
- data/test/unit/test_descendant_appends.rb +8 -16
- data/test/unit/test_document.rb +4 -9
- data/test/unit/test_dynamic_finder.rb +1 -1
- data/test/unit/test_embedded_document.rb +51 -18
- data/test/unit/test_identity_map_middleware.rb +34 -0
- data/test/unit/test_inspect.rb +22 -0
- data/test/unit/test_key.rb +21 -1
- data/test/unit/test_keys.rb +0 -2
- data/test/unit/test_plugins.rb +106 -20
- data/test/unit/test_rails.rb +8 -8
- data/test/unit/test_serialization.rb +116 -1
- data/test/unit/test_translation.rb +27 -0
- data/test/unit/test_validations.rb +66 -81
- metadata +103 -43
- data/examples/identity_map/middleware.rb +0 -14
- data/lib/mongo_mapper/plugins/descendants.rb +0 -17
- data/rails/init.rb +0 -19
@@ -2,6 +2,8 @@
|
|
2
2
|
module MongoMapper
|
3
3
|
module Plugins
|
4
4
|
module Document
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
5
7
|
module ClassMethods
|
6
8
|
def embeddable?
|
7
9
|
false
|
@@ -20,8 +22,8 @@ module MongoMapper
|
|
20
22
|
def reload
|
21
23
|
if doc = collection.find_one(:_id => id)
|
22
24
|
tap do |instance|
|
23
|
-
instance.class.associations.
|
24
|
-
|
25
|
+
instance.class.associations.each_value do |association|
|
26
|
+
get_proxy(association).reset
|
25
27
|
end
|
26
28
|
instance.attributes = doc
|
27
29
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module EmbeddedCallbacks
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
extend ::ActiveModel::Callbacks
|
9
|
+
include ::ActiveModel::Validations::Callbacks
|
10
|
+
|
11
|
+
define_model_callbacks :validation, :save, :create, :update, :destroy, :only => [:before, :after]
|
12
|
+
end
|
13
|
+
|
14
|
+
module InstanceMethods
|
15
|
+
def run_callbacks(callback, &block)
|
16
|
+
embedded_docs = []
|
17
|
+
|
18
|
+
embedded_associations.each do |association|
|
19
|
+
embedded_docs += Array(get_proxy(association).send(:load_target))
|
20
|
+
end
|
21
|
+
|
22
|
+
block = embedded_docs.inject(block) do |chain, doc|
|
23
|
+
if doc.class.respond_to?("_#{callback}_callbacks")
|
24
|
+
lambda { doc.run_callbacks(callback, &chain) }
|
25
|
+
else
|
26
|
+
chain
|
27
|
+
end
|
28
|
+
end
|
29
|
+
super callback, &block
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Need to monkey patch ActiveModel for now since it uses the internal
|
37
|
+
# _run_validation_callbacks, which is impossible to override due to the
|
38
|
+
# way ActiveSupport::Callbacks is implemented.
|
39
|
+
ActiveModel::Validations::Callbacks.class_eval do
|
40
|
+
def run_validations!
|
41
|
+
run_callbacks(:validation) { super }
|
42
|
+
end
|
43
|
+
end
|
@@ -2,10 +2,10 @@
|
|
2
2
|
module MongoMapper
|
3
3
|
module Plugins
|
4
4
|
module EmbeddedDocument
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
attr_accessor :_parent_document
|
9
9
|
end
|
10
10
|
|
11
11
|
module ClassMethods
|
@@ -14,7 +14,7 @@ module MongoMapper
|
|
14
14
|
end
|
15
15
|
|
16
16
|
def embedded_in(owner_name)
|
17
|
-
|
17
|
+
alias_method owner_name, :_parent_document
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
@@ -29,20 +29,27 @@ module MongoMapper
|
|
29
29
|
|
30
30
|
def save(options={})
|
31
31
|
_root_document.try(:save, options).tap do |result|
|
32
|
-
|
32
|
+
persist(options) if result
|
33
33
|
end
|
34
34
|
end
|
35
35
|
|
36
36
|
def save!(options={})
|
37
|
-
|
38
|
-
|
37
|
+
valid? || raise(DocumentNotValid.new(self))
|
38
|
+
_root_document.try(:save!, options).tap do |result|
|
39
|
+
persist(options) if result
|
39
40
|
end
|
40
41
|
end
|
41
42
|
|
43
|
+
def persist(options={})
|
44
|
+
@_new = false
|
45
|
+
clear_changes if respond_to?(:clear_changes)
|
46
|
+
save_to_collection(options)
|
47
|
+
end
|
48
|
+
|
42
49
|
def _root_document
|
43
50
|
@_root_document ||= _parent_document.try(:_root_document)
|
44
51
|
end
|
45
52
|
end
|
46
53
|
end
|
47
54
|
end
|
48
|
-
end
|
55
|
+
end
|
@@ -4,6 +4,8 @@ require 'set'
|
|
4
4
|
module MongoMapper
|
5
5
|
module Plugins
|
6
6
|
module IdentityMap
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
7
9
|
def self.models
|
8
10
|
@models ||= Set.new
|
9
11
|
end
|
@@ -12,8 +14,8 @@ module MongoMapper
|
|
12
14
|
models.each { |m| m.identity_map.clear }
|
13
15
|
end
|
14
16
|
|
15
|
-
|
16
|
-
IdentityMap.models <<
|
17
|
+
included do
|
18
|
+
IdentityMap.models << self
|
17
19
|
end
|
18
20
|
|
19
21
|
module ClassMethods
|
@@ -2,9 +2,11 @@
|
|
2
2
|
module MongoMapper
|
3
3
|
module Plugins
|
4
4
|
module Inspect
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
5
7
|
module InstanceMethods
|
6
8
|
def inspect
|
7
|
-
attributes_as_nice_string = key_names.collect do |name|
|
9
|
+
attributes_as_nice_string = key_names.sort.collect do |name|
|
8
10
|
"#{name}: #{self[name].inspect}"
|
9
11
|
end.join(", ")
|
10
12
|
"#<#{self.class} #{attributes_as_nice_string}>"
|
@@ -4,8 +4,11 @@ require 'mongo_mapper/plugins/keys/key'
|
|
4
4
|
module MongoMapper
|
5
5
|
module Plugins
|
6
6
|
module Keys
|
7
|
-
|
8
|
-
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
|
9
|
+
included do
|
10
|
+
extend ActiveSupport::DescendantsTracker
|
11
|
+
key :_id, ObjectId
|
9
12
|
end
|
10
13
|
|
11
14
|
module ClassMethods
|
@@ -15,7 +18,7 @@ module MongoMapper
|
|
15
18
|
end
|
16
19
|
|
17
20
|
def keys
|
18
|
-
@keys ||=
|
21
|
+
@keys ||= {}
|
19
22
|
end
|
20
23
|
|
21
24
|
def key(*args)
|
@@ -37,7 +40,7 @@ module MongoMapper
|
|
37
40
|
end
|
38
41
|
|
39
42
|
def object_id_keys
|
40
|
-
keys.keys.select { |key| keys[key].type == ObjectId }.map
|
43
|
+
keys.keys.select { |key| keys[key].type == ObjectId }.map { |k| k.to_sym }
|
41
44
|
end
|
42
45
|
|
43
46
|
def object_id_key?(name)
|
@@ -92,8 +95,8 @@ module MongoMapper
|
|
92
95
|
read_key(:#{key.name})
|
93
96
|
end
|
94
97
|
|
95
|
-
def #{key.name}
|
96
|
-
|
98
|
+
def #{key.name}_before_type_cast
|
99
|
+
read_key_before_type_cast(:#{key.name})
|
97
100
|
end
|
98
101
|
|
99
102
|
def #{key.name}=(value)
|
@@ -137,11 +140,11 @@ module MongoMapper
|
|
137
140
|
end
|
138
141
|
|
139
142
|
if key.options[:in]
|
140
|
-
validates_inclusion_of(attribute, :
|
143
|
+
validates_inclusion_of(attribute, :in => key.options[:in])
|
141
144
|
end
|
142
145
|
|
143
146
|
if key.options[:not_in]
|
144
|
-
validates_exclusion_of(attribute, :
|
147
|
+
validates_exclusion_of(attribute, :in => key.options[:not_in])
|
145
148
|
end
|
146
149
|
|
147
150
|
if key.options[:length]
|
@@ -168,6 +171,7 @@ module MongoMapper
|
|
168
171
|
def initialize_from_database(attrs={})
|
169
172
|
@_new = false
|
170
173
|
load_from_database(attrs)
|
174
|
+
default_id_value(attrs)
|
171
175
|
self
|
172
176
|
end
|
173
177
|
|
@@ -196,7 +200,7 @@ module MongoMapper
|
|
196
200
|
|
197
201
|
embedded_associations.each do |association|
|
198
202
|
if documents = instance_variable_get(association.ivar)
|
199
|
-
if association.
|
203
|
+
if association.is_a?(Associations::OneAssociation)
|
200
204
|
attrs[association.name] = documents.to_mongo
|
201
205
|
else
|
202
206
|
attrs[association.name] = documents.map { |document| document.to_mongo }
|
@@ -221,6 +225,10 @@ module MongoMapper
|
|
221
225
|
save!
|
222
226
|
end
|
223
227
|
|
228
|
+
def update_attribute(name, value)
|
229
|
+
update_attributes(name.to_sym => value)
|
230
|
+
end
|
231
|
+
|
224
232
|
def id
|
225
233
|
_id
|
226
234
|
end
|
@@ -258,6 +266,13 @@ module MongoMapper
|
|
258
266
|
keys.values.select { |key| key.embeddable? }
|
259
267
|
end
|
260
268
|
|
269
|
+
def default_id_value(attrs={})
|
270
|
+
id_provided = !attrs.nil? && attrs.keys.map { |k| k.to_s }.detect { |k| k == 'id' || k == '_id' }
|
271
|
+
if !id_provided && self.class.can_default_id?
|
272
|
+
write_key :_id, BSON::ObjectId.new
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
261
276
|
private
|
262
277
|
def load_from_database(attrs)
|
263
278
|
return if attrs.blank?
|
@@ -270,15 +285,6 @@ module MongoMapper
|
|
270
285
|
end
|
271
286
|
end
|
272
287
|
|
273
|
-
def default_id_value(attrs)
|
274
|
-
unless attrs.nil?
|
275
|
-
id_provided = attrs.keys.map { |k| k.to_s }.detect { |k| k == 'id' || k == '_id' }
|
276
|
-
if !id_provided && self.class.can_default_id?
|
277
|
-
write_key :_id, BSON::ObjectId.new
|
278
|
-
end
|
279
|
-
end
|
280
|
-
end
|
281
|
-
|
282
288
|
def ensure_key_exists(name)
|
283
289
|
self.class.key(name) unless respond_to?("#{name}=")
|
284
290
|
end
|
@@ -290,21 +296,21 @@ module MongoMapper
|
|
290
296
|
end
|
291
297
|
|
292
298
|
def read_key(key_name)
|
293
|
-
if key = keys[key_name]
|
299
|
+
if key = keys[key_name.to_s]
|
294
300
|
value = key.get(instance_variable_get(:"@#{key_name}"))
|
295
301
|
set_parent_document(key, value)
|
296
302
|
instance_variable_set(:"@#{key_name}", value)
|
297
303
|
end
|
298
304
|
end
|
299
305
|
|
300
|
-
def
|
301
|
-
instance_variable_get(:"@#{name}
|
306
|
+
def read_key_before_type_cast(name)
|
307
|
+
instance_variable_get(:"@#{name}_before_type_cast")
|
302
308
|
end
|
303
309
|
|
304
310
|
def write_key(name, value)
|
305
311
|
key = keys[name.to_s]
|
306
312
|
set_parent_document(key, value)
|
307
|
-
instance_variable_set :"@#{name}
|
313
|
+
instance_variable_set :"@#{name}_before_type_cast", value
|
308
314
|
instance_variable_set :"@#{name}", key.set(value)
|
309
315
|
end
|
310
316
|
end
|
@@ -22,11 +22,11 @@ module MongoMapper
|
|
22
22
|
end
|
23
23
|
|
24
24
|
def can_default_id?
|
25
|
-
type &&
|
25
|
+
type && (type == ObjectId || type == BSON::ObjectId || type == String)
|
26
26
|
end
|
27
27
|
|
28
28
|
def number?
|
29
|
-
|
29
|
+
type == Integer || type == Float
|
30
30
|
end
|
31
31
|
|
32
32
|
def get(value)
|
@@ -34,11 +34,17 @@ module MongoMapper
|
|
34
34
|
if default_value.respond_to?(:call)
|
35
35
|
return default_value.call
|
36
36
|
else
|
37
|
-
|
37
|
+
# Using Marshal is easiest way to get a copy of mutable objects
|
38
|
+
# without getting an error on immutable objects
|
39
|
+
return Marshal.load(Marshal.dump(default_value))
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
|
43
|
+
if options[:typecast].present?
|
44
|
+
type.from_mongo(value).map! { |v| typecast_class.from_mongo(v) }
|
45
|
+
else
|
46
|
+
type.from_mongo(value)
|
47
|
+
end
|
42
48
|
end
|
43
49
|
|
44
50
|
def set(value)
|
@@ -48,7 +54,7 @@ module MongoMapper
|
|
48
54
|
end
|
49
55
|
end
|
50
56
|
end
|
51
|
-
|
57
|
+
|
52
58
|
private
|
53
59
|
def typecast_class
|
54
60
|
@typecast_class ||= options[:typecast].constantize
|
@@ -56,4 +62,4 @@ module MongoMapper
|
|
56
62
|
end
|
57
63
|
end
|
58
64
|
end
|
59
|
-
end
|
65
|
+
end
|
@@ -2,6 +2,8 @@
|
|
2
2
|
module MongoMapper
|
3
3
|
module Plugins
|
4
4
|
module Modifiers
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
5
7
|
module ClassMethods
|
6
8
|
def increment(*args)
|
7
9
|
modifier_update('$inc', args)
|
@@ -17,7 +19,7 @@ module MongoMapper
|
|
17
19
|
def set(*args)
|
18
20
|
criteria, updates = criteria_and_keys_from_args(args)
|
19
21
|
updates.each do |key, value|
|
20
|
-
updates[key] = keys[key].set(value) if key?(key)
|
22
|
+
updates[key] = keys[key.to_s].set(value) if key?(key)
|
21
23
|
end
|
22
24
|
collection.update(criteria, {'$set' => updates}, :multi => true)
|
23
25
|
end
|
@@ -5,6 +5,8 @@ require 'mongo_mapper/plugins/querying/plucky_methods'
|
|
5
5
|
module MongoMapper
|
6
6
|
module Plugins
|
7
7
|
module Querying
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
8
10
|
module ClassMethods
|
9
11
|
include PluckyMethods
|
10
12
|
|
@@ -50,7 +52,7 @@ module MongoMapper
|
|
50
52
|
end
|
51
53
|
|
52
54
|
def destroy(*ids)
|
53
|
-
find_some!(ids.flatten).each
|
55
|
+
find_some!(ids.flatten).each { |doc| doc.destroy }
|
54
56
|
end
|
55
57
|
|
56
58
|
def destroy_all(options={})
|
@@ -148,13 +150,12 @@ module MongoMapper
|
|
148
150
|
end
|
149
151
|
|
150
152
|
def delete
|
151
|
-
@_destroyed = true
|
152
|
-
self.class.delete(id) unless new?
|
153
|
+
self.class.delete(id).tap { @_destroyed = true } if persisted?
|
153
154
|
end
|
154
155
|
|
155
156
|
private
|
156
157
|
def create_or_update(options={})
|
157
|
-
result =
|
158
|
+
result = persisted? ? update(options) : create(options)
|
158
159
|
result != false
|
159
160
|
end
|
160
161
|
|