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 CHANGED
@@ -1 +1 @@
1
- 2010.01.19
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 = to_finder_options(options)
27
- key = identity_map_key(criteria[:_id])
28
- if criteria.keys == [:_id] && document = identity_map[key]
29
- document
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
- document = super
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
- document
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
- Mongo::Collection.any_instance.expects(:find_one).once.returns({})
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
- Mongo::Collection.any_instance.expects(:find_one).once
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
- Mongo::Collection.any_instance.expects(:find).never
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
- Mongo::Collection.any_instance.expects(:find_one)
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
- Mongo::Collection.any_instance.expects(:find_one).once
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
- Mongo::Collection.any_instance.expects(:find).never
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 ::DocParent
330
+ class ::Item
287
331
  include MongoMapper::Document
332
+ plugin MongoMapper::Plugins::IdentityMap
333
+
288
334
  key :_type, String
289
- key :name, String
335
+ key :title, String
290
336
  key :parent_id, ObjectId
291
337
 
292
- belongs_to :parent, :class_name => 'DocParent'
293
- one :child, :class_name => 'DocDaughter'
338
+ belongs_to :parent, :class_name => 'Item'
339
+ one :child, :class_name => 'Blog'
294
340
  end
295
- DocParent.collection.remove
296
- DocParent.identity_map.clear
341
+ Item.collection.remove
342
+ Item.identity_map.clear
297
343
 
298
- class ::DocDaughter < ::DocParent; end
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, 'DocParent' if defined?(::DocParent)
303
- Object.send :remove_const, 'DocDaughter' if defined?(::DocDaughter)
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
- @daughter = DocDaughter.create(:name => 'Jill')
308
- assert_in_map(@daughter)
309
- DocParent.identity_map_key(@daughter).should == DocDaughter.identity_map_key(@daughter)
310
- DocParent.identity_map.object_id.should == DocDaughter.identity_map.object_id
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
- @daughter = DocDaughter.create(:name => 'Jill')
315
- DocParent.find(@daughter.id).object_id.should == @daughter.object_id
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
- @parent = DocParent.create(:name => 'Dad')
320
- assert_in_map(@parent)
386
+ root = Item.create(:title => 'Root')
387
+ assert_in_map(root)
321
388
 
322
- @daughter = DocDaughter.create(:name => 'Jill', :parent => @parent)
323
- assert_in_map(@daughter)
324
- @parent.object_id.should == @daughter.parent.object_id
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
- @daughter = DocDaughter.create(:name => 'Jill')
329
- assert_in_map(@daughter)
395
+ blog = Blog.create(:title => 'Jill')
396
+ assert_in_map(blog)
330
397
 
331
- @parent = DocParent.create(:name => 'Dad', :child => @daughter)
332
- assert_in_map(@parent)
398
+ root = Item.create(:title => 'Root', :child => blog)
399
+ assert_in_map(root)
333
400
 
334
- @parent.child.object_id.should == @daughter.object_id
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.19
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-19 00:00:00 -05:00
12
+ date: 2010-01-20 00:00:00 -05:00
13
13
  default_executable: mmconsole
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency