mongo_mapper-unstable 2010.1.22 → 2010.1.25
Sign up to get free protection for your applications and to get access to all the features.
- 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
|