From c82cc222c793275f74fc5e8b6aa88edebe136929 Mon Sep 17 00:00:00 2001 From: Ben Woosley Date: Sun, 15 Mar 2015 16:13:54 -0700 Subject: Reuse the CollectionAssociation#reader proxy cache if the foreign key is present from the start. When a new record has the necessary information prior to save, we can avoid busting the cache. We could simply clear the @proxy on #reset or #reset_scope, but that would clear the cache more often than necessary. --- activerecord/CHANGELOG.md | 5 +++++ .../lib/active_record/associations/collection_association.rb | 4 ++-- .../test/cases/associations/has_many_associations_test.rb | 12 ++++++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index a011579124..b6e74cdbbc 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,8 @@ +* Reuse the `CollectionAssociation#reader` cache when the foreign key is + available prior to save. + + *Ben Woosley* + * Increase pg gem version requirement to `~> 0.18`. Earlier versions of the pg gem are known to have problems with Ruby 2.2. diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 1e245926e0..88531205a1 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -33,10 +33,10 @@ module ActiveRecord reload end - if owner.new_record? + if null_scope? # Cache the proxy separately before the owner has an id # or else a post-save proxy will still lack the id - @new_record_proxy ||= CollectionProxy.create(klass, self) + @null_proxy ||= CollectionProxy.create(klass, self) else @proxy ||= CollectionProxy.create(klass, self) end diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index 675bed9bfa..290b2a0d6b 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -532,9 +532,21 @@ class HasManyAssociationsTest < ActiveRecord::TestCase def test_update_all_on_association_accessed_before_save firm = Firm.new(name: 'Firm') + clients_proxy_id = firm.clients.object_id firm.clients << Client.first firm.save! assert_equal firm.clients.count, firm.clients.update_all(description: 'Great!') + assert_not_equal clients_proxy_id, firm.clients.object_id + end + + def test_update_all_on_association_accessed_before_save_with_explicit_foreign_key + # We can use the same cached proxy object because the id is available for the scope + firm = Firm.new(name: 'Firm', id: 100) + clients_proxy_id = firm.clients.object_id + firm.clients << Client.first + firm.save! + assert_equal firm.clients.count, firm.clients.update_all(description: 'Great!') + assert_equal clients_proxy_id, firm.clients.object_id end def test_belongs_to_sanity -- cgit v1.2.3