delete_all vs destroy_all?

Ruby on-RailsRubyDatabaseActiverecord

Ruby on-Rails Problem Overview


I am looking for the best approach to delete records from a table. For instance, I have a user whose user ID is across many tables. I want to delete this user and every record that has his ID in all tables.

u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all
u.sources.destroy_all
u.user_stats.destroy_all
u.delete

This works and removes all references of the user from all tables, but I heard that destroy_all was very process heavy, so I tried delete_all. It only removes the user from his own user table and the id from all the other tables are made null, but leaves the records intact in them. Can someone share what the correct process is for performing a task like this?

I see that destroy_all calls the destroy function on all associated objects but I just want to confirm the correct approach.

Ruby on-Rails Solutions


Solution 1 - Ruby on-Rails

You are right. If you want to delete the User and all associated objects -> destroy_all However, if you just want to delete the User without suppressing all associated objects -> delete_all

According to this post : https://stackoverflow.com/questions/2797339/rails-dependent-destroy-vs-dependent-delete-all

  • destroy / destroy_all: The associated objects are destroyed alongside this object by calling their destroy method
  • delete / delete_all: All associated objects are destroyed immediately without calling their :destroy method

Solution 2 - Ruby on-Rails

delete_all is a single SQL DELETE statement and nothing more. destroy_all calls destroy() on all matching results of :conditions (if you have one) which could be at least NUM_OF_RESULTS SQL statements.

If you have to do something drastic such as destroy_all() on large dataset, I would probably not do it from the app and handle it manually with care. If the dataset is small enough, you wouldn't hurt as much.

Solution 3 - Ruby on-Rails

To avoid the fact that destroy_all instantiates all the records and destroys them one at a time, you can use it directly from the model class.

So instead of :

u = User.find_by_name('JohnBoy')
u.usage_indexes.destroy_all

You can do :

u = User.find_by_name('JohnBoy')
UsageIndex.destroy_all "user_id = #{u.id}"

The result is one query to destroy all the associated records

Solution 4 - Ruby on-Rails

I’ve made a small gem that can alleviate the need to manually delete associated records in some circumstances.

>This gem adds a new option for ActiveRecord associations: > >dependent: :delete_recursively > >When you destroy a record, all records that are associated using this option will be deleted recursively (i.e. across models), without instantiating any of them. > >Note that, just like dependent: :delete or dependent: :delete_all, this new option does not trigger the around/before/after_destroy callbacks of the dependent records. > >However, it is possible to have dependent: :destroy associations anywhere within a chain of models that are otherwise associated with dependent: :delete_recursively. The :destroy option will work normally anywhere up or down the line, instantiating and destroying all relevant records and thus also triggering their callbacks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionglogicView Question on Stackoverflow
Solution 1 - Ruby on-RailsSandro MundaView Answer on Stackoverflow
Solution 2 - Ruby on-RailsRyan HerView Answer on Stackoverflow
Solution 3 - Ruby on-Railssimon-olivierView Answer on Stackoverflow
Solution 4 - Ruby on-RailsJanoschView Answer on Stackoverflow