aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--activerecord/CHANGELOG.md7
-rw-r--r--activerecord/lib/active_record/relation/finder_methods.rb6
-rw-r--r--activerecord/test/cases/associations/eager_test.rb6
-rw-r--r--activerecord/test/models/developer.rb9
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