public
Description: simple identity map for active record. eager loading associations FTL
Clone URL: git://github.com/technoweenie/active_record_context.git
Click here to lend your support to: active_record_context and make a donation at www.pledgie.com !
add #prefetch method for models

git-svn-id: 
http://svn.techno-weenie.net/projects/plugins/active_record_context@2944 
567b1171-46fb-0310-a4c9-b4bef9110e78
technoweenie (author)
Mon Aug 13 07:48:50 -0700 2007
commit  9fb24fc500d1e617626660449c34cefc58ff7155
tree    3fa3aaf43bc15e86641913a19e4dfcace3e9a010
parent  a50087b83300a43f9ce15d91cf02dd85d5bf9a7e
...
10
11
12
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
14
15
...
23
24
25
26
 
27
28
29
...
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
...
45
46
47
 
48
49
50
51
0
@@ -10,6 +10,28 @@ module Technoweenie
0
     mattr_accessor :log_context_activity
0
     mattr_reader :context_cache
0
 
0
+ # Preloads the record from the given array of IDs. The ids should all be the same type.
0
+ # You can pass an array of active record models if that model belongs to the current one.
0
+ #
0
+ # users = User.find :all
0
+ # Avatar.prefetch users # performs this automatically: users.collect { |user| user.avatar_id }
0
+ #
0
+ def prefetch(ids)
0
+ return [] if ids.blank?
0
+ initial = ids.first
0
+ ids = ids.collect { |record| record.send(prefetch_default) } if initial.respond_to?(prefetch_default)
0
+ ids.compact!
0
+ ids.uniq!
0
+ find :all, :conditions => { :id => ids }
0
+ end
0
+
0
+ # defaults to the foreign key of the current model
0
+ #
0
+ # Avatar => avatar_id
0
+ def prefetch_default
0
+ @prefetch_default ||= name.foreign_key
0
+ end
0
+
0
     def find_every_with_context(options)
0
       returning find_every_without_context(options) do |records|
0
         store_in_context records
0
@@ -23,7 +45,7 @@ module Technoweenie
0
     end
0
 
0
     def cached
0
- context_cache ? (context_cache[self] ||= {}) : {}
0
+ context_cache ? (context_cache[self.base_class] ||= {}) : {}
0
     end
0
     
0
     def store_in_context(records)
...
7
8
9
 
 
10
11
12
...
7
8
9
10
11
12
13
14
0
@@ -7,6 +7,8 @@ require 'active_support'
0
 require 'active_record'
0
 require 'active_record/fixtures'
0
 require 'technoweenie/active_record_context'
0
+require 'rubygems'
0
+require 'mocha'
0
 
0
 config = YAML::load(IO.read(File.dirname(__FILE__) + '/database.yml'))
0
 ActiveRecord::Base.logger = Logger.new(File.dirname(__FILE__) + "/debug.log")
...
7
8
9
 
 
10
11
12
...
21
22
23
24
25
26
 
 
 
27
28
29
 
 
 
 
 
 
 
 
 
 
 
30
31
32
33
34
35
 
 
36
37
38
...
59
60
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
...
7
8
9
10
11
12
13
14
...
23
24
25
 
 
 
26
27
28
29
30
 
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
 
 
46
47
48
49
50
...
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
0
@@ -7,6 +7,8 @@ class ActiveRecordContextTest < Test::Unit::TestCase
0
     @topic = Topic.create! :title => 'test'
0
     @posts << NormalPost.create!(:body => 'normal body', :topic => @topic)
0
     @posts << PolymorphPost.create!(:body => 'polymorph body', :topic => @topic)
0
+ assert_equal 2, @posts.size
0
+ assert_equal 2, Post.count
0
     assert_nil Post.context_cache
0
   end
0
 
0
@@ -21,18 +23,28 @@ class ActiveRecordContextTest < Test::Unit::TestCase
0
   def test_should_store_records_in_cache
0
     Post.with_context do
0
       records = Post.find(:all)
0
- assert_equal records.size, Post.context_cache[Post].size
0
- assert_equal @posts[0], Post.find_in_context(1)
0
- assert_equal @posts[1], Post.find_in_context(2)
0
+ assert_equal 2, Post.context_cache[Post].size
0
+ assert_equal @posts[0], Post.cached[@posts[0].id]
0
+ assert_equal @posts[1], Post.cached[@posts[1].id]
0
     end
0
   end
0
-
0
+
0
+ def test_should_store_records_in_base_class_cache
0
+ Post.with_context do
0
+ records = NormalPost.find(:all)
0
+ assert Post.context_cache[NormalPost].nil?
0
+ assert_equal @posts[0], NormalPost.cached[@posts[0].id]
0
+ assert_equal 1, Post.context_cache[Post].size
0
+ assert_equal @posts[0], Post.cached[@posts[0].id]
0
+ end
0
+ end
0
+
0
   def test_should_find_records_in_context
0
     Post.with_context do
0
       records = Post.find(:all)
0
       Post.destroy_all
0
- assert_equal @posts[0], Post.find(1)
0
- assert_equal @posts[1], Post.find(2)
0
+ assert_equal @posts[0], Post.find(@posts.first.id)
0
+ assert_equal @posts[1], Post.find(@posts.last.id)
0
     end
0
     
0
     assert_raise ActiveRecord::RecordNotFound do
0
@@ -59,4 +71,20 @@ class ActiveRecordContextTest < Test::Unit::TestCase
0
     assert_equal @topic, @posts[1].topic
0
     assert_nil @posts[1].topic(true)
0
   end
0
+
0
+ def test_default_prefetch_methods
0
+ {Topic => 'topic_id', Post => 'post_id'}.each do |klass, expected|
0
+ assert_equal expected, klass.prefetch_default
0
+ end
0
+ end
0
+
0
+ def test_should_prefetch_ids
0
+ Topic.expects(:find).with(:all, :conditions => {:id => [1,2,3]})
0
+ Topic.prefetch [1,2,3]
0
+ end
0
+
0
+ def test_should_prefetch_by_parent_records
0
+ Topic.expects(:find).with(:all, :conditions => {:id => [@topic.id]})
0
+ Topic.prefetch @posts
0
+ end
0
 end

Comments

    No one has commented yet.