Reputation: 14776
I am trying to perform delete_all
on an ActiveRecord relation that has a lot of rows, and one level dependents.
When I used the destroy_all
, it was of course painfully slow, since it iterated over the entire relation.
When using delete_all
, I was unable to find a way to specify that rails should also delete (not destroy) its dependents.
This is what I know and tried:
Member
model and a Message
model.has_many :messages, inverse_of: :member, dependent: :destroy
dependent: :delete_all
would delete all the dependents using one query (delete messages where member ID in [array of members to be deleted]) - it did not, and instead failed with a foreign key error.The solution I found so far is this:
# Define the Member collection we want to delete
members = Member.where comment: 'debug'
# Get all the IDs from it
ids = members.pluck :id
# Delete all the dependent Message objects first
Message.where(member_id: ids).delete_all
# Then delete the Members
members.delete_all
This is fast, and properly results in two delete queries.
My questions are:
dependent: :delete_all
definition supposed to do this for me?Upvotes: 0
Views: 354
Reputation: 31
I have also done this before where I have overridden my destroy
method. At the time, I did my extensive research and did exactly what you have done. If you end up overriding destroy
, make sure to wrap your method in a transaction. This will protect you by rolling back your deletes if you get errors in one of your dependents.
Btw, you can chain your where and pluck and save 1 call from the db.
member_ids = Member.where(comment: 'debug').pluck(:id)
Upvotes: 1