rails icon indicating copy to clipboard operation
rails copied to clipboard

Fix bi-directional destroying of has_one :through

Open airblade opened this issue 4 months ago • 0 comments

With a bi-directional has one through association, where the join model belongs to each parent with dependent: :destroy, destroying either parent should destroy the through record and the other parent.

class Left < ActiveRecord::Base
  has_one :middle, dependent: :destroy
  has_one :right, through: :middle
end

class Middle < ActiveRecord::Base
  belongs_to :left, dependent: :destroy
  belongs_to :right, dependent: :destroy
end

class Right < ActiveRecord::Base
  has_one :middle, dependent: :destroy
  has_one :left, through: :middle
end

However this only worked from one end. When destroying the "non-working" end, the join model was correctly destroyed but the other end was not.

In the example above:

  • right.destroy correctly destroys its middle and its left;
  • left.destroy destroys its middle but not its right.

The end which worked depended on the order of belongs_to statements in the join model.

This commit ensures that the no matter which end you destroy, the far end is destroyed (along with the join record).

Fixes #50948.

Checklist

Before submitting the PR make sure the following are checked:

  • [x] This Pull Request is related to one change. Changes that are unrelated should be opened in separate PRs.
  • [x] Commit message has a detailed description of what changed and why. If this PR fixes a related issue include it in the commit message. Ex: [Fix #issue-number]
  • [x] Tests are added or updated if you fix a bug or add a feature.
  • [ ] CHANGELOG files are updated for the changed libraries if there is a behavior change or additional feature. Minor bug fixes and documentation changes should not be included.

airblade avatar Feb 13 '24 16:02 airblade