Skip to content

Commit

Permalink
When preloading has_and_belongs_to_many associations, we should only …
Browse files Browse the repository at this point in the history
…instantiate one AR object per actual record in the database. (Even when IM is off.)
  • Loading branch information
jonleighton committed Mar 4, 2011
1 parent a5ef8b9 commit 73c0b39
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 2 deletions.
Expand Up @@ -31,10 +31,12 @@ def association_key
private

# Once we have used the join table column (in super), we manually instantiate the
# actual records
# actual records, ensuring that we don't create more than one instances of the same
# record
def associated_records_by_owner
records = {}
super.each do |owner_key, rows|
rows.map! { |row| klass.instantiate(row) }
rows.map! { |row| records[row[klass.primary_key]] ||= klass.instantiate(row) }
end
end

Expand Down
16 changes: 16 additions & 0 deletions activerecord/test/cases/associations/eager_test.rb
Expand Up @@ -525,6 +525,22 @@ def test_eager_with_has_and_belongs_to_many_and_limit
assert posts[1].categories.include?(categories(:general))
end

# This is only really relevant when the identity map is off. Since the preloader for habtm
# gets raw row hashes from the database and then instantiates them, this test ensures that
# it only instantiates one actual object per record from the database.
def test_has_and_belongs_to_many_should_not_instantiate_same_records_multiple_times
welcome = posts(:welcome)
categories = Category.includes(:posts)

general = categories.find { |c| c == categories(:general) }
technology = categories.find { |c| c == categories(:technology) }

post1 = general.posts.to_a.find { |p| p == posts(:welcome) }
post2 = technology.posts.to_a.find { |p| p == posts(:welcome) }

assert_equal post1.object_id, post2.object_id
end

def test_eager_with_has_many_and_limit_and_conditions_on_the_eagers
posts = authors(:david).posts.find(:all,
:include => :comments,
Expand Down

0 comments on commit 73c0b39

Please sign in to comment.