mongo_mapper-unstable 2010.1.19 → 2010.1.20

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.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