aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord
diff options
context:
space:
mode:
authorRyuta Kamizono <kamipo@gmail.com>2018-10-10 16:51:14 +0900
committerGitHub <noreply@github.com>2018-10-10 16:51:14 +0900
commit6c69a96048f61b280076412eab37c9134ddb7440 (patch)
treed1083c380207d34459d46171f849d12b2e13ebad /activerecord
parent301409a98f2bef4f431a10cae74a3430bbaca9c2 (diff)
parent961776832d13b4cea7f67aface2c2882416ac975 (diff)
downloadrails-6c69a96048f61b280076412eab37c9134ddb7440.tar.gz
rails-6c69a96048f61b280076412eab37c9134ddb7440.tar.bz2
rails-6c69a96048f61b280076412eab37c9134ddb7440.zip
Merge pull request #34094 from christophemaximin/fix-activerecord-clearing-of-query-cache
Fix inconsistent behavior by clearing QueryCache when reloading associations
Diffstat (limited to 'activerecord')
-rw-r--r--activerecord/CHANGELOG.md17
-rw-r--r--activerecord/lib/active_record/associations/association.rb4
-rw-r--r--activerecord/lib/active_record/associations/collection_proxy.rb2
-rw-r--r--activerecord/lib/active_record/associations/singular_association.rb2
-rw-r--r--activerecord/test/cases/associations/belongs_to_associations_test.rb24
-rw-r--r--activerecord/test/cases/associations/has_many_associations_test.rb42
-rw-r--r--activerecord/test/cases/associations/has_one_associations_test.rb23
7 files changed, 111 insertions, 3 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 96fd6a62c6..19558a9e0c 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,20 @@
+* Reloading associations now clears the Query Cache like `Persistence#reload` does.
+
+ ```
+ class Post < ActiveRecord::Base
+ has_one :category
+ belongs_to :author
+ has_many :comments
+ end
+
+ # Each of the following will now clear the query cache.
+ post.reload_category
+ post.reload_author
+ post.comments.reload
+ ```
+
+ *Christophe Maximin*
+
* Added `index` option for `change_table` migration helpers.
With this change you can create indexes while adding new
columns into the existing tables.
diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 4686b9f517..bf4942aac8 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -40,7 +40,9 @@ module ActiveRecord
end
# Reloads the \target and returns +self+ on success.
- def reload
+ # The QueryCache is cleared if +force+ is true.
+ def reload(force = false)
+ klass.connection.clear_query_cache if force && klass
reset
reset_scope
load_target
diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb
index 9a30198b95..08b7c9274d 100644
--- a/activerecord/lib/active_record/associations/collection_proxy.rb
+++ b/activerecord/lib/active_record/associations/collection_proxy.rb
@@ -1088,7 +1088,7 @@ module ActiveRecord
# person.pets.reload # fetches pets from the database
# # => [#<Pet id: 1, name: "Snoop", group: "dogs", person_id: 1>]
def reload
- proxy_association.reload
+ proxy_association.reload(true)
reset_scope
end
diff --git a/activerecord/lib/active_record/associations/singular_association.rb b/activerecord/lib/active_record/associations/singular_association.rb
index cfab16a745..8e50cce102 100644
--- a/activerecord/lib/active_record/associations/singular_association.rb
+++ b/activerecord/lib/active_record/associations/singular_association.rb
@@ -26,7 +26,7 @@ module ActiveRecord
# Implements the reload reader method, e.g. foo.reload_bar for
# Foo.has_one :bar
def force_reload_reader
- klass.uncached { reload }
+ reload(true)
target
end
diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb
index d520919332..93dd427951 100644
--- a/activerecord/test/cases/associations/belongs_to_associations_test.rb
+++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb
@@ -367,6 +367,30 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase
assert_equal "ODEGY", odegy_account.reload_firm.name
end
+ def test_reload_the_belonging_object_with_query_cache
+ odegy_account_id = accounts(:odegy_account).id
+
+ connection = ActiveRecord::Base.connection
+ connection.enable_query_cache!
+ connection.clear_query_cache
+
+ # Populate the cache with a query
+ odegy_account = Account.find(odegy_account_id)
+
+ # Populate the cache with a second query
+ odegy_account.firm
+
+ assert_equal 2, connection.query_cache.size
+
+ # Clear the cache and fetch the firm again, populating the cache with a query
+ assert_queries(1) { odegy_account.reload_firm }
+
+ # This query is not cached anymore, so it should make a real SQL query
+ assert_queries(1) { Account.find(odegy_account_id) }
+ ensure
+ ActiveRecord::Base.connection.disable_query_cache!
+ end
+
def test_natural_assignment_to_nil
client = Client.find(3)
client.firm = nil
diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb
index eb65f9e74f..c1074b90a0 100644
--- a/activerecord/test/cases/associations/has_many_associations_test.rb
+++ b/activerecord/test/cases/associations/has_many_associations_test.rb
@@ -829,6 +829,48 @@ class HasManyAssociationsTest < ActiveRecord::TestCase
assert_not_same original_object, collection.first, "Expected #first after #reload to return a new object"
end
+ def test_reload_with_query_cache
+ connection = ActiveRecord::Base.connection
+ connection.enable_query_cache!
+ connection.clear_query_cache
+
+ # Populate the cache with a query
+ firm = Firm.first
+ # Populate the cache with a second query
+ firm.clients.load
+
+ assert_equal 2, connection.query_cache.size
+
+ # Clear the cache and fetch the clients again, populating the cache with a query
+ assert_queries(1) { firm.clients.reload }
+ # This query is cached, so it shouldn't make a real SQL query
+ assert_queries(0) { firm.clients.load }
+
+ assert_equal 1, connection.query_cache.size
+ ensure
+ ActiveRecord::Base.connection.disable_query_cache!
+ end
+
+ def test_reloading_unloaded_associations_with_query_cache
+ connection = ActiveRecord::Base.connection
+ connection.enable_query_cache!
+ connection.clear_query_cache
+
+ firm = Firm.create!(name: "firm name")
+ client = firm.clients.create!(name: "client name")
+ firm.clients.to_a # add request to cache
+
+ connection.uncached do
+ client.update!(name: "new client name")
+ end
+
+ firm = Firm.find(firm.id)
+
+ assert_equal [client.name], firm.clients.reload.map(&:name)
+ ensure
+ ActiveRecord::Base.connection.disable_query_cache!
+ end
+
def test_find_all_with_include_and_conditions
assert_nothing_raised do
Developer.all.merge!(joins: :audit_logs, where: { "audit_logs.message" => nil, :name => "Smith" }).to_a
diff --git a/activerecord/test/cases/associations/has_one_associations_test.rb b/activerecord/test/cases/associations/has_one_associations_test.rb
index 801720b214..adfb3ce072 100644
--- a/activerecord/test/cases/associations/has_one_associations_test.rb
+++ b/activerecord/test/cases/associations/has_one_associations_test.rb
@@ -333,6 +333,29 @@ class HasOneAssociationsTest < ActiveRecord::TestCase
assert_equal 80, odegy.reload_account.credit_limit
end
+ def test_reload_association_with_query_cache
+ odegy_id = companies(:odegy).id
+
+ connection = ActiveRecord::Base.connection
+ connection.enable_query_cache!
+ connection.clear_query_cache
+
+ # Populate the cache with a query
+ odegy = Company.find(odegy_id)
+ # Populate the cache with a second query
+ odegy.account
+
+ assert_equal 2, connection.query_cache.size
+
+ # Clear the cache and fetch the account again, populating the cache with a query
+ assert_queries(1) { odegy.reload_account }
+
+ # This query is not cached anymore, so it should make a real SQL query
+ assert_queries(1) { Company.find(odegy_id) }
+ ensure
+ ActiveRecord::Base.connection.disable_query_cache!
+ end
+
def test_build
firm = Firm.new("name" => "GlobalMegaCorp")
firm.save