mongo_mapper-unstable 2010.1.19 → 2010.1.20
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 +2 -1
- data/lib/mongo_mapper/plugins/identity_map.rb +25 -6
- data/test/functional/test_identity_map.rb +101 -34
- data/test/unit/test_finder_options.rb +4 -0
- metadata +2 -2
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2010.01.
|
1
|
+
2010.01.20
|
@@ -22,7 +22,6 @@ module MongoMapper
|
|
22
22
|
plugin Plugins::Serialization
|
23
23
|
plugin Plugins::Validations
|
24
24
|
plugin Plugins::Callbacks # for now callbacks needs to be after validations
|
25
|
-
plugin Plugins::IdentityMap
|
26
25
|
|
27
26
|
extend Plugins::Validations::DocumentMacros
|
28
27
|
end
|
@@ -277,6 +276,7 @@ module MongoMapper
|
|
277
276
|
end
|
278
277
|
end
|
279
278
|
|
279
|
+
# All query methods that load documents pass through find_one or find_many
|
280
280
|
def find_one(options={})
|
281
281
|
criteria, options = to_finder_options(options)
|
282
282
|
if doc = collection.find_one(criteria, options)
|
@@ -284,6 +284,7 @@ module MongoMapper
|
|
284
284
|
end
|
285
285
|
end
|
286
286
|
|
287
|
+
# All query methods that load documents pass through find_one or find_many
|
287
288
|
def find_many(options)
|
288
289
|
criteria, options = to_finder_options(options)
|
289
290
|
collection.find(criteria, options).to_a.map do |doc|
|
@@ -23,15 +23,27 @@ module MongoMapper
|
|
23
23
|
end
|
24
24
|
|
25
25
|
def find_one(options={})
|
26
|
-
criteria, finder_options
|
27
|
-
|
28
|
-
|
29
|
-
|
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
|
30
35
|
else
|
31
|
-
|
36
|
+
super.tap do |document|
|
37
|
+
remove_documents_from_map(document) unless finder_options[:fields].nil?
|
38
|
+
end
|
32
39
|
end
|
40
|
+
end
|
33
41
|
|
34
|
-
|
42
|
+
def find_many(options)
|
43
|
+
criteria, finder_options = to_finder_options(options)
|
44
|
+
super.tap do |documents|
|
45
|
+
remove_documents_from_map(documents) unless finder_options[:fields].nil?
|
46
|
+
end
|
35
47
|
end
|
36
48
|
|
37
49
|
def load(attrs)
|
@@ -43,6 +55,13 @@ module MongoMapper
|
|
43
55
|
|
44
56
|
document
|
45
57
|
end
|
58
|
+
|
59
|
+
private
|
60
|
+
def remove_documents_from_map(*documents)
|
61
|
+
documents.flatten.compact.each do |document|
|
62
|
+
identity_map.delete(identity_map_key(document._id))
|
63
|
+
end
|
64
|
+
end
|
46
65
|
end
|
47
66
|
|
48
67
|
module InstanceMethods
|
@@ -11,15 +11,28 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
11
11
|
resource.identity_map.keys.should_not include(resource.identity_map_key)
|
12
12
|
end
|
13
13
|
|
14
|
+
def expect_no_queries
|
15
|
+
Mongo::Collection.any_instance.expects(:find_one).never
|
16
|
+
Mongo::Collection.any_instance.expects(:find).never
|
17
|
+
end
|
18
|
+
|
19
|
+
def expects_one_query
|
20
|
+
Mongo::Collection.any_instance.expects(:find_one).once.returns({})
|
21
|
+
end
|
22
|
+
|
14
23
|
context "Document" do
|
15
24
|
setup do
|
16
25
|
@person_class = Doc('Person') do
|
17
26
|
set_collection_name 'people'
|
27
|
+
plugin MongoMapper::Plugins::IdentityMap
|
28
|
+
|
18
29
|
key :name, String
|
19
30
|
end
|
20
31
|
|
21
32
|
@post_class = Doc('Post') do
|
22
33
|
set_collection_name 'posts'
|
34
|
+
plugin MongoMapper::Plugins::IdentityMap
|
35
|
+
|
23
36
|
key :title, String
|
24
37
|
key :person_id, ObjectId
|
25
38
|
end
|
@@ -82,7 +95,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
82
95
|
|
83
96
|
should "remove object from identity and re-query" do
|
84
97
|
assert_in_map(@person)
|
85
|
-
|
98
|
+
expects_one_query
|
86
99
|
@person.reload
|
87
100
|
end
|
88
101
|
|
@@ -120,7 +133,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
120
133
|
end
|
121
134
|
|
122
135
|
should "query the database" do
|
123
|
-
|
136
|
+
expects_one_query
|
124
137
|
@person_class.find(@person.id)
|
125
138
|
end
|
126
139
|
|
@@ -129,6 +142,10 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
129
142
|
found_person = @person_class.find(@person.id)
|
130
143
|
assert_in_map(found_person)
|
131
144
|
end
|
145
|
+
|
146
|
+
should "return nil if not found " do
|
147
|
+
@person_class.find(1234).should be_nil
|
148
|
+
end
|
132
149
|
end
|
133
150
|
|
134
151
|
context "for object in map" do
|
@@ -137,8 +154,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
137
154
|
end
|
138
155
|
|
139
156
|
should "not query database" do
|
140
|
-
|
141
|
-
Mongo::Collection.any_instance.expects(:find_one).never
|
157
|
+
expect_no_queries
|
142
158
|
@person_class.find(@person.id)
|
143
159
|
end
|
144
160
|
|
@@ -147,7 +163,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
147
163
|
found_person = @person_class.find(@person.id)
|
148
164
|
found_person.object_id.should == @person.object_id
|
149
165
|
end
|
150
|
-
end
|
166
|
+
end
|
151
167
|
end
|
152
168
|
|
153
169
|
context "#find (with one id and options)" do
|
@@ -165,7 +181,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
165
181
|
# way to check if document matches criteria without querying.
|
166
182
|
should "query the database" do
|
167
183
|
assert_in_map(@post1)
|
168
|
-
|
184
|
+
expects_one_query
|
169
185
|
@person.posts.find(@post1.id)
|
170
186
|
end
|
171
187
|
|
@@ -174,6 +190,10 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
174
190
|
@person.posts.find(@post1.id)
|
175
191
|
assert_in_map(@post1)
|
176
192
|
end
|
193
|
+
|
194
|
+
should "return nil if not found " do
|
195
|
+
@person.posts.find(1234).should be_nil
|
196
|
+
end
|
177
197
|
end
|
178
198
|
|
179
199
|
context "#find (with multiple ids)" do
|
@@ -212,7 +232,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
212
232
|
end
|
213
233
|
|
214
234
|
should "query the database" do
|
215
|
-
|
235
|
+
expects_one_query
|
216
236
|
@person_class.first(:_id => @person.id)
|
217
237
|
end
|
218
238
|
|
@@ -221,6 +241,10 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
221
241
|
found_person = @person_class.first(:_id => @person.id)
|
222
242
|
assert_in_map(found_person)
|
223
243
|
end
|
244
|
+
|
245
|
+
should "return nil if not found" do
|
246
|
+
@person_class.first(:name => 'Bill').should be_nil
|
247
|
+
end
|
224
248
|
end
|
225
249
|
|
226
250
|
context "for object in map" do
|
@@ -229,8 +253,7 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
229
253
|
end
|
230
254
|
|
231
255
|
should "not query database" do
|
232
|
-
|
233
|
-
Mongo::Collection.any_instance.expects(:find_one).never
|
256
|
+
expect_no_queries
|
234
257
|
@person_class.first(:_id => @person.id)
|
235
258
|
end
|
236
259
|
|
@@ -281,57 +304,101 @@ class IdentityMapTest < Test::Unit::TestCase
|
|
281
304
|
end
|
282
305
|
end
|
283
306
|
|
307
|
+
context "querying and selecting certain fields" do
|
308
|
+
setup do
|
309
|
+
@person = @person_class.create(:name => 'Bill')
|
310
|
+
@person_class.identity_map.clear
|
311
|
+
end
|
312
|
+
|
313
|
+
should "not add to map" do
|
314
|
+
assert_not_in_map(@person)
|
315
|
+
@person_class.first(:_id => @person.id, :select => 'name').should == @person
|
316
|
+
@person_class.first(:_id => @person.id, 'fields' => ['name']).should == @person
|
317
|
+
@person_class.last(:_id => @person.id, :select => 'name', :order => 'name').should == @person
|
318
|
+
@person_class.find(@person.id, :select => 'name').should == @person
|
319
|
+
@person_class.all(:_id => @person.id, :select => 'name').should == [@person]
|
320
|
+
assert_not_in_map(@person)
|
321
|
+
end
|
322
|
+
|
323
|
+
should "return nil if not found" do
|
324
|
+
@person_class.find(1234, :select => 'name').should be_nil
|
325
|
+
end
|
326
|
+
end
|
327
|
+
|
284
328
|
context "single collection inheritance" do
|
285
329
|
setup do
|
286
|
-
class ::
|
330
|
+
class ::Item
|
287
331
|
include MongoMapper::Document
|
332
|
+
plugin MongoMapper::Plugins::IdentityMap
|
333
|
+
|
288
334
|
key :_type, String
|
289
|
-
key :
|
335
|
+
key :title, String
|
290
336
|
key :parent_id, ObjectId
|
291
337
|
|
292
|
-
belongs_to :parent, :class_name => '
|
293
|
-
one :child, :class_name => '
|
338
|
+
belongs_to :parent, :class_name => 'Item'
|
339
|
+
one :child, :class_name => 'Blog'
|
294
340
|
end
|
295
|
-
|
296
|
-
|
341
|
+
Item.collection.remove
|
342
|
+
Item.identity_map.clear
|
297
343
|
|
298
|
-
class ::
|
344
|
+
class ::Blog < ::Item; end
|
345
|
+
|
346
|
+
class ::BlogPost < ::Item
|
347
|
+
key :blog_id, ObjectId
|
348
|
+
belongs_to :blog
|
349
|
+
end
|
299
350
|
end
|
300
351
|
|
301
352
|
teardown do
|
302
|
-
Object.send :remove_const, '
|
303
|
-
Object.send :remove_const, '
|
353
|
+
Object.send :remove_const, 'Item' if defined?(::Item)
|
354
|
+
Object.send :remove_const, 'Blog' if defined?(::Blog)
|
355
|
+
Object.send :remove_const, 'BlogPost' if defined?(::BlogPost)
|
304
356
|
end
|
305
357
|
|
306
358
|
should "share the same identity map 4eva" do
|
307
|
-
|
308
|
-
assert_in_map(
|
309
|
-
|
310
|
-
|
359
|
+
blog = Blog.create(:title => 'Jill')
|
360
|
+
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
|
363
|
+
end
|
364
|
+
|
365
|
+
should "not query when finding by _id and _type" do
|
366
|
+
blog = Blog.create(:title => 'Blog')
|
367
|
+
post = BlogPost.create(:title => 'Mongo Rocks', :blog => blog)
|
368
|
+
Item.identity_map.clear
|
369
|
+
|
370
|
+
blog = Item.find(blog.id)
|
371
|
+
post = Item.find(post.id)
|
372
|
+
assert_in_map(blog)
|
373
|
+
assert_in_map(post)
|
374
|
+
|
375
|
+
expect_no_queries
|
376
|
+
post.blog
|
377
|
+
Blog.find(blog.id)
|
311
378
|
end
|
312
379
|
|
313
380
|
should "load from map when using parent collection inherited class" do
|
314
|
-
|
315
|
-
|
381
|
+
blog = Blog.create(:title => 'Jill')
|
382
|
+
Item.find(blog.id).object_id.should == blog.object_id
|
316
383
|
end
|
317
384
|
|
318
385
|
should "work correctly with belongs to proxy" do
|
319
|
-
|
320
|
-
assert_in_map(
|
386
|
+
root = Item.create(:title => 'Root')
|
387
|
+
assert_in_map(root)
|
321
388
|
|
322
|
-
|
323
|
-
assert_in_map(
|
324
|
-
|
389
|
+
blog = Blog.create(:title => 'Jill', :parent => root)
|
390
|
+
assert_in_map(blog)
|
391
|
+
root.object_id.should == blog.parent.object_id
|
325
392
|
end
|
326
393
|
|
327
394
|
should "work correctly with one proxy" do
|
328
|
-
|
329
|
-
assert_in_map(
|
395
|
+
blog = Blog.create(:title => 'Jill')
|
396
|
+
assert_in_map(blog)
|
330
397
|
|
331
|
-
|
332
|
-
assert_in_map(
|
398
|
+
root = Item.create(:title => 'Root', :child => blog)
|
399
|
+
assert_in_map(root)
|
333
400
|
|
334
|
-
|
401
|
+
root.child.object_id.should == blog.object_id
|
335
402
|
end
|
336
403
|
end
|
337
404
|
end
|
@@ -242,6 +242,10 @@ class FinderOptionsTest < Test::Unit::TestCase
|
|
242
242
|
should "also work as select" do
|
243
243
|
FinderOptions.new(Room, :select => %w(a b)).options[:fields].should == %w(a b)
|
244
244
|
end
|
245
|
+
|
246
|
+
should "also work with select as array of symbols" do
|
247
|
+
FinderOptions.new(Room, :select => [:a, :b]).options[:fields].should == [:a, :b]
|
248
|
+
end
|
245
249
|
end
|
246
250
|
|
247
251
|
context "Condition auto-detection" do
|
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.20
|
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-20 00:00:00 -05:00
|
13
13
|
default_executable: mmconsole
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|