mongo_mapper-unstable 2010.1.22 → 2010.1.25
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/VERSION +1 -1
- data/lib/mongo_mapper/document.rb +12 -4
- data/lib/mongo_mapper/plugins.rb +3 -8
- data/lib/mongo_mapper/plugins/callbacks.rb +15 -15
- data/lib/mongo_mapper/plugins/equality.rb +12 -0
- data/lib/mongo_mapper/plugins/identity_map.rb +65 -33
- data/lib/mongo_mapper/plugins/keys.rb +4 -4
- data/lib/mongo_mapper/plugins/serialization.rb +4 -8
- data/lib/mongo_mapper/plugins/validations.rb +2 -4
- data/test/functional/associations/test_belongs_to_proxy.rb +8 -0
- data/test/functional/associations/test_one_proxy.rb +12 -0
- data/test/functional/test_document.rb +53 -0
- data/test/functional/test_identity_map.rb +166 -69
- data/test/unit/associations/test_proxy.rb +5 -3
- data/test/unit/test_document.rb +28 -0
- data/test/unit/test_embedded_document.rb +24 -0
- data/test/unit/test_plugins.rb +12 -4
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2010.01.
|
1
|
+
2010.01.25
|
@@ -90,6 +90,13 @@ module MongoMapper
|
|
90
90
|
collection.find(to_criteria(options)).count
|
91
91
|
end
|
92
92
|
|
93
|
+
def find_each(options={})
|
94
|
+
criteria, options = to_finder_options(options)
|
95
|
+
collection.find(criteria, options).each do |doc|
|
96
|
+
yield load(doc)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
93
100
|
def exists?(options={})
|
94
101
|
!count(options).zero?
|
95
102
|
end
|
@@ -343,13 +350,14 @@ module MongoMapper
|
|
343
350
|
end
|
344
351
|
|
345
352
|
def save(options={})
|
353
|
+
options.assert_valid_keys(:validate, :safe)
|
346
354
|
options.reverse_merge!(:validate => true)
|
347
|
-
|
348
|
-
!perform_validations || valid? ? create_or_update(options) : false
|
355
|
+
!options[:validate] || valid? ? create_or_update(options) : false
|
349
356
|
end
|
350
357
|
|
351
|
-
def save!
|
352
|
-
|
358
|
+
def save!(options={})
|
359
|
+
options.assert_valid_keys(:safe)
|
360
|
+
save(options) || raise(DocumentNotValid.new(self))
|
353
361
|
end
|
354
362
|
|
355
363
|
def update_attributes(attrs={})
|
data/lib/mongo_mapper/plugins.rb
CHANGED
@@ -5,14 +5,9 @@ module MongoMapper
|
|
5
5
|
end
|
6
6
|
|
7
7
|
def plugin(mod)
|
8
|
-
if mod.const_defined?(:ClassMethods)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
if mod.const_defined?(:InstanceMethods)
|
13
|
-
include mod::InstanceMethods
|
14
|
-
end
|
15
|
-
|
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)
|
16
11
|
plugins << mod
|
17
12
|
end
|
18
13
|
end
|
@@ -1,23 +1,23 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
module Plugins
|
3
3
|
module Callbacks
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
include ActiveSupport::Callbacks
|
4
|
+
def self.configure(model)
|
5
|
+
model.class_eval do
|
6
|
+
include ActiveSupport::Callbacks
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
end
|
8
|
+
define_callbacks(
|
9
|
+
:before_save, :after_save,
|
10
|
+
:before_create, :after_create,
|
11
|
+
:before_update, :after_update,
|
12
|
+
:before_validation, :after_validation,
|
13
|
+
:before_validation_on_create, :after_validation_on_create,
|
14
|
+
:before_validation_on_update, :after_validation_on_update,
|
15
|
+
:before_destroy, :after_destroy
|
16
|
+
)
|
19
17
|
end
|
20
|
-
|
18
|
+
end
|
19
|
+
|
20
|
+
module InstanceMethods
|
21
21
|
def valid?
|
22
22
|
action = new? ? 'create' : 'update'
|
23
23
|
|
@@ -5,6 +5,18 @@ module MongoMapper
|
|
5
5
|
def ==(other)
|
6
6
|
other.is_a?(self.class) && _id == other._id
|
7
7
|
end
|
8
|
+
|
9
|
+
def eql?(other)
|
10
|
+
self == other
|
11
|
+
end
|
12
|
+
|
13
|
+
def equal?(other)
|
14
|
+
object_id === other.object_id
|
15
|
+
end
|
16
|
+
|
17
|
+
def hash
|
18
|
+
_id.hash
|
19
|
+
end
|
8
20
|
end
|
9
21
|
end
|
10
22
|
end
|
@@ -1,40 +1,40 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
module Plugins
|
3
3
|
module IdentityMap
|
4
|
-
def self.
|
5
|
-
|
4
|
+
def self.models
|
5
|
+
@models ||= Set.new
|
6
6
|
end
|
7
|
-
|
8
|
-
def self.
|
9
|
-
|
7
|
+
|
8
|
+
def self.clear
|
9
|
+
models.each { |m| m.identity_map.clear }
|
10
10
|
end
|
11
11
|
|
12
|
+
def self.configure(model)
|
13
|
+
IdentityMap.models << model
|
14
|
+
end
|
15
|
+
|
12
16
|
module ClassMethods
|
13
|
-
def
|
14
|
-
|
17
|
+
def inherited(descendant)
|
18
|
+
descendant.identity_map = identity_map
|
19
|
+
super
|
15
20
|
end
|
16
21
|
|
17
|
-
def identity_map
|
18
|
-
|
22
|
+
def identity_map
|
23
|
+
@identity_map ||= {}
|
19
24
|
end
|
20
25
|
|
21
|
-
def
|
22
|
-
|
26
|
+
def identity_map=(v)
|
27
|
+
@identity_map = v
|
23
28
|
end
|
24
29
|
|
25
30
|
def find_one(options={})
|
26
|
-
criteria, finder_options
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
if find_by_single_id && document_in_map
|
32
|
-
document_in_map
|
33
|
-
elsif find_by_single_id_with_sci && document_in_map
|
34
|
-
document_in_map
|
31
|
+
criteria, finder_options = to_finder_options(options)
|
32
|
+
|
33
|
+
if simple_find?(criteria) && identity_map.key?(criteria[:_id])
|
34
|
+
identity_map[criteria[:_id]]
|
35
35
|
else
|
36
36
|
super.tap do |document|
|
37
|
-
remove_documents_from_map(document)
|
37
|
+
remove_documents_from_map(document) if selecting_fields?(finder_options)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
end
|
@@ -42,46 +42,78 @@ module MongoMapper
|
|
42
42
|
def find_many(options)
|
43
43
|
criteria, finder_options = to_finder_options(options)
|
44
44
|
super.tap do |documents|
|
45
|
-
remove_documents_from_map(documents)
|
45
|
+
remove_documents_from_map(documents) if selecting_fields?(finder_options)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
|
49
49
|
def load(attrs)
|
50
|
-
|
51
|
-
|
50
|
+
document = identity_map[attrs['_id']]
|
51
|
+
|
52
|
+
if document.nil? || identity_map_off?
|
52
53
|
document = super
|
53
|
-
identity_map[document.
|
54
|
+
identity_map[document._id] = document if identity_map_on?
|
54
55
|
end
|
55
56
|
|
56
57
|
document
|
57
58
|
end
|
58
|
-
|
59
|
+
|
60
|
+
def identity_map_status
|
61
|
+
defined?(@identity_map_status) ? @identity_map_status : true
|
62
|
+
end
|
63
|
+
|
64
|
+
def identity_map_on
|
65
|
+
@identity_map_status = true
|
66
|
+
end
|
67
|
+
|
68
|
+
def identity_map_off
|
69
|
+
@identity_map_status = false
|
70
|
+
end
|
71
|
+
|
72
|
+
def identity_map_on?
|
73
|
+
identity_map_status
|
74
|
+
end
|
75
|
+
|
76
|
+
def identity_map_off?
|
77
|
+
!identity_map_on?
|
78
|
+
end
|
79
|
+
|
80
|
+
def without_identity_map(&block)
|
81
|
+
identity_map_off
|
82
|
+
yield
|
83
|
+
ensure
|
84
|
+
identity_map_on
|
85
|
+
end
|
86
|
+
|
59
87
|
private
|
60
88
|
def remove_documents_from_map(*documents)
|
61
89
|
documents.flatten.compact.each do |document|
|
62
|
-
identity_map.delete(
|
90
|
+
identity_map.delete(document._id)
|
63
91
|
end
|
64
92
|
end
|
93
|
+
|
94
|
+
def simple_find?(criteria)
|
95
|
+
criteria.keys == [:_id] || criteria.keys.to_set == [:_id, :_type].to_set
|
96
|
+
end
|
97
|
+
|
98
|
+
def selecting_fields?(options)
|
99
|
+
!options[:fields].nil?
|
100
|
+
end
|
65
101
|
end
|
66
102
|
|
67
103
|
module InstanceMethods
|
68
|
-
def identity_map_key
|
69
|
-
@identity_map_key ||= self.class.identity_map_key(_id)
|
70
|
-
end
|
71
|
-
|
72
104
|
def identity_map
|
73
105
|
self.class.identity_map
|
74
106
|
end
|
75
107
|
|
76
108
|
def save(*args)
|
77
109
|
if result = super
|
78
|
-
identity_map[
|
110
|
+
identity_map[_id] = self if self.class.identity_map_on?
|
79
111
|
end
|
80
112
|
result
|
81
113
|
end
|
82
114
|
|
83
115
|
def delete
|
84
|
-
identity_map.delete(
|
116
|
+
identity_map.delete(_id) if self.class.identity_map_on?
|
85
117
|
super
|
86
118
|
end
|
87
119
|
end
|
@@ -1,6 +1,10 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
module Plugins
|
3
3
|
module Keys
|
4
|
+
def self.configure(model)
|
5
|
+
model.key :_id, ObjectId
|
6
|
+
end
|
7
|
+
|
4
8
|
module ClassMethods
|
5
9
|
def inherited(descendant)
|
6
10
|
descendant.instance_variable_set(:@keys, keys.dup)
|
@@ -133,10 +137,6 @@ module MongoMapper
|
|
133
137
|
end
|
134
138
|
|
135
139
|
module InstanceMethods
|
136
|
-
def self.included(model)
|
137
|
-
model.key :_id, ObjectId
|
138
|
-
end
|
139
|
-
|
140
140
|
def initialize(attrs={}, from_db=false)
|
141
141
|
unless attrs.nil?
|
142
142
|
provided_keys = attrs.keys.map { |k| k.to_s }
|
@@ -3,6 +3,10 @@ require 'active_support/json'
|
|
3
3
|
module MongoMapper
|
4
4
|
module Plugins
|
5
5
|
module Serialization
|
6
|
+
def self.configure(model)
|
7
|
+
model.class_eval { include Json }
|
8
|
+
end
|
9
|
+
|
6
10
|
class Serializer
|
7
11
|
attr_reader :options
|
8
12
|
|
@@ -96,14 +100,6 @@ module MongoMapper
|
|
96
100
|
options[:except] = except
|
97
101
|
end
|
98
102
|
end
|
99
|
-
|
100
|
-
module InstanceMethods
|
101
|
-
def self.included(model)
|
102
|
-
model.class_eval do
|
103
|
-
include Json
|
104
|
-
end
|
105
|
-
end
|
106
|
-
end
|
107
103
|
end
|
108
104
|
end
|
109
105
|
end
|
@@ -1,10 +1,8 @@
|
|
1
1
|
module MongoMapper
|
2
2
|
module Plugins
|
3
3
|
module Validations
|
4
|
-
|
5
|
-
|
6
|
-
model.class_eval { include Validatable }
|
7
|
-
end
|
4
|
+
def self.configure(model)
|
5
|
+
model.class_eval { include Validatable }
|
8
6
|
end
|
9
7
|
|
10
8
|
module DocumentMacros
|
@@ -15,6 +15,14 @@ class BelongsToProxyTest < Test::Unit::TestCase
|
|
15
15
|
@comment_class.new.post.nil?.should be_true
|
16
16
|
end
|
17
17
|
|
18
|
+
should "send object id to target" do
|
19
|
+
post = @post_class.new(:name => 'mongomapper')
|
20
|
+
comment = @comment_class.new(:name => 'Foo!', :post => post)
|
21
|
+
comment.save
|
22
|
+
|
23
|
+
comment.post.object_id.should == comment.post.target.object_id
|
24
|
+
end
|
25
|
+
|
18
26
|
should "have boolean presence method" do
|
19
27
|
comment = @comment_class.new(:name => 'Foo!')
|
20
28
|
comment.post?.should be_false
|
@@ -13,6 +13,18 @@ class OneProxyTest < Test::Unit::TestCase
|
|
13
13
|
@post_class.new.author.nil?.should be_true
|
14
14
|
end
|
15
15
|
|
16
|
+
should "send object id to target" do
|
17
|
+
@post_class.one :author, :class => @author_class
|
18
|
+
|
19
|
+
post = @post_class.new
|
20
|
+
author = @author_class.new(:name => 'Frank')
|
21
|
+
post.author = author
|
22
|
+
author.save.should be_true
|
23
|
+
post.save.should be_true
|
24
|
+
|
25
|
+
post.author.object_id.should == post.author.target.object_id
|
26
|
+
end
|
27
|
+
|
16
28
|
should "be able to replace the association" do
|
17
29
|
@post_class.one :author, :class => @author_class
|
18
30
|
|
@@ -338,6 +338,18 @@ class DocumentTest < Test::Unit::TestCase
|
|
338
338
|
end
|
339
339
|
end
|
340
340
|
|
341
|
+
context "#find_each" do
|
342
|
+
should "yield all documents found, based on criteria" do
|
343
|
+
yield_documents = []
|
344
|
+
@document.find_each(:order => "first_name") {|doc| yield_documents << doc }
|
345
|
+
yield_documents.should == [@doc1, @doc3, @doc2]
|
346
|
+
|
347
|
+
yield_documents = []
|
348
|
+
@document.find_each(:last_name => 'Nunemaker', :order => 'age desc') {|doc| yield_documents << doc }
|
349
|
+
yield_documents.should == [@doc1, @doc3]
|
350
|
+
end
|
351
|
+
end
|
352
|
+
|
341
353
|
context "dynamic finders" do
|
342
354
|
should "find document based on all arguments" do
|
343
355
|
@document.find_by_first_name_and_last_name_and_age('John', 'Nunemaker', 27).should == @doc1
|
@@ -751,6 +763,47 @@ class DocumentTest < Test::Unit::TestCase
|
|
751
763
|
@document.new(:name => 'John').save(:safe => true)
|
752
764
|
end
|
753
765
|
end
|
766
|
+
|
767
|
+
should "raise argument error if options has unsupported key" do
|
768
|
+
doc = @document.new
|
769
|
+
assert_raises(ArgumentError) { doc.save(:foo => true) }
|
770
|
+
end
|
771
|
+
end
|
772
|
+
|
773
|
+
context "#save! (with options)" do
|
774
|
+
setup do
|
775
|
+
MongoMapper.ensured_indexes = []
|
776
|
+
|
777
|
+
@document = Doc do
|
778
|
+
key :name, String
|
779
|
+
set_collection_name 'test_indexes'
|
780
|
+
ensure_index :name, :unique => true
|
781
|
+
end
|
782
|
+
|
783
|
+
if @document.database.collection_names.include?(@document.collection.name)
|
784
|
+
@document.collection.drop_indexes
|
785
|
+
end
|
786
|
+
|
787
|
+
MongoMapper.ensure_indexes!
|
788
|
+
end
|
789
|
+
|
790
|
+
should "allow passing safe" do
|
791
|
+
doc = @document.create(:name => 'John')
|
792
|
+
|
793
|
+
assert_raises(Mongo::OperationFailure) do
|
794
|
+
@document.new(:name => 'John').save!(:safe => true)
|
795
|
+
end
|
796
|
+
end
|
797
|
+
|
798
|
+
should "raise argument error if options has unsupported key" do
|
799
|
+
doc = @document.new
|
800
|
+
assert_raises(ArgumentError) { doc.save!(:foo => true) }
|
801
|
+
end
|
802
|
+
|
803
|
+
should "raise argument error if using validate as that would be pointless with save!" do
|
804
|
+
doc = @document.new
|
805
|
+
assert_raises(ArgumentError) { doc.save!(:validate => false) }
|
806
|
+
end
|
754
807
|
end
|
755
808
|
|
756
809
|
context "#destroy" do
|
@@ -1,34 +1,40 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
class IdentityMapTest < Test::Unit::TestCase
|
4
|
-
def assert_in_map(
|
5
|
-
|
6
|
-
|
7
|
-
|
4
|
+
def assert_in_map(*resources)
|
5
|
+
[resources].flatten.each do |resource|
|
6
|
+
resource.identity_map.keys.should include(resource._id)
|
7
|
+
mapped_resource = resource.identity_map[resource._id]
|
8
|
+
resource.should equal(mapped_resource)
|
9
|
+
end
|
8
10
|
end
|
9
|
-
|
10
|
-
def assert_not_in_map(
|
11
|
-
|
11
|
+
|
12
|
+
def assert_not_in_map(*resources)
|
13
|
+
[resources].flatten.each do |resource|
|
14
|
+
resource.identity_map.keys.should_not include(resource._id)
|
15
|
+
end
|
12
16
|
end
|
13
|
-
|
17
|
+
|
14
18
|
def expect_no_queries
|
15
19
|
Mongo::Collection.any_instance.expects(:find_one).never
|
16
20
|
Mongo::Collection.any_instance.expects(:find).never
|
17
21
|
end
|
18
|
-
|
22
|
+
|
19
23
|
def expects_one_query
|
20
24
|
Mongo::Collection.any_instance.expects(:find_one).once.returns({})
|
21
25
|
end
|
22
|
-
|
26
|
+
|
23
27
|
context "Document" do
|
24
28
|
setup do
|
29
|
+
MongoMapper::Plugins::IdentityMap.models.clear
|
30
|
+
|
25
31
|
@person_class = Doc('Person') do
|
26
32
|
set_collection_name 'people'
|
27
33
|
plugin MongoMapper::Plugins::IdentityMap
|
28
34
|
|
29
35
|
key :name, String
|
30
36
|
end
|
31
|
-
|
37
|
+
|
32
38
|
@post_class = Doc('Post') do
|
33
39
|
set_collection_name 'posts'
|
34
40
|
plugin MongoMapper::Plugins::IdentityMap
|
@@ -36,35 +42,62 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
36
42
|
key :title, String
|
37
43
|
key :person_id, ObjectId
|
38
44
|
end
|
39
|
-
|
45
|
+
|
40
46
|
@post_class.belongs_to :person, :class => @person_class
|
41
47
|
@person_class.many :posts, :class => @post_class
|
42
|
-
|
43
|
-
@
|
44
|
-
@
|
48
|
+
|
49
|
+
@post_class.identity_map_on
|
50
|
+
@person_class.identity_map_on
|
51
|
+
MongoMapper::Plugins::IdentityMap.clear
|
45
52
|
end
|
46
53
|
|
47
|
-
should "
|
48
|
-
|
49
|
-
plugin MongoMapper::Plugins::IdentityMap
|
50
|
-
end.identity_map.should == {}
|
54
|
+
should "track identity mapped models" do
|
55
|
+
MongoMapper::Plugins::IdentityMap.models.should == [@person_class, @post_class].to_set
|
51
56
|
end
|
52
57
|
|
53
|
-
should "
|
54
|
-
|
55
|
-
|
58
|
+
should "be able to clear the map of all models" do
|
59
|
+
person = @person_class.create(:name => 'John')
|
60
|
+
post = @post_class.create(:title => 'IM 4eva')
|
61
|
+
assert_in_map(person, post)
|
62
|
+
|
63
|
+
MongoMapper::Plugins::IdentityMap.clear
|
64
|
+
|
65
|
+
assert_not_in_map(person, post)
|
66
|
+
|
67
|
+
[@person_class, @post_class].each { |klass| klass.identity_map.should == {} }
|
56
68
|
end
|
69
|
+
|
70
|
+
context "IM on off status" do
|
71
|
+
teardown do
|
72
|
+
@post_class.identity_map_on
|
73
|
+
@person_class.identity_map_on
|
74
|
+
end
|
57
75
|
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
76
|
+
should "default identity map status to on" do
|
77
|
+
Doc { plugin MongoMapper::Plugins::IdentityMap }.identity_map_status.should be_true
|
78
|
+
end
|
79
|
+
|
80
|
+
should "be true if on" do
|
81
|
+
@post_class.identity_map_on
|
82
|
+
@post_class.should be_identity_map_on
|
83
|
+
@post_class.should_not be_identity_map_off
|
84
|
+
end
|
62
85
|
|
63
|
-
|
64
|
-
|
65
|
-
|
86
|
+
should "be false if off" do
|
87
|
+
@post_class.identity_map_off
|
88
|
+
@post_class.should be_identity_map_off
|
89
|
+
@post_class.should_not be_identity_map_on
|
90
|
+
end
|
66
91
|
|
67
|
-
|
92
|
+
should "not share with other classes" do
|
93
|
+
@post_class.identity_map_off
|
94
|
+
@person_class.identity_map_on
|
95
|
+
@post_class.identity_map_status.should_not == @person_class.identity_map_status
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
should "default identity map to hash" do
|
100
|
+
Doc { plugin MongoMapper::Plugins::IdentityMap }.identity_map.should == {}
|
68
101
|
end
|
69
102
|
|
70
103
|
should "add key to map when saved" do
|
@@ -73,7 +106,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
73
106
|
person.save.should be_true
|
74
107
|
assert_in_map(person)
|
75
108
|
end
|
76
|
-
|
109
|
+
|
77
110
|
should "allow saving with options" do
|
78
111
|
person = @person_class.new
|
79
112
|
assert_nothing_raised do
|
@@ -87,7 +120,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
87
120
|
person.destroy
|
88
121
|
assert_not_in_map(person)
|
89
122
|
end
|
90
|
-
|
123
|
+
|
91
124
|
context "reload" do
|
92
125
|
setup do
|
93
126
|
@person = @person_class.create(:name => 'Fred')
|
@@ -101,8 +134,8 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
101
134
|
|
102
135
|
should "add object back into map" do
|
103
136
|
assert_in_map(@person)
|
104
|
-
|
105
|
-
@person.reload.
|
137
|
+
before_reload = @person
|
138
|
+
@person.reload.should equal(before_reload)
|
106
139
|
assert_in_map(@person)
|
107
140
|
end
|
108
141
|
end
|
@@ -121,10 +154,10 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
121
154
|
first_load = @person_class.load({'_id' => @id, 'name' => 'Frank'})
|
122
155
|
@person_class.identity_map.expects(:[]=).never
|
123
156
|
second_load = @person_class.load({'_id' => @id, 'name' => 'Frank'})
|
124
|
-
first_load.
|
157
|
+
first_load.should equal(second_load)
|
125
158
|
end
|
126
159
|
end
|
127
|
-
|
160
|
+
|
128
161
|
context "#find (with one id)" do
|
129
162
|
context "for object not in map" do
|
130
163
|
setup do
|
@@ -142,7 +175,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
142
175
|
found_person = @person_class.find(@person.id)
|
143
176
|
assert_in_map(found_person)
|
144
177
|
end
|
145
|
-
|
178
|
+
|
146
179
|
should "return nil if not found " do
|
147
180
|
@person_class.find(1234).should be_nil
|
148
181
|
end
|
@@ -157,15 +190,15 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
157
190
|
expect_no_queries
|
158
191
|
@person_class.find(@person.id)
|
159
192
|
end
|
160
|
-
|
193
|
+
|
161
194
|
should "return exact object" do
|
162
195
|
assert_in_map(@person)
|
163
196
|
found_person = @person_class.find(@person.id)
|
164
|
-
found_person.
|
197
|
+
found_person.should equal(@person)
|
165
198
|
end
|
166
199
|
end
|
167
200
|
end
|
168
|
-
|
201
|
+
|
169
202
|
context "#find (with one id and options)" do
|
170
203
|
setup do
|
171
204
|
@person = @person_class.create(:name => 'Fred')
|
@@ -195,7 +228,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
195
228
|
@person.posts.find(1234).should be_nil
|
196
229
|
end
|
197
230
|
end
|
198
|
-
|
231
|
+
|
199
232
|
context "#find (with multiple ids)" do
|
200
233
|
should "add all documents to map" do
|
201
234
|
person1 = @person_class.create(:name => 'Fred')
|
@@ -204,7 +237,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
204
237
|
@person_class.identity_map.clear
|
205
238
|
|
206
239
|
people = @person_class.find(person1.id, person2.id, person3.id)
|
207
|
-
|
240
|
+
assert_in_map(people)
|
208
241
|
end
|
209
242
|
|
210
243
|
should "add missing documents to map and return existing ones" do
|
@@ -214,16 +247,14 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
214
247
|
person3 = @person_class.create(:name => 'Jesse')
|
215
248
|
|
216
249
|
assert_not_in_map(person1)
|
217
|
-
assert_in_map(person2)
|
218
|
-
assert_in_map(person3)
|
250
|
+
assert_in_map(person2, person3)
|
219
251
|
|
220
252
|
people = @person_class.find(person1.id, person2.id, person3.id)
|
221
253
|
assert_in_map(people.first) # making sure one that wasn't mapped now is
|
222
|
-
assert_in_map(person2)
|
223
|
-
assert_in_map(person3)
|
254
|
+
assert_in_map(person2, person3)
|
224
255
|
end
|
225
256
|
end
|
226
|
-
|
257
|
+
|
227
258
|
context "#first" do
|
228
259
|
context "for object not in map" do
|
229
260
|
setup do
|
@@ -256,15 +287,15 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
256
287
|
expect_no_queries
|
257
288
|
@person_class.first(:_id => @person.id)
|
258
289
|
end
|
259
|
-
|
290
|
+
|
260
291
|
should "return exact object" do
|
261
292
|
assert_in_map(@person)
|
262
293
|
found_person = @person_class.first(:_id => @person.id)
|
263
|
-
found_person.
|
294
|
+
found_person.should equal(@person)
|
264
295
|
end
|
265
296
|
end
|
266
297
|
end
|
267
|
-
|
298
|
+
|
268
299
|
context "#all" do
|
269
300
|
should "add all documents to map" do
|
270
301
|
person1 = @person_class.create(:name => 'Fred')
|
@@ -273,7 +304,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
273
304
|
@person_class.identity_map.clear
|
274
305
|
|
275
306
|
people = @person_class.all(:_id => [person1.id, person2.id, person3.id])
|
276
|
-
|
307
|
+
assert_in_map(people)
|
277
308
|
end
|
278
309
|
|
279
310
|
should "add missing documents to map and return existing ones" do
|
@@ -283,13 +314,11 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
283
314
|
person3 = @person_class.create(:name => 'Jesse')
|
284
315
|
|
285
316
|
assert_not_in_map(person1)
|
286
|
-
assert_in_map(person2)
|
287
|
-
assert_in_map(person3)
|
317
|
+
assert_in_map(person2, person3)
|
288
318
|
|
289
319
|
people = @person_class.all(:_id => [person1.id, person2.id, person3.id])
|
290
|
-
|
291
|
-
assert_in_map(person2)
|
292
|
-
assert_in_map(person3)
|
320
|
+
# people.first is making sure one that wasn't mapped now is
|
321
|
+
assert_in_map(people.first, person2, person3)
|
293
322
|
end
|
294
323
|
end
|
295
324
|
|
@@ -303,7 +332,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
303
332
|
@person_class.find_by_id(1234).should be_nil
|
304
333
|
end
|
305
334
|
end
|
306
|
-
|
335
|
+
|
307
336
|
context "querying and selecting certain fields" do
|
308
337
|
setup do
|
309
338
|
@person = @person_class.create(:name => 'Bill')
|
@@ -324,8 +353,8 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
324
353
|
@person_class.find(1234, :select => 'name').should be_nil
|
325
354
|
end
|
326
355
|
end
|
327
|
-
|
328
|
-
context "single collection
|
356
|
+
|
357
|
+
context "single collection inherited models" do
|
329
358
|
setup do
|
330
359
|
class ::Item
|
331
360
|
include MongoMapper::Document
|
@@ -339,10 +368,9 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
339
368
|
one :child, :class_name => 'Blog'
|
340
369
|
end
|
341
370
|
Item.collection.remove
|
342
|
-
Item.identity_map.clear
|
343
371
|
|
344
372
|
class ::Blog < ::Item; end
|
345
|
-
|
373
|
+
|
346
374
|
class ::BlogPost < ::Item
|
347
375
|
key :blog_id, ObjectId
|
348
376
|
belongs_to :blog
|
@@ -355,11 +383,10 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
355
383
|
Object.send :remove_const, 'BlogPost' if defined?(::BlogPost)
|
356
384
|
end
|
357
385
|
|
358
|
-
should "share the same identity map
|
386
|
+
should "share the same identity map" do
|
359
387
|
blog = Blog.create(:title => 'Jill')
|
360
388
|
assert_in_map(blog)
|
361
|
-
Item.
|
362
|
-
Item.identity_map.object_id.should == Blog.identity_map.object_id
|
389
|
+
Item.identity_map.should equal(Blog.identity_map)
|
363
390
|
end
|
364
391
|
|
365
392
|
should "not query when finding by _id and _type" do
|
@@ -369,8 +396,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
369
396
|
|
370
397
|
blog = Item.find(blog.id)
|
371
398
|
post = Item.find(post.id)
|
372
|
-
assert_in_map(blog)
|
373
|
-
assert_in_map(post)
|
399
|
+
assert_in_map(blog, post)
|
374
400
|
|
375
401
|
expect_no_queries
|
376
402
|
post.blog
|
@@ -379,7 +405,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
379
405
|
|
380
406
|
should "load from map when using parent collection inherited class" do
|
381
407
|
blog = Blog.create(:title => 'Jill')
|
382
|
-
Item.find(blog.id).
|
408
|
+
Item.find(blog.id).should equal(blog)
|
383
409
|
end
|
384
410
|
|
385
411
|
should "work correctly with belongs to proxy" do
|
@@ -388,7 +414,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
388
414
|
|
389
415
|
blog = Blog.create(:title => 'Jill', :parent => root)
|
390
416
|
assert_in_map(blog)
|
391
|
-
root.
|
417
|
+
root.should equal(blog.parent)
|
392
418
|
end
|
393
419
|
|
394
420
|
should "work correctly with one proxy" do
|
@@ -397,8 +423,79 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
397
423
|
|
398
424
|
root = Item.create(:title => 'Root', :child => blog)
|
399
425
|
assert_in_map(root)
|
426
|
+
root.child.should equal(blog)
|
427
|
+
end
|
428
|
+
end
|
429
|
+
|
430
|
+
context "without identity map" do
|
431
|
+
should "not add to map on save" do
|
432
|
+
@post_class.without_identity_map do
|
433
|
+
post = @post_class.create(:title => 'Bill')
|
434
|
+
assert_not_in_map(post)
|
435
|
+
end
|
436
|
+
end
|
437
|
+
|
438
|
+
should "not remove from map on delete" do
|
439
|
+
post = @post_class.create(:title => 'Bill')
|
440
|
+
assert_in_map(post)
|
441
|
+
|
442
|
+
@post_class.without_identity_map do
|
443
|
+
post.destroy
|
444
|
+
end
|
445
|
+
|
446
|
+
assert_in_map(post)
|
447
|
+
end
|
448
|
+
|
449
|
+
should "not add to map when loading" do
|
450
|
+
@post_class.without_identity_map do
|
451
|
+
post = @post_class.load({'_id' => Mongo::ObjectID.new, 'title' => 'Awesome!'})
|
452
|
+
assert_not_in_map(post)
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
should "not load from map when loading" do
|
457
|
+
post = @post_class.create(:title => 'Awesome!')
|
400
458
|
|
401
|
-
|
459
|
+
@post_class.without_identity_map do
|
460
|
+
loaded = @post_class.load('_id' => post._id, 'title' => 'Awesome!')
|
461
|
+
loaded.should_not equal(post)
|
462
|
+
end
|
463
|
+
end
|
464
|
+
|
465
|
+
context "all" do
|
466
|
+
should "not add to map" do
|
467
|
+
@post_class.without_identity_map do
|
468
|
+
post1 = @post_class.create(:title => 'Foo')
|
469
|
+
post2 = @post_class.create(:title => 'Bar')
|
470
|
+
@post_class.identity_map.clear
|
471
|
+
|
472
|
+
assert_not_in_map(@post_class.all)
|
473
|
+
end
|
474
|
+
end
|
475
|
+
end
|
476
|
+
|
477
|
+
context "first" do
|
478
|
+
should "not add to map" do
|
479
|
+
@post_class.without_identity_map do
|
480
|
+
post1 = @post_class.create(:title => 'Foo')
|
481
|
+
post2 = @post_class.create(:title => 'Bar')
|
482
|
+
@post_class.identity_map.clear
|
483
|
+
|
484
|
+
assert_not_in_map(@post_class.first)
|
485
|
+
end
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
context "last" do
|
490
|
+
should "not add to map" do
|
491
|
+
@post_class.without_identity_map do
|
492
|
+
post1 = @post_class.create(:title => 'Foo')
|
493
|
+
post2 = @post_class.create(:title => 'Bar')
|
494
|
+
@post_class.identity_map.clear
|
495
|
+
|
496
|
+
assert_not_in_map(@post_class.last(:order => 'title'))
|
497
|
+
end
|
498
|
+
end
|
402
499
|
end
|
403
500
|
end
|
404
501
|
end
|
@@ -8,10 +8,12 @@ class FakeBlankProxy < MongoMapper::Plugins::Associations::Proxy
|
|
8
8
|
def find_target; '' end
|
9
9
|
end
|
10
10
|
|
11
|
+
class FakeNumberProxy < MongoMapper::Plugins::Associations::Proxy
|
12
|
+
def find_target; 17 end
|
13
|
+
end
|
14
|
+
|
11
15
|
class FakeProxy < MongoMapper::Plugins::Associations::Proxy
|
12
|
-
def find_target
|
13
|
-
[1, 2]
|
14
|
-
end
|
16
|
+
def find_target; [1, 2] end
|
15
17
|
end
|
16
18
|
|
17
19
|
class ProxyTest < Test::Unit::TestCase
|
data/test/unit/test_document.rb
CHANGED
@@ -186,6 +186,34 @@ class DocumentTest < Test::Unit::TestCase
|
|
186
186
|
@oid = Mongo::ObjectID.new
|
187
187
|
end
|
188
188
|
|
189
|
+
should "delegate hash to _id" do
|
190
|
+
doc = @document.new
|
191
|
+
doc.hash.should == doc._id.hash
|
192
|
+
end
|
193
|
+
|
194
|
+
should "delegate eql to ==" do
|
195
|
+
doc = @document.new
|
196
|
+
other = @document.new
|
197
|
+
doc.eql?(other).should == (doc == other)
|
198
|
+
doc.eql?(doc).should == (doc == doc)
|
199
|
+
end
|
200
|
+
|
201
|
+
should "know if same object as another" do
|
202
|
+
doc = @document.new
|
203
|
+
doc.should equal(doc)
|
204
|
+
doc.should_not equal(@document.new)
|
205
|
+
end
|
206
|
+
|
207
|
+
should "allow set operations on array of documents" do
|
208
|
+
@document.key :parent_id, ObjectId
|
209
|
+
@document.belongs_to :parent, :class => @document
|
210
|
+
|
211
|
+
parent = @document.create
|
212
|
+
child = @document.create(:parent => parent)
|
213
|
+
|
214
|
+
([child.parent] & [parent]).should == [parent]
|
215
|
+
end
|
216
|
+
|
189
217
|
should "be equal if id and class are the same" do
|
190
218
|
(@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be(true)
|
191
219
|
end
|
@@ -566,6 +566,30 @@ class EmbeddedDocumentTest < Test::Unit::TestCase
|
|
566
566
|
setup do
|
567
567
|
@oid = Mongo::ObjectID.new
|
568
568
|
end
|
569
|
+
|
570
|
+
should "delegate hash to _id" do
|
571
|
+
doc = @document.new
|
572
|
+
doc.hash.should == doc._id.hash
|
573
|
+
end
|
574
|
+
|
575
|
+
should "delegate eql to ==" do
|
576
|
+
doc = @document.new
|
577
|
+
other = @document.new
|
578
|
+
doc.eql?(other).should == (doc == other)
|
579
|
+
doc.eql?(doc).should == (doc == doc)
|
580
|
+
end
|
581
|
+
|
582
|
+
should "know if same object as another" do
|
583
|
+
doc = @document.new
|
584
|
+
doc.should equal(doc)
|
585
|
+
doc.should_not equal(@document.new)
|
586
|
+
end
|
587
|
+
|
588
|
+
should "allow set operations on array of documents" do
|
589
|
+
doc = @document.new
|
590
|
+
([doc] & [doc]).should == [doc]
|
591
|
+
end
|
592
|
+
|
569
593
|
should "be equal if id and class are the same" do
|
570
594
|
(@document.new('_id' => @oid) == @document.new('_id' => @oid)).should be_true
|
571
595
|
end
|
data/test/unit/test_plugins.rb
CHANGED
@@ -1,12 +1,16 @@
|
|
1
1
|
require 'test_helper'
|
2
2
|
|
3
3
|
module MyPlugin
|
4
|
+
def self.configure(model)
|
5
|
+
model.class_eval { attr_accessor :from_configure }
|
6
|
+
end
|
7
|
+
|
4
8
|
module ClassMethods
|
5
9
|
def class_foo
|
6
10
|
'class_foo'
|
7
11
|
end
|
8
12
|
end
|
9
|
-
|
13
|
+
|
10
14
|
module InstanceMethods
|
11
15
|
def instance_foo
|
12
16
|
'instance_foo'
|
@@ -26,15 +30,19 @@ class PluginsTest < Test::Unit::TestCase
|
|
26
30
|
should "include instance methods" do
|
27
31
|
@document.new.instance_foo.should == 'instance_foo'
|
28
32
|
end
|
29
|
-
|
33
|
+
|
30
34
|
should "extend class methods" do
|
31
35
|
@document.class_foo.should == 'class_foo'
|
32
36
|
end
|
33
|
-
|
37
|
+
|
38
|
+
should "pass model to configure" do
|
39
|
+
@document.new.should respond_to(:from_configure)
|
40
|
+
end
|
41
|
+
|
34
42
|
should "default plugins to empty array" do
|
35
43
|
Class.new { extend MongoMapper::Plugins }.plugins.should == []
|
36
44
|
end
|
37
|
-
|
45
|
+
|
38
46
|
should "add plugin to plugins" do
|
39
47
|
@document.plugins.should include(MyPlugin)
|
40
48
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mongo_mapper-unstable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2010.1.
|
4
|
+
version: 2010.1.25
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-25 00:00:00 -05:00
|
13
13
|
default_executable: mmconsole
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|