Rails 6 adds delete_by and destroy_by methods on ActiveRecord

Akshay MohiteBy Akshay Mohite in RailsActiveRecord on December 3, 2019

Often we need to find records based on certain conditions and then delete those records. To perform this, ActiveRecord has introduced delete_by and destroy_by methods in Rails 6.

Let’s say, we have a following model.

class Post < ApplicationRecord {
  :id          => :integer,
  :user_id     => :integer,
  :title       => :string,
  :description => :text,
  :status      => :string,
  :created_at  => :datetime,
  :updated_at  => :datetime

Requirement: Delete all posts created by a user with ID 5.

Before Rails 6

This can be done by using delete_all as given below.

Post.where(user_id: 5).delete_all Similarly, if we want to destroy all records, we can use destroy_all as given below.

Post.where(user_id: 5).destroy_all

The difference between delete_all and destroy_all is that, delete_all does not run callbacks defined over the corresponding model.

After Rails 6

As this feature of querying records based on some conditions and then deleting / destroying is required quite often, Rails 6 introduces delete_by and destroy_by methods.

Delete records by condition

Post.delete_by(user_id: 5)

Destroy records by condition

Post.destroy_by(user_id: 5)

It can also be used with associations as given below. Let’s say, we want to delete all posts of user with id 5 having status unpublished.

User.where(id: 5).posts.delete_by(status: 'unpublished')


As you can observe, delete_by / destroy_by, these are just short-hands for operations where(condition).delete_all and where(condition).destroy_all respectively.