aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorPratik Naik <pratiknaik@gmail.com>2009-12-26 15:07:00 +0530
committerPratik Naik <pratiknaik@gmail.com>2009-12-26 15:07:00 +0530
commit3c5a7dcaf55f427f3a48e206feb06410d011ca4f (patch)
tree1eed5483a1c1d2ad6e7a6d83408cf509c4e7b8c1 /activerecord
parent9d3d60c64a9ce69b9932f5c543112199e576c2ad (diff)
downloadrails-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.rb75
-rw-r--r--activerecord/test/cases/relations_test.rb33
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