mongo_mapper 0.10.1 → 0.11.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 +3 -0
- data/examples/plugins.rb +2 -5
- data/lib/mongo_mapper.rb +1 -0
- data/lib/mongo_mapper/connection.rb +4 -0
- data/lib/mongo_mapper/embedded_document.rb +1 -0
- data/lib/mongo_mapper/extensions/object.rb +5 -6
- data/lib/mongo_mapper/plugins/accessible.rb +14 -16
- data/lib/mongo_mapper/plugins/associations.rb +21 -23
- data/lib/mongo_mapper/plugins/associations/base.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/belongs_to_association.rb +4 -0
- data/lib/mongo_mapper/plugins/associations/many_association.rb +0 -4
- data/lib/mongo_mapper/plugins/associations/one_association.rb +1 -1
- data/lib/mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy.rb +30 -0
- data/lib/mongo_mapper/plugins/caching.rb +11 -13
- data/lib/mongo_mapper/plugins/callbacks.rb +12 -14
- data/lib/mongo_mapper/plugins/clone.rb +11 -13
- data/lib/mongo_mapper/plugins/dirty.rb +36 -38
- data/lib/mongo_mapper/plugins/document.rb +20 -22
- data/lib/mongo_mapper/plugins/embedded_callbacks.rb +11 -13
- data/lib/mongo_mapper/plugins/embedded_document.rb +22 -24
- data/lib/mongo_mapper/plugins/equality.rb +6 -8
- data/lib/mongo_mapper/plugins/identity_map.rb +11 -13
- data/lib/mongo_mapper/plugins/inspect.rb +6 -8
- data/lib/mongo_mapper/plugins/keys.rb +109 -110
- data/lib/mongo_mapper/plugins/logger.rb +2 -4
- data/lib/mongo_mapper/plugins/modifiers.rb +32 -34
- data/lib/mongo_mapper/plugins/persistence.rb +5 -7
- data/lib/mongo_mapper/plugins/protected.rb +14 -16
- data/lib/mongo_mapper/plugins/querying.rb +29 -31
- data/lib/mongo_mapper/plugins/rails.rb +28 -22
- data/lib/mongo_mapper/plugins/rails/active_record_association_adapter.rb +33 -0
- data/lib/mongo_mapper/plugins/safe.rb +3 -5
- data/lib/mongo_mapper/plugins/sci.rb +3 -5
- data/lib/mongo_mapper/plugins/serialization.rb +49 -52
- data/lib/mongo_mapper/plugins/timestamps.rb +4 -6
- data/lib/mongo_mapper/plugins/validations.rb +8 -10
- data/lib/mongo_mapper/railtie/database.rake +1 -1
- data/lib/mongo_mapper/version.rb +1 -1
- data/lib/rails/generators/mongo_mapper/model/model_generator.rb +1 -1
- data/lib/rails/generators/mongo_mapper/model/templates/model.rb +2 -0
- data/test/functional/associations/test_many_embedded_polymorphic_proxy.rb +63 -0
- data/test/functional/associations/test_one_embedded_polymorphic_proxy.rb +208 -0
- data/test/functional/test_accessible.rb +5 -0
- data/test/functional/test_embedded_document.rb +12 -0
- data/test/functional/test_modifiers.rb +19 -19
- data/test/functional/test_protected.rb +10 -0
- data/test/functional/test_querying.rb +15 -1
- data/test/functional/test_validations.rb +33 -0
- data/test/models.rb +14 -0
- data/test/unit/associations/test_one_association.rb +11 -0
- data/test/unit/test_mongo_mapper.rb +9 -0
- data/test/unit/test_plugins.rb +2 -4
- data/test/unit/test_rails_reflect_on_association.rb +118 -0
- metadata +15 -11
data/UPGRADES
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
0.10 => 0.11
|
2
|
+
* #update_attribute now ignores attr_accessible and attr_protected
|
3
|
+
|
1
4
|
0.9 => 0.10
|
2
5
|
* Using String IDs are no longer supported. If you are declaring your own ID, ensure it is an ObjectId, and set the default
|
3
6
|
key :_id, ObjectId, :default => lambda { BSON::ObjectId.new }
|
data/examples/plugins.rb
CHANGED
@@ -16,11 +16,8 @@ module FooPlugin
|
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
|
-
|
20
|
-
|
21
|
-
def foo
|
22
|
-
'Foo instance method!'
|
23
|
-
end
|
19
|
+
def foo
|
20
|
+
'Foo instance method!'
|
24
21
|
end
|
25
22
|
|
26
23
|
# Any configuration can be done in the #included block, which gets
|
data/lib/mongo_mapper.rb
CHANGED
@@ -75,6 +75,7 @@ module MongoMapper
|
|
75
75
|
autoload :OneProxy, 'mongo_mapper/plugins/associations/one_proxy'
|
76
76
|
autoload :OneAsProxy, 'mongo_mapper/plugins/associations/one_as_proxy'
|
77
77
|
autoload :OneEmbeddedProxy, 'mongo_mapper/plugins/associations/one_embedded_proxy'
|
78
|
+
autoload :OneEmbeddedPolymorphicProxy, 'mongo_mapper/plugins/associations/one_embedded_polymorphic_proxy'
|
78
79
|
autoload :InArrayProxy, 'mongo_mapper/plugins/associations/in_array_proxy'
|
79
80
|
end
|
80
81
|
end
|
@@ -62,6 +62,10 @@ module MongoMapper
|
|
62
62
|
raise 'Set config before connecting. MongoMapper.config = {...}' if config.blank?
|
63
63
|
env = config_for_environment(environment)
|
64
64
|
|
65
|
+
if env['options'].is_a? Hash
|
66
|
+
options = env['options'].symbolize_keys.merge(options)
|
67
|
+
end
|
68
|
+
|
65
69
|
MongoMapper.connection = if env['hosts']
|
66
70
|
Mongo::ReplSetConnection.new( *env['hosts'].push(options) )
|
67
71
|
else
|
@@ -2,6 +2,8 @@
|
|
2
2
|
module MongoMapper
|
3
3
|
module Extensions
|
4
4
|
module Object
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
5
7
|
module ClassMethods
|
6
8
|
def to_mongo(value)
|
7
9
|
value
|
@@ -12,16 +14,13 @@ module MongoMapper
|
|
12
14
|
end
|
13
15
|
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
-
self.class.to_mongo(self)
|
18
|
-
end
|
17
|
+
def to_mongo
|
18
|
+
self.class.to_mongo(self)
|
19
19
|
end
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
24
24
|
class Object
|
25
|
-
|
26
|
-
include MongoMapper::Extensions::Object::InstanceMethods
|
25
|
+
include MongoMapper::Extensions::Object
|
27
26
|
end
|
@@ -14,25 +14,23 @@ module MongoMapper
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def update_attributes(attrs={})
|
23
|
-
super(filter_inaccessible_attrs(attrs))
|
24
|
-
end
|
17
|
+
def attributes=(attrs={})
|
18
|
+
super(filter_inaccessible_attrs(attrs))
|
19
|
+
end
|
25
20
|
|
26
|
-
|
27
|
-
|
28
|
-
|
21
|
+
def update_attributes(attrs={})
|
22
|
+
super(filter_inaccessible_attrs(attrs))
|
23
|
+
end
|
29
24
|
|
30
|
-
|
31
|
-
|
32
|
-
return attrs if !accessible_attributes? || attrs.blank?
|
33
|
-
attrs.dup.delete_if { |key, val| !accessible_attributes.include?(key.to_sym) }
|
34
|
-
end
|
25
|
+
def update_attributes!(attrs={})
|
26
|
+
super(filter_inaccessible_attrs(attrs))
|
35
27
|
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
def filter_inaccessible_attrs(attrs)
|
31
|
+
return attrs if !accessible_attributes? || attrs.blank?
|
32
|
+
attrs.dup.delete_if { |key, val| !accessible_attributes.include?(key.to_sym) }
|
33
|
+
end
|
36
34
|
end
|
37
35
|
end
|
38
36
|
end
|
@@ -56,35 +56,33 @@ module MongoMapper
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
end
|
59
|
+
def associations
|
60
|
+
self.class.associations
|
61
|
+
end
|
63
62
|
|
64
|
-
|
65
|
-
|
66
|
-
|
63
|
+
def embedded_associations
|
64
|
+
associations.values.select { |assoc| assoc.embeddable? }
|
65
|
+
end
|
67
66
|
|
68
|
-
|
69
|
-
|
70
|
-
|
67
|
+
def build_proxy(association)
|
68
|
+
proxy = association.proxy_class.new(self, association)
|
69
|
+
self.instance_variable_set(association.ivar, proxy)
|
71
70
|
|
72
|
-
|
73
|
-
|
71
|
+
proxy
|
72
|
+
end
|
74
73
|
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
end
|
79
|
-
proxy
|
74
|
+
def get_proxy(association)
|
75
|
+
unless proxy = self.instance_variable_get(association.ivar)
|
76
|
+
proxy = build_proxy(association)
|
80
77
|
end
|
78
|
+
proxy
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
end
|
81
|
+
def save_to_collection(options={})
|
82
|
+
super if defined?(super)
|
83
|
+
associations.each do |association_name, association|
|
84
|
+
proxy = get_proxy(association)
|
85
|
+
proxy.save_to_collection(options) if proxy.proxy_respond_to?(:save_to_collection) && association.autosave?
|
88
86
|
end
|
89
87
|
end
|
90
88
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
module MongoMapper
|
3
|
+
module Plugins
|
4
|
+
module Associations
|
5
|
+
class OneEmbeddedPolymorphicProxy < OneEmbeddedProxy
|
6
|
+
def replace(value)
|
7
|
+
@value = value.respond_to?(:attributes) ? value.attributes.merge(association.type_key_name => value.class.name) : value
|
8
|
+
reset
|
9
|
+
end
|
10
|
+
|
11
|
+
protected
|
12
|
+
def find_target
|
13
|
+
if @value
|
14
|
+
child = polymorphic_class(@value).load(@value)
|
15
|
+
assign_references(child)
|
16
|
+
child
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def polymorphic_class(doc)
|
21
|
+
if class_name = doc[association.type_key_name]
|
22
|
+
class_name.constantize
|
23
|
+
else
|
24
|
+
klass
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -4,19 +4,17 @@ module MongoMapper
|
|
4
4
|
module Caching
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
cache_key
|
19
|
-
end
|
7
|
+
def cache_key(*suffixes)
|
8
|
+
cache_key = case
|
9
|
+
when !persisted?
|
10
|
+
"#{self.class.name}/new"
|
11
|
+
when timestamp = self[:updated_at]
|
12
|
+
"#{self.class.name}/#{id}-#{timestamp.to_s(:number)}"
|
13
|
+
else
|
14
|
+
"#{self.class.name}/#{id}"
|
15
|
+
end
|
16
|
+
cache_key += "/#{suffixes.join('/')}" unless suffixes.empty?
|
17
|
+
cache_key
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -4,23 +4,21 @@ module MongoMapper
|
|
4
4
|
module Callbacks
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
end
|
7
|
+
def destroy
|
8
|
+
run_callbacks(:destroy) { super }
|
9
|
+
end
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
11
|
+
private
|
12
|
+
def create_or_update(*)
|
13
|
+
run_callbacks(:save) { super }
|
14
|
+
end
|
16
15
|
|
17
|
-
|
18
|
-
|
19
|
-
|
16
|
+
def create(*)
|
17
|
+
run_callbacks(:create) { super }
|
18
|
+
end
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
end
|
20
|
+
def update(*)
|
21
|
+
run_callbacks(:update) { super }
|
24
22
|
end
|
25
23
|
end
|
26
24
|
end
|
@@ -4,19 +4,17 @@ module MongoMapper
|
|
4
4
|
module Clone
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
hash
|
19
|
-
end
|
7
|
+
def initialize_copy(other)
|
8
|
+
@_new = true
|
9
|
+
@_destroyed = false
|
10
|
+
@_id = nil
|
11
|
+
associations.each do |name, association|
|
12
|
+
instance_variable_set(association.ivar, nil)
|
13
|
+
end
|
14
|
+
self.attributes = other.attributes.clone.except(:_id).inject({}) do |hash, entry|
|
15
|
+
key, value = entry
|
16
|
+
hash[key] = value.duplicable? ? value.clone : value
|
17
|
+
hash
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|
@@ -6,56 +6,54 @@ module MongoMapper
|
|
6
6
|
|
7
7
|
include ::ActiveModel::Dirty
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
end
|
9
|
+
def initialize(*)
|
10
|
+
# never register initial id assignment as a change
|
11
|
+
super.tap { changed_attributes.delete('_id') }
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
def initialize_from_database(*)
|
15
|
+
super.tap { changed_attributes.clear }
|
16
|
+
end
|
18
17
|
|
19
|
-
|
20
|
-
|
21
|
-
|
18
|
+
def save(*)
|
19
|
+
clear_changes { super }
|
20
|
+
end
|
22
21
|
|
23
|
-
|
24
|
-
|
25
|
-
|
22
|
+
def reload(*)
|
23
|
+
super.tap { clear_changes }
|
24
|
+
end
|
26
25
|
|
27
|
-
|
26
|
+
protected
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
28
|
+
def attribute_method?(attr)
|
29
|
+
# This overrides ::ActiveSupport::Dirty#attribute_method? to allow attributes to be any key
|
30
|
+
# in the attributes hash ( default ) or any key defined on the model that may not yet have
|
31
|
+
# had a value stored in the attributes collection.
|
32
|
+
super || key_names.include?(attr)
|
33
|
+
end
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
end
|
35
|
+
def clear_changes
|
36
|
+
previous = changes
|
37
|
+
(block_given? ? yield : true).tap do |result|
|
38
|
+
unless result == false #failed validation; nil is OK.
|
39
|
+
@previously_changed = previous
|
40
|
+
changed_attributes.clear
|
43
41
|
end
|
44
42
|
end
|
43
|
+
end
|
45
44
|
|
46
|
-
|
45
|
+
private
|
47
46
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
47
|
+
def write_key(key, value)
|
48
|
+
key = key.to_s
|
49
|
+
attribute_will_change!(key) unless attribute_changed?(key)
|
50
|
+
super(key, value).tap do
|
51
|
+
changed_attributes.delete(key) unless attribute_value_changed?(key)
|
54
52
|
end
|
53
|
+
end
|
55
54
|
|
56
|
-
|
57
|
-
|
58
|
-
end
|
55
|
+
def attribute_value_changed?(key_name)
|
56
|
+
attribute_was(key_name) != read_key(key_name)
|
59
57
|
end
|
60
58
|
end
|
61
59
|
end
|
@@ -10,34 +10,32 @@ module MongoMapper
|
|
10
10
|
end
|
11
11
|
end
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
end
|
13
|
+
def new?
|
14
|
+
@_new
|
15
|
+
end
|
17
16
|
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
def destroyed?
|
18
|
+
@_destroyed == true
|
19
|
+
end
|
21
20
|
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
27
|
-
instance_variables.each { |ivar| instance_variable_set(ivar, nil) }
|
28
|
-
load_from_database(doc)
|
29
|
-
self
|
30
|
-
else
|
31
|
-
raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
|
21
|
+
def reload
|
22
|
+
if doc = collection.find_one(:_id => id)
|
23
|
+
self.class.associations.each_value do |association|
|
24
|
+
get_proxy(association).reset
|
32
25
|
end
|
33
|
-
|
34
|
-
|
35
|
-
# Used by embedded docs to find root easily without if/respond_to? stuff.
|
36
|
-
# Documents are always root documents.
|
37
|
-
def _root_document
|
26
|
+
instance_variables.each { |ivar| instance_variable_set(ivar, nil) }
|
27
|
+
load_from_database(doc)
|
38
28
|
self
|
29
|
+
else
|
30
|
+
raise DocumentNotFound, "Document match #{_id.inspect} does not exist in #{collection.name} collection"
|
39
31
|
end
|
40
32
|
end
|
33
|
+
|
34
|
+
# Used by embedded docs to find root easily without if/respond_to? stuff.
|
35
|
+
# Documents are always root documents.
|
36
|
+
def _root_document
|
37
|
+
self
|
38
|
+
end
|
41
39
|
end
|
42
40
|
end
|
43
41
|
end
|