Skip to content

Commit 42dd5d9

Browse files
committed
Fix rails#7191. Remove unnecessary transaction when assigning has_one associations.
1 parent 485e655 commit 42dd5d9

File tree

2 files changed

+28
-13
lines changed

2 files changed

+28
-13
lines changed

activerecord/lib/active_record/associations/has_one_association.rb

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,21 @@ def replace(record, save = true)
77
raise_on_type_mismatch(record) if record
88
load_target
99

10-
reflection.klass.transaction do
11-
if target && target != record
12-
remove_target!(options[:dependent]) unless target.destroyed?
13-
end
14-
15-
if record
16-
set_owner_attributes(record)
17-
set_inverse_instance(record)
18-
19-
if owner.persisted? && save && !record.save
20-
nullify_owner_attributes(record)
21-
set_owner_attributes(target) if target
22-
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
10+
# If target and record are nil, or target is equal to record,
11+
# we don't need to have transaction.
12+
if (target || record) && target != record
13+
reflection.klass.transaction do
14+
remove_target!(options[:dependent]) if target && !target.destroyed?
15+
16+
if record
17+
set_owner_attributes(record)
18+
set_inverse_instance(record)
19+
20+
if owner.persisted? && save && !record.save
21+
nullify_owner_attributes(record)
22+
set_owner_attributes(target) if target
23+
raise RecordNotSaved, "Failed to save the new associated #{reflection.name}."
24+
end
2325
end
2426
end
2527
end

activerecord/test/cases/associations/has_one_associations_test.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -535,4 +535,17 @@ def test_building_has_one_association_with_dependent_restrict
535535
ensure
536536
ActiveRecord::Base.dependent_restrict_raises = option_before
537537
end
538+
539+
def test_has_one_transaction
540+
company = companies(:first_firm)
541+
account = Account.find(1)
542+
543+
company.account # force loading
544+
assert_no_queries { company.account = account }
545+
546+
company.account = nil
547+
assert_no_queries { company.account = nil }
548+
account = Account.find(2)
549+
assert_queries { company.account = account }
550+
end
538551
end

0 commit comments

Comments
 (0)