Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure reload sets correct owner for each association (ActiveRecord::Persistence) #46383

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 2 additions & 1 deletion activerecord/lib/active_record/associations/association.rb
Expand Up @@ -33,7 +33,8 @@ module Associations
# <tt>owner</tt>, the collection of its posts as <tt>target</tt>, and
# the <tt>reflection</tt> object represents a <tt>:has_many</tt> macro.
class Association # :nodoc:
attr_reader :owner, :target, :reflection, :disable_joins
attr_accessor :owner
attr_reader :target, :reflection, :disable_joins

delegate :options, to: :reflection

Expand Down
1 change: 1 addition & 0 deletions activerecord/lib/active_record/persistence.rb
Expand Up @@ -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
Expand Down
@@ -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
8 changes: 8 additions & 0 deletions 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
6 changes: 6 additions & 0 deletions activerecord/test/models/editorship.rb
@@ -0,0 +1,6 @@
# frozen_string_literal: true

class Editorship < ActiveRecord::Base
belongs_to :publication
belongs_to :editor
end
16 changes: 16 additions & 0 deletions 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
14 changes: 14 additions & 0 deletions activerecord/test/schema/schema.rb
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down