1
0
Fork 0
mirror of https://github.com/rails/rails.git synced 2022-11-09 12:12:34 -05:00

Do not instantiate intermediate AR objects when eager loading.

Closes #3313
This commit is contained in:
Yves Senn 2012-12-02 21:24:47 +01:00 committed by Yves Senn
parent c7e4ee7932
commit db51704bd9
4 changed files with 26 additions and 2 deletions

View file

@ -1,5 +1,11 @@
## Rails 4.0.0 (unreleased) ##
* Do not instantiate intermediate Active Record objects when eager loading.
These records caused `after_find` to run more than expected.
Fix #3313
*Yves Senn*
* Add STI support to init and building associations.
Allows you to do BaseClass.new(:type => "SubClass") as well as
parent.children.build(:type => "SubClass") or parent.build_child

View file

@ -225,9 +225,11 @@ module ActiveRecord
orders = relation.order_values.map { |val| val.presence }.compact
values = @klass.connection.distinct("#{quoted_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

View file

@ -944,6 +944,12 @@ class EagerAssociationTest < ActiveRecord::TestCase
assert_equal 3, Developer.all.merge!(:includes => 'projects', :where => { 'developers_projects.access_level' => 1 }, :limit => 5).to_a.size
end
def test_dont_create_temporary_active_record_instances
Developer.instance_count = 0
developers = Developer.all.merge!(:includes => 'projects', :where => { '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.all.merge!(:includes => 'projects', :order => 'developers_projects.joined_on DESC', :limit => 5).to_a.size
end

View file

@ -57,6 +57,16 @@ class Developer < ActiveRecord::Base
def log=(message)
audit_logs.build :message => message
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