How to Use destroy_all in Rails: Syntax and Examples
In Rails, use
destroy_all to delete all records matching a condition while running callbacks and validations. It differs from delete_all by invoking model callbacks and ensuring dependent associations are handled.Syntax
The destroy_all method is called on an ActiveRecord relation or model to delete all matching records. It runs callbacks like before_destroy and after_destroy for each record.
Model.destroy_all: Deletes all records in the model's table.Model.where(condition).destroy_all: Deletes records matching the condition.
ruby
Model.destroy_all Model.where(condition).destroy_all
Example
This example shows how to delete all users who are inactive using destroy_all. It runs callbacks for each user deleted.
ruby
class User < ApplicationRecord before_destroy :log_destroy private def log_destroy puts "Destroying user: #{id}" end end # Delete all inactive users User.where(active: false).destroy_all
Output
Destroying user: 3
Destroying user: 7
Destroying user: 12
Common Pitfalls
One common mistake is confusing destroy_all with delete_all. destroy_all runs callbacks and validations, which can slow down deletion if many records exist. delete_all deletes directly in the database without callbacks.
Another pitfall is calling destroy_all on large datasets without batching, which can cause performance issues.
ruby
## Wrong: Using delete_all when callbacks are needed User.where(active: false).delete_all ## Right: Use destroy_all to run callbacks User.where(active: false).destroy_all
Quick Reference
| Method | Description | Callbacks Run | Performance |
|---|---|---|---|
| destroy_all | Deletes records with callbacks and validations | Yes | Slower for many records |
| delete_all | Deletes records directly in DB without callbacks | No | Faster but skips callbacks |
Key Takeaways
Use destroy_all to delete records while running callbacks and validations.
destroy_all can be slower than delete_all because it processes each record.
Avoid using destroy_all on very large datasets without batching.
Use where conditions with destroy_all to target specific records.
Remember delete_all skips callbacks and should be used only when callbacks are not needed.