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 CHANGED
@@ -1 +1 @@
1
- 2010.01.22
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
- perform_validations = options.delete(:validate)
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
- save || raise(DocumentNotValid.new(self))
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={})
@@ -5,14 +5,9 @@ module MongoMapper
5
5
  end
6
6
 
7
7
  def plugin(mod)
8
- if mod.const_defined?(:ClassMethods)
9
- extend mod::ClassMethods
10
- end
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
- module InstanceMethods
5
- def self.included(model)
6
- model.class_eval do
7
- include ActiveSupport::Callbacks
4
+ def self.configure(model)
5
+ model.class_eval do
6
+ include ActiveSupport::Callbacks
8
7
 
9
- define_callbacks(
10
- :before_save, :after_save,
11
- :before_create, :after_create,
12
- :before_update, :after_update,
13
- :before_validation, :after_validation,
14
- :before_validation_on_create, :after_validation_on_create,
15
- :before_validation_on_update, :after_validation_on_update,
16
- :before_destroy, :after_destroy
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.identity_map
5
- Thread.current[:mongo_mapper_identity_map] ||= {}
4
+ def self.models
5
+ @models ||= Set.new
6
6
  end
7
-
8
- def self.identity_map=(v)
9
- Thread.current[:mongo_mapper_identity_map] = v
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 identity_map
14
- IdentityMap.identity_map
17
+ def inherited(descendant)
18
+ descendant.identity_map = identity_map
19
+ super
15
20
  end
16
21
 
17
- def identity_map=(v)
18
- IdentityMap.identity_map = v
22
+ def identity_map
23
+ @identity_map ||= {}
19
24
  end
20
25
 
21
- def identity_map_key(id)
22
- "#{collection.name}:#{id}"
26
+ def identity_map=(v)
27
+ @identity_map = v
23
28
  end
24
29
 
25
30
  def find_one(options={})
26
- criteria, finder_options = to_finder_options(options)
27
- document_in_map = identity_map[identity_map_key(criteria[:_id])]
28
- find_by_single_id = criteria.keys == [:_id]
29
- find_by_single_id_with_sci = criteria.keys.to_set == [:_id, :_type].to_set
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) unless finder_options[:fields].nil?
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) unless finder_options[:fields].nil?
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
- key = identity_map_key(attrs['_id'])
51
- unless document = identity_map[key]
50
+ document = identity_map[attrs['_id']]
51
+
52
+ if document.nil? || identity_map_off?
52
53
  document = super
53
- identity_map[document.identity_map_key] = 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(identity_map_key(document._id))
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[identity_map_key] = self
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(identity_map_key)
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
- module InstanceMethods
5
- def self.included(model)
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(resource)
5
- resource.identity_map.keys.should include(resource.identity_map_key)
6
- mapped_resource = resource.identity_map[resource.identity_map_key]
7
- resource.object_id.should == mapped_resource.object_id
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(resource)
11
- resource.identity_map.keys.should_not include(resource.identity_map_key)
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
- @person_class.identity_map.clear
44
- @post_class.identity_map.clear
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 "default identity map to hash" do
48
- Doc() do
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 "share identity map with other classes" do
54
- map = @post_class.identity_map
55
- map.object_id.should == @person_class.identity_map.object_id
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
- should "have identity map key that is always unique per document and class" do
59
- person = @person_class.new
60
- person.identity_map_key.should == "people:#{person.id}"
61
- @person_class.identity_map_key(person.id).should == person.identity_map_key
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
- post = @post_class.new
64
- post.identity_map_key.should == "posts:#{post.id}"
65
- @post_class.identity_map_key(post.id).should == post.identity_map_key
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
- person.identity_map_key.should_not == post.identity_map_key
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
- object_id = @person.object_id
105
- @person.reload.object_id.should == object_id
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.object_id.should == second_load.object_id
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.object_id.should == @person.object_id
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
- people.each { |person| assert_in_map(person) }
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.object_id.should == @person.object_id
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
- people.each { |person| assert_in_map(person) }
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
- assert_in_map(people.first) # making sure one that wasn't mapped now is
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 inheritance" do
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 4eva" do
386
+ should "share the same identity map" do
359
387
  blog = Blog.create(:title => 'Jill')
360
388
  assert_in_map(blog)
361
- Item.identity_map_key(blog).should == Blog.identity_map_key(blog)
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).object_id.should == blog.object_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.object_id.should == blog.parent.object_id
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
- root.child.object_id.should == blog.object_id
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
@@ -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
@@ -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.22
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-22 00:00:00 -05:00
12
+ date: 2010-01-25 00:00:00 -05:00
13
13
  default_executable: mmconsole
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency