Skip to content

Commit af2bbd5

Browse files
authored
Merge pull request rails#46383 from dmytro-savochkin/fix-activerecord-reload-association-cache
Ensure `reload` sets correct owner for each association (ActiveRecord::Persistence)
2 parents 883b033 + 781ecc2 commit af2bbd5

File tree

7 files changed

+67
-1
lines changed

7 files changed

+67
-1
lines changed

activerecord/lib/active_record/associations/association.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,8 @@ module Associations
3333
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
3434
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
3535
class Association # :nodoc:
36-
attr_reader :owner, :target, :reflection, :disable_joins
36+
attr_accessor :owner
37+
attr_reader :target, :reflection, :disable_joins
3738

3839
delegate :options, to: :reflection
3940

activerecord/lib/active_record/persistence.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1078,6 +1078,7 @@ def reload(options = nil)
10781078
end
10791079

10801080
@association_cache = fresh_object.instance_variable_get(:@association_cache)
1081+
@association_cache.each_value { |association| association.owner = self }
10811082
@attributes = fresh_object.instance_variable_get(:@attributes)
10821083
@new_record = false
10831084
@previously_new_record = false
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# frozen_string_literal: true
2+
3+
require "cases/helper"
4+
require "models/publication"
5+
require "models/editorship"
6+
require "models/editor"
7+
8+
class ReloadAssociationCacheTest < ActiveRecord::TestCase
9+
def test_reload_sets_correct_owner_for_association_cache
10+
publication = Publication.create!(name: "Rails Way")
11+
assert_equal "Rails Way (touched)", publication.name
12+
publication.reload
13+
assert_equal "Rails Way", publication.name
14+
publication.transaction do
15+
publication.editors = [publication.build_editor_in_chief(name: "Alex Black")]
16+
publication.save!
17+
end
18+
assert_equal "Rails Way (touched)", publication.name
19+
end
20+
end

activerecord/test/models/editor.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# frozen_string_literal: true
2+
3+
class Editor < ActiveRecord::Base
4+
self.primary_key = "name"
5+
6+
has_one :publication, foreign_key: :editor_in_chief_id, inverse_of: :editor_in_chief
7+
has_many :editorships
8+
end
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
# frozen_string_literal: true
2+
3+
class Editorship < ActiveRecord::Base
4+
belongs_to :publication
5+
belongs_to :editor
6+
end
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# frozen_string_literal: true
2+
3+
class Publication < ActiveRecord::Base
4+
belongs_to :editor_in_chief, class_name: "Editor", inverse_of: :publication, optional: true
5+
has_many :editorships
6+
has_many :editors, through: :editorships
7+
8+
after_initialize do
9+
self.editor_in_chief = build_editor_in_chief(name: "John Doe")
10+
end
11+
12+
after_save_commit :touch_name
13+
def touch_name
14+
self.name = "#{name} (touched)"
15+
end
16+
end

activerecord/test/schema/schema.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,15 @@
574574
t.index [:source_id, :sink_id], unique: true, name: "unique_edge_index"
575575
end
576576

577+
create_table :editorships, force: true do |t|
578+
t.string :publication_id
579+
t.string :editor_id
580+
end
581+
582+
create_table :editors, force: true do |t|
583+
t.string :name
584+
end
585+
577586
create_table :engines, force: true do |t|
578587
t.references :car, index: false
579588
end
@@ -1050,6 +1059,11 @@
10501059
t.integer :mentor_id
10511060
end
10521061

1062+
create_table :publications, force: true do |t|
1063+
t.column :name, :string
1064+
t.integer :editor_in_chief_id
1065+
end
1066+
10531067
create_table :randomly_named_table1, force: true do |t|
10541068
t.string :some_attribute
10551069
t.integer :another_attribute

0 commit comments

Comments
 (0)