diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb
index 96bf5dd705df1..398278883cbe9 100644
--- a/activerecord/lib/active_record/associations/association.rb
+++ b/activerecord/lib/active_record/associations/association.rb
@@ -33,7 +33,8 @@ module Associations
# owner, the collection of its posts as target, and
# the reflection object represents a :has_many macro.
class Association # :nodoc:
- attr_reader :owner, :target, :reflection, :disable_joins
+ attr_accessor :owner
+ attr_reader :target, :reflection, :disable_joins
delegate :options, to: :reflection
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index 9e9219a46b8cd..689f4ee36138f 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -1078,6 +1078,7 @@ def reload(options = nil)
end
@association_cache = fresh_object.instance_variable_get(:@association_cache)
+ @association_cache.each_value { |association| association.owner = self }
@attributes = fresh_object.instance_variable_get(:@attributes)
@new_record = false
@previously_new_record = false
diff --git a/activerecord/test/cases/persistence/reload_association_cache_test.rb b/activerecord/test/cases/persistence/reload_association_cache_test.rb
new file mode 100644
index 0000000000000..caf9d4fd10dd5
--- /dev/null
+++ b/activerecord/test/cases/persistence/reload_association_cache_test.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+require "cases/helper"
+require "models/publication"
+require "models/editorship"
+require "models/editor"
+
+class ReloadAssociationCacheTest < ActiveRecord::TestCase
+ def test_reload_sets_correct_owner_for_association_cache
+ publication = Publication.create!(name: "Rails Way")
+ assert_equal "Rails Way (touched)", publication.name
+ publication.reload
+ assert_equal "Rails Way", publication.name
+ publication.transaction do
+ publication.editors = [publication.build_editor_in_chief(name: "Alex Black")]
+ publication.save!
+ end
+ assert_equal "Rails Way (touched)", publication.name
+ end
+end
diff --git a/activerecord/test/models/editor.rb b/activerecord/test/models/editor.rb
new file mode 100644
index 0000000000000..d75f8ebea763b
--- /dev/null
+++ b/activerecord/test/models/editor.rb
@@ -0,0 +1,8 @@
+# frozen_string_literal: true
+
+class Editor < ActiveRecord::Base
+ self.primary_key = "name"
+
+ has_one :publication, foreign_key: :editor_in_chief_id, inverse_of: :editor_in_chief
+ has_many :editorships
+end
diff --git a/activerecord/test/models/editorship.rb b/activerecord/test/models/editorship.rb
new file mode 100644
index 0000000000000..2620cf5b97a5a
--- /dev/null
+++ b/activerecord/test/models/editorship.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+class Editorship < ActiveRecord::Base
+ belongs_to :publication
+ belongs_to :editor
+end
diff --git a/activerecord/test/models/publication.rb b/activerecord/test/models/publication.rb
new file mode 100644
index 0000000000000..6873709f113c2
--- /dev/null
+++ b/activerecord/test/models/publication.rb
@@ -0,0 +1,16 @@
+# frozen_string_literal: true
+
+class Publication < ActiveRecord::Base
+ belongs_to :editor_in_chief, class_name: "Editor", inverse_of: :publication, optional: true
+ has_many :editorships
+ has_many :editors, through: :editorships
+
+ after_initialize do
+ self.editor_in_chief = build_editor_in_chief(name: "John Doe")
+ end
+
+ after_save_commit :touch_name
+ def touch_name
+ self.name = "#{name} (touched)"
+ end
+end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb
index 7ba19dfcaee96..b5c6263f75d43 100644
--- a/activerecord/test/schema/schema.rb
+++ b/activerecord/test/schema/schema.rb
@@ -562,6 +562,15 @@
t.index [:source_id, :sink_id], unique: true, name: "unique_edge_index"
end
+ create_table :editorships, force: true do |t|
+ t.string :publication_id
+ t.string :editor_id
+ end
+
+ create_table :editors, force: true do |t|
+ t.string :name
+ end
+
create_table :engines, force: true do |t|
t.references :car, index: false
end
@@ -1038,6 +1047,11 @@
t.integer :mentor_id
end
+ create_table :publications, force: true do |t|
+ t.column :name, :string
+ t.integer :editor_in_chief_id
+ end
+
create_table :randomly_named_table1, force: true do |t|
t.string :some_attribute
t.integer :another_attribute