diff options
author | Pratik Naik <pratiknaik@gmail.com> | 2009-12-26 15:07:00 +0530 |
---|---|---|
committer | Pratik Naik <pratiknaik@gmail.com> | 2009-12-26 15:07:00 +0530 |
commit | 3c5a7dcaf55f427f3a48e206feb06410d011ca4f (patch) | |
tree | 1eed5483a1c1d2ad6e7a6d83408cf509c4e7b8c1 /activerecord | |
parent | 9d3d60c64a9ce69b9932f5c543112199e576c2ad (diff) | |
download | rails-3c5a7dcaf55f427f3a48e206feb06410d011ca4f.tar.gz rails-3c5a7dcaf55f427f3a48e206feb06410d011ca4f.tar.bz2 rails-3c5a7dcaf55f427f3a48e206feb06410d011ca4f.zip |
Cache the loaded relations
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/lib/active_record/relation.rb | 75 | ||||
-rw-r--r-- | activerecord/test/cases/relations_test.rb | 33 |
2 files changed, 75 insertions, 33 deletions
diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index c02acba786..a030ba29fa 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -9,6 +9,7 @@ module ActiveRecord @readonly = readonly @associations_to_preload = preload @eager_load_associations = eager_load + @loaded = false end def preload(*associations) @@ -23,38 +24,6 @@ module ActiveRecord create_new_relation(@relation, true) end - def to_a - records = if @eager_load_associations.any? - catch :invalid_query do - return @klass.send(:find_with_associations, { - :select => @relation.send(:select_clauses).join(', '), - :joins => @relation.joins(relation), - :group => @relation.send(:group_clauses).join(', '), - :order => @relation.send(:order_clauses).join(', '), - :conditions => @relation.send(:where_clauses).join("\n\tAND "), - :limit => @relation.taken, - :offset => @relation.skipped - }, - ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, @eager_load_associations, nil)) - end - [] - else - @klass.find_by_sql(@relation.to_sql) - end - - @associations_to_preload.each {|associations| @klass.send(:preload_associations, records, associations) } - records.each { |record| record.readonly! } if @readonly - - records - end - - alias all to_a - - def first - @relation = @relation.take(1) - to_a.first - end - def select(selects) create_new_relation(@relation.project(selects)) end @@ -109,6 +78,48 @@ module ActiveRecord @relation.respond_to?(method) || Array.method_defined?(method) || super end + def to_a + return @records if loaded? + + @records = if @eager_load_associations.any? + catch :invalid_query do + return @klass.send(:find_with_associations, { + :select => @relation.send(:select_clauses).join(', '), + :joins => @relation.joins(relation), + :group => @relation.send(:group_clauses).join(', '), + :order => @relation.send(:order_clauses).join(', '), + :conditions => @relation.send(:where_clauses).join("\n\tAND "), + :limit => @relation.taken, + :offset => @relation.skipped + }, + ActiveRecord::Associations::ClassMethods::JoinDependency.new(@klass, @eager_load_associations, nil)) + end + [] + else + @klass.find_by_sql(@relation.to_sql) + end + + @associations_to_preload.each {|associations| @klass.send(:preload_associations, @records, associations) } + @records.each { |record| record.readonly! } if @readonly + + @loaded = true + @records + end + + alias all to_a + + def first + if loaded? + @records.first + else + @first ||= limit(1).to_a[0] + end + end + + def loaded? + @loaded + end + private def method_missing(method, *args, &block) diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index d0a28c58e0..475090fbd8 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -24,6 +24,37 @@ class RelationTest < ActiveRecord::TestCase assert_no_queries { assert_equal 4, topics.size } end + def test_loaded_all + topics = Topic.scoped + + assert_queries(1) do + 2.times { assert_equal 4, topics.all.size } + end + + assert topics.loaded? + end + + def test_scoped_first + topics = Topic.scoped + + assert_queries(1) do + 2.times { assert_equal "The First Topic", topics.first.title } + end + + assert ! topics.loaded? + end + + def test_loaded_first + topics = Topic.scoped + + assert_queries(1) do + topics.all # force load + 2.times { assert_equal "The First Topic", topics.first.title } + end + + assert topics.loaded? + end + def test_finding_with_conditions assert_equal ["David"], Author.where(:name => 'David').map(&:name) assert_equal ['Mary'], Author.where(["name = ?", 'Mary']).map(&:name) @@ -141,7 +172,7 @@ class RelationTest < ActiveRecord::TestCase end end - def test_default_scope_with_conditions_string + def test_default_scope_with_conditions_string assert_equal Developer.find_all_by_name('David').map(&:id).sort, DeveloperCalledDavid.scoped.to_a.map(&:id).sort assert_equal nil, DeveloperCalledDavid.create!.name end |