Skip to content

Commit 1b6b1a9

Browse files
authored
Merge pull request rails#51788 from fatkodima/batch_enumerator-destroy_all-returns-rows-number
Change `BatchEnumerator#destroy_all` to return the total number of affected rows
2 parents a8d2678 + 94af7c1 commit 1b6b1a9

File tree

4 files changed

+39
-3
lines changed

4 files changed

+39
-3
lines changed

activerecord/CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
1+
* Change `BatchEnumerator#destroy_all` to return the total number of affected rows.
2+
3+
Previously, it always returned `nil`.
4+
5+
*fatkodima*
16

27
Please check [7-2-stable](https://github.com/rails/rails/blob/7-2-stable/activerecord/CHANGELOG.md) for previous changes.

activerecord/lib/active_record/relation/batches/batch_enumerator.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,15 @@ def touch_all(...)
8888
end
8989
end
9090

91-
# Destroys records in batches.
91+
# Destroys records in batches. Returns the total number of rows affected.
9292
#
9393
# Person.where("age < 10").in_batches.destroy_all
9494
#
9595
# See Relation#destroy_all for details of how each batch is destroyed.
9696
def destroy_all
97-
each(&:destroy_all)
97+
sum do |relation|
98+
relation.destroy_all.count(&:destroyed?)
99+
end
98100
end
99101

100102
# Yields an ActiveRecord::Relation object for each batch of records.

activerecord/test/cases/batches_test.rb

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# frozen_string_literal: true
22

33
require "cases/helper"
4-
require "models/comment"
54
require "models/post"
65
require "models/subscriber"
76
require "models/developer"
@@ -416,6 +415,22 @@ def test_in_batches_delete_all_returns_zero_when_no_batches
416415
assert_equal 0, Post.where("1=0").in_batches(of: 2).delete_all
417416
end
418417

418+
def test_in_batches_destroy_all_should_not_destroy_records_in_other_batches
419+
not_destroyed_count = Post.where("id <= 2").count
420+
Post.where("id > 2").in_batches(of: 2).destroy_all
421+
assert_equal 0, Post.where("id > 2").count
422+
assert_equal not_destroyed_count, Post.count
423+
end
424+
425+
def test_in_batches_destroy_all_returns_rows_affected
426+
# 1 records is not destroyed because of the callback.
427+
assert_equal 10, PostWithDestroyCallback.in_batches(of: 2).destroy_all
428+
end
429+
430+
def test_in_batches_destroy_all_returns_zero_when_no_batches
431+
assert_equal 0, Post.where("1=0").in_batches(of: 2).destroy_all
432+
end
433+
419434
def test_in_batches_should_not_be_loaded
420435
Post.in_batches(of: 1) do |relation|
421436
assert_not_predicate relation, :loaded?

activerecord/test/models/post.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
# frozen_string_literal: true
22

3+
require "models/tag"
4+
require "models/tagging"
5+
require "models/comment"
6+
require "models/category"
7+
38
class Post < ActiveRecord::Base
49
class CategoryPost < ActiveRecord::Base
510
self.table_name = "categories_posts"
@@ -329,6 +334,15 @@ class ConditionalStiPost < Post
329334
class SubConditionalStiPost < ConditionalStiPost
330335
end
331336

337+
class PostWithDestroyCallback < ActiveRecord::Base
338+
self.inheritance_column = :disabled
339+
self.table_name = "posts"
340+
341+
before_destroy do
342+
throw :abort if id == 1
343+
end
344+
end
345+
332346
class FakeKlass
333347
extend ActiveRecord::Delegation::DelegateCache
334348

0 commit comments

Comments
 (0)