Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I delete all objects associated in a nested has_many association?

My models are:

class Campaign < ActiveRecord::Base
  has_many :days, dependent: :destroy
end

class Day < ActiveRecord::Base
  belongs_to :campaign

  has_many :time_slots
  before_destroy { time_slots.destroy_all }
end

class TimeSlot < ActiveRecord::Base
  belongs_to :day
  has_and_belongs_to_many :users
end

I would like to be able to delete a campaign and have all of its associated days, and timeslots deleted. I'd also like the records in the time_slot_users join table to be deleted.

I have tried to use dependent: :destroy, but it doesn't seem to cascade? Should I be using before_destroy callbacks?

What is the difference between destroy and destroy_all? I have read: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html#label-Delete+or+destroy%3F and the difference is still fuzzy.

like image 229
Jeffrey Guenther Avatar asked Oct 22 '22 11:10

Jeffrey Guenther


1 Answers

Here is how I did it:

class Campaign < ActiveRecord::Base
  has_many :days, dependent: :destroy
  has_many :members
  has_many :users, :through => :members
end

class Day < ActiveRecord::Base
  belongs_to :campaign
  has_many :time_slots, dependent: :destroy
end 

class TimeSlot < ActiveRecord::Base
  belongs_to :day
  has_and_belongs_to_many :users

  before_destroy do |time_slot|
      users.delete
  end
end

For the has_many relations, use dependent: :destroy. This will cause destroy to be called on each associated instance of campaign, day, and timeslot. To remove the associations between the users and the timeslot, the record in the time_slot_users, table, I added the before_destroy callback. I used delete because these rows can be removed without an object instance being created. For join tables, it is unlikely you'll have a model object anyway, so it is the only approach.

Helpful Resources:

  • ActiveRecord Callbacks
  • Activerecord Associations Delete/Destroy
like image 91
Jeffrey Guenther Avatar answered Oct 31 '22 17:10

Jeffrey Guenther