9

With a regular has_many, there's the option of :dependent => :destroy to delete the associations when the parent record is deleted. With has_many :through, there might be other parents associated to the child records, so :dependent => :destroy doesn't have any effect.

How do you ensure child records are deleted after they are orphaned from the last HMT association?

Andrew Vit
  • 18,961
  • 6
  • 77
  • 84

2 Answers2

13

The solution I have found seems to be an after_destroy callback, such as this:

class Parent < ActiveRecord::Base
  has_many :children, :through => :parentage
  after_destroy :destroy_orphaned_children

  private

  def destroy_orphaned_children
    children.each do |child|
      child.destroy if child.parents.empty?
    end
  end

end
Andrew Vit
  • 18,961
  • 6
  • 77
  • 84
  • To poke into an old question/answer, I had a `has_many :through` assocation; I called `destroy` on the through model, but I wanted to delete any model on the other side of the association that may be orphaned. I placed this code inside of my through model, and since the model on the end being destroyed was only a `belongs_to`, I removed the wrapping `each` call. Thanks for the shove in the right direction. – Ben Kreeger Mar 29 '12 at 19:41
1

On the join model, use "belongs_to :model, dependent: :destroy"

for example, if you want to destroy a patient once their doctor is destroyed, and doctor has_many patients though appointments

Class Appointment
  belongs_to :doctor
  belongs_to :patient, dependent: :destroy

Class Doctor
  has_many :appointments, dependent: :destroy
  has_many :patients, through: :appointments

Class Patient
  has_many :appointments
  has_many :doctors, through: :appointments
suga_shane
  • 694
  • 10
  • 19
  • 2
    I like the idea of destroying all patients :)) – Christian Romeni Jun 06 '13 at 12:34
  • 1
    I want to destroy a patient only when ALL of his appointments are destroyed. As long as there is at least one appointment left, I want the patient to remain alive (otherwise he won't come and pay :-) Is your approach suitable for that or will it destroy the patient whenever ANY of the appointments is destroyed? – silverdr Feb 15 '17 at 13:09
  • 1
    This will destroy the patient even if they have another (different) doctor to the one being destroyed. It will also destroy the patient if the appointment is destroyed... I don't think this makes sense for the scenario you've given here - and hence the downvote. I think here it makes sense to have the `dependent: :destroy` on the `has_many :appointments` relationship in both Doctor and Patient, but that's about it. – Louis Sayers Jun 20 '18 at 05:56