Rails Batch Processing Of Records For destroy_all

July 03, 2021

In Ruby on Rails, we use destroy_all when we want to delete a collection of ActiveRecord::Relation records.

Example:

Article.where(published: false).destroy_all # Logs # Article Load (0.3ms) SELECT "articles".* FROM "articles" WHERE "articles"."published" = #? [["published", 0]] # TRANSACTION (0.1ms) begin transaction # Article Destroy (0.5ms) DELETE FROM "articles" WHERE "articles"."id" = ? [["id", 1]] # TRANSACTION (1.7ms) commit transaction # TRANSACTION (0.1ms) begin transaction # Article Destroy (0.5ms) DELETE FROM "articles" WHERE "articles"."id" = ? [["id", 2]] # TRANSACTION (1.9ms) commit transaction # Output #=> [#<Article id: 1, title: "#0 Title", published: false>, #<Article id: 2, title: "#1 Title", published: false">]

As we notice above in the logs, all the records were loaded into the memory at a time and then DELETE transaction was initiated for each record one by one.

Mark that destroy_all always returns the destroyed records as an array.

The initial load of all records at a time consumes memory unnecessarily which can be processed in batches.

To destroy records in batches, we can use in_batches and destroy_all methods defined in ActiveRecord::Batches::BatchEnumerator.

Let's refactor above example to process it in batches:

# Ruby on Rails v6.1, v7.0 Article.where(published: false).in_batches(of: 100).destroy_all


When Ruby on Rails was getting ready for v7.0 release, there was a pull request that proposed to use in_batches under the hood for destroy_all method. However that pull request was reverted after initial merge since that might break many existing applications.

Share feedback with us at:

info@scriptday.com

© All rights reserved 2022