diff options
author | Neeraj Singh <neerajdotname@gmail.com> | 2013-05-11 00:34:25 -0400 |
---|---|---|
committer | Neeraj Singh <neerajdotname@gmail.com> | 2013-06-21 23:35:12 +0530 |
commit | 82882d4162c534e9aeef629cbbd7b5f84f45ee12 (patch) | |
tree | dfd8289327ad2cbd307a7366f2f4965d5b221fdd /activerecord | |
parent | cbc2e7987e71ff34149acaf1f9f3205f30b67174 (diff) | |
download | rails-82882d4162c534e9aeef629cbbd7b5f84f45ee12.tar.gz rails-82882d4162c534e9aeef629cbbd7b5f84f45ee12.tar.bz2 rails-82882d4162c534e9aeef629cbbd7b5f84f45ee12.zip |
do not load all child records for inverse case
currently `post.comments.find(Comment.first.id)` would load all
comments for the given post to set the inverse association.
This has a huge performance penalty. Because if post has 100k
records and all these 100k records would be loaded in memory
even though the comment id was supplied.
Fix is to use in-memory records only if loaded? is true. Otherwise
load the records using full sql.
Fixes #10509
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 16 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/collection_association.rb | 2 | ||||
-rw-r--r-- | activerecord/test/cases/associations/inverse_associations_test.rb | 8 |
3 files changed, 25 insertions, 1 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index b24222b700..608b5b64cb 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,19 @@ +* Do not load all child records for inverse case. + + currently `post.comments.find(Comment.first.id)` would load all + comments for the given post to set the inverse association. + + This has a huge performance penalty. Because if post has 100k + records and all these 100k records would be loaded in memory + even though the comment id was supplied. + + Fix is to use in-memory records only if loaded? is true. Otherwise + load the records using full sql. + + Fixes #10509. + + *Neeraj Singh* + * `inspect` on Active Record model classes does not initiate a new connection. This means that calling `inspect`, when the database is missing, will no longer raise an exception. diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index efd7ecb97c..9833822f8f 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -81,7 +81,7 @@ module ActiveRecord else if options[:finder_sql] find_by_scan(*args) - elsif options[:inverse_of] + elsif options[:inverse_of] && loaded? args = args.flatten raise RecordNotFound, "Couldn't find #{scope.klass.name} without an ID" if args.blank? diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb index d961ceca1d..71cf1237e8 100644 --- a/activerecord/test/cases/associations/inverse_associations_test.rb +++ b/activerecord/test/cases/associations/inverse_associations_test.rb @@ -401,6 +401,14 @@ class InverseHasManyTests < ActiveRecord::TestCase assert_equal man.name, man.interests.find(interest.id).man.name, "The name of the man should match after the child name is changed" end + def test_find_on_child_instance_with_id_should_not_load_all_child_records + man = Man.create! + interest = Interest.create!(man: man) + + man.interests.find(interest.id) + refute man.interests.loaded? + end + def test_raise_record_not_found_error_when_invalid_ids_are_passed # delete all interest records to ensure that hard coded invalid_id(s) # are indeed invalid. |