From 1b961765871eba76d50d463d3af6c3c5926f537a Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Sun, 2 Dec 2012 21:24:47 +0100 Subject: backport #8403, no intermediate AR objects when eager loading. Closes #3313 Conflicts: activerecord/CHANGELOG.md activerecord/test/models/developer.rb --- activerecord/CHANGELOG.md | 7 +++++++ activerecord/lib/active_record/relation/finder_methods.rb | 6 ++++-- activerecord/test/cases/associations/eager_test.rb | 6 ++++++ activerecord/test/models/developer.rb | 9 +++++++++ 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 68a48e6431..fcc4f044f0 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,12 @@ ## Rails 3.2.10 (unreleased) +* Do not instantiate intermediate Active Record objects when eager loading. + These records caused `after_find` to run more than expected. + Fix #3313 + Backport of #8403 + + *Yves Senn* + * Fix `pluck` to work with joins. Backport of #4942. *Carlos Antonio da Silva* diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 57ecabb537..cbb2f676c8 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -253,9 +253,11 @@ module ActiveRecord orders = relation.order_values.map { |val| val.presence }.compact values = @klass.connection.distinct("#{@klass.connection.quote_table_name table_name}.#{primary_key}", orders) - relation = relation.dup + relation = relation.dup.select(values) + + id_rows = @klass.connection.select_all(relation.arel, 'SQL', relation.bind_values) + ids_array = id_rows.map {|row| row[primary_key]} - ids_array = relation.select(values).collect {|row| row[primary_key]} ids_array.empty? ? raise(ThrowResult) : table[primary_key].in(ids_array) end diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index bf01b46852..d3601e0dba 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -916,6 +916,12 @@ class EagerAssociationTest < ActiveRecord::TestCase assert_equal 3, Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).size end + def test_dont_create_temporary_active_record_instances + Developer.instance_count = 0 + developers = Developer.find(:all, :include => 'projects', :conditions => 'developers_projects.access_level = 1', :limit => 5).to_a + assert_equal developers.count, Developer.instance_count + end + def test_order_on_join_table_with_include_and_limit assert_equal 5, Developer.find(:all, :include => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).size end diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index 4dc9fff9fd..a730d86586 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -63,6 +63,15 @@ class Developer < ActiveRecord::Base self.all end end + + after_find :track_instance_count + cattr_accessor :instance_count + + def track_instance_count + self.class.instance_count ||= 0 + self.class.instance_count += 1 + end + private :track_instance_count end class AuditLog < ActiveRecord::Base -- cgit v1.2.3