Skip to content

Commit 7488910

Browse files
authored
Merge pull request rails#51066 from airblade/bidirectional-has-one-through
Fix destroy of has_one with multiple belongs_to
2 parents 7977908 + f206e93 commit 7488910

File tree

6 files changed

+34
-1
lines changed

6 files changed

+34
-1
lines changed

activerecord/lib/active_record/callbacks.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ module ClassMethods
418418

419419
def destroy # :nodoc:
420420
@_destroy_callback_already_called ||= false
421-
return if @_destroy_callback_already_called
421+
return true if @_destroy_callback_already_called
422422
@_destroy_callback_already_called = true
423423
_run_destroy_callbacks { super }
424424
rescue RecordNotDestroyed => e

activerecord/test/cases/associations/has_one_associations_test.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
require "models/membership"
2121
require "models/parrot"
2222
require "models/cpk"
23+
require "models/room"
24+
require "models/user"
2325

2426
class HasOneAssociationsTest < ActiveRecord::TestCase
2527
self.use_transactional_tests = false unless supports_savepoints?
@@ -806,6 +808,28 @@ def test_has_one_with_touch_option_on_empty_update
806808
assert_no_queries { new_club.save }
807809
end
808810

811+
def test_has_one_double_belongs_to_destroys_both_from_either_end
812+
landlord = User.create!
813+
tenant = User.create!
814+
room = Room.create!(landlord: landlord, tenant: tenant)
815+
816+
landlord.destroy!
817+
818+
assert_predicate(room, :destroyed?)
819+
assert_predicate(landlord, :destroyed?)
820+
assert_predicate(tenant, :destroyed?)
821+
822+
landlord = User.create!
823+
tenant = User.create!
824+
room = Room.create!(landlord: landlord, tenant: tenant)
825+
826+
tenant.destroy!
827+
828+
assert_predicate(room, :destroyed?)
829+
assert_predicate(tenant, :destroyed?)
830+
assert_predicate(landlord, :destroyed?)
831+
end
832+
809833
class SpecialBook < ActiveRecord::Base
810834
self.table_name = "books"
811835
belongs_to :author, class_name: "SpecialAuthor"

activerecord/test/cases/token_for_test.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
require "models/matey"
55
require "models/user"
66
require "models/cpk"
7+
require "models/room"
78
require "active_support/message_verifier"
89

910
class TokenForTest < ActiveRecord::TestCase

activerecord/test/models/room.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@
33
class Room < ActiveRecord::Base
44
belongs_to :user
55
belongs_to :owner, class_name: "User"
6+
7+
belongs_to :landlord, class_name: "User", dependent: :destroy, inverse_of: :let_room
8+
belongs_to :tenant, class_name: "User", dependent: :destroy, inverse_of: :rented_room
69
end

activerecord/test/models/user.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ class User < ActiveRecord::Base
1818
has_one :family_tree, -> { where(token: nil) }, foreign_key: "member_id"
1919
has_one :family, through: :family_tree
2020
has_many :family_members, through: :family, source: :members
21+
22+
has_one :let_room, class_name: "Room", foreign_key: "landlord_id", dependent: :destroy
23+
has_one :rented_room, class_name: "Room", foreign_key: "tenant_id", dependent: :destroy
2124
end
2225

2326
class UserWithNotification < User

activerecord/test/schema/schema.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1070,6 +1070,8 @@
10701070
create_table :rooms, force: true do |t|
10711071
t.references :user
10721072
t.references :owner
1073+
t.references :landlord
1074+
t.references :tenant
10731075
end
10741076

10751077
disable_referential_integrity do

0 commit comments

Comments
 (0)