mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Return rows affected from batched update_all and delete_all
The previous return value of nil was undocumented and inconsistent with the non-batched versions of these methods. Also lean on `each` to create the batches, and add API documentation for `update_all`, `delete_all`, and `destroy_all` on `BatchEnumerator`.
This commit is contained in:
parent
166b63eb67
commit
80e73ad7c1
3 changed files with 53 additions and 9 deletions
|
@ -1,3 +1,15 @@
|
||||||
|
* `BatchEnumerator#update_all` and `BatchEnumerator#delete_all` now return the
|
||||||
|
total number of rows affected, just like their non-batched counterparts.
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
Person.in_batches.update_all("first_name = 'Eugene'") # => 42
|
||||||
|
Person.in_batches.delete_all # => 42
|
||||||
|
```
|
||||||
|
|
||||||
|
Fixes #40287.
|
||||||
|
|
||||||
|
*Eugene Kenny*
|
||||||
|
|
||||||
* Add support for PostgreSQL `interval` data type with conversion to
|
* Add support for PostgreSQL `interval` data type with conversion to
|
||||||
`ActiveSupport::Duration` when loading records from database and
|
`ActiveSupport::Duration` when loading records from database and
|
||||||
serialization to ISO 8601 formatted duration string on save.
|
serialization to ISO 8601 formatted duration string on save.
|
||||||
|
|
|
@ -41,19 +41,35 @@ module ActiveRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
# Delegates #delete_all, #update_all, #destroy_all methods to each batch.
|
# Deletes records in batches. Returns the total number of rows affected.
|
||||||
#
|
#
|
||||||
# People.in_batches.delete_all
|
# Person.in_batches.delete_all
|
||||||
# People.where('age < 10').in_batches.destroy_all
|
#
|
||||||
# People.in_batches.update_all('age = age + 1')
|
# See Relation#delete_all for details of how each batch is deleted.
|
||||||
[:delete_all, :update_all, :destroy_all].each do |method|
|
def delete_all
|
||||||
define_method(method) do |*args, &block|
|
sum(&:delete_all)
|
||||||
@relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: false).each do |relation|
|
end
|
||||||
relation.public_send(method, *args, &block)
|
|
||||||
end
|
# Updates records in batches. Returns the total number of rows affected.
|
||||||
|
#
|
||||||
|
# Person.in_batches.update_all("age = age + 1")
|
||||||
|
#
|
||||||
|
# See Relation#update_all for details of how each batch is updated.
|
||||||
|
def update_all(updates)
|
||||||
|
sum do |relation|
|
||||||
|
relation.update_all(updates)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Destroys records in batches.
|
||||||
|
#
|
||||||
|
# Person.where("age < 10").in_batches.destroy_all
|
||||||
|
#
|
||||||
|
# See Relation#destroy_all for details of how each batch is destroyed.
|
||||||
|
def destroy_all
|
||||||
|
each(&:destroy_all)
|
||||||
|
end
|
||||||
|
|
||||||
# Yields an ActiveRecord::Relation object for each batch of records.
|
# Yields an ActiveRecord::Relation object for each batch of records.
|
||||||
#
|
#
|
||||||
# Person.in_batches.each do |relation|
|
# Person.in_batches.each do |relation|
|
||||||
|
|
|
@ -356,6 +356,14 @@ class EachTest < ActiveRecord::TestCase
|
||||||
assert_equal Post.all.pluck(:title), ["updated-title"] * Post.count
|
assert_equal Post.all.pluck(:title), ["updated-title"] * Post.count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_in_batches_update_all_returns_rows_affected
|
||||||
|
assert_equal 11, Post.in_batches(of: 2).update_all(title: "updated-title")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_in_batches_update_all_returns_zero_when_no_batches
|
||||||
|
assert_equal 0, Post.where("1=0").in_batches(of: 2).update_all(title: "updated-title")
|
||||||
|
end
|
||||||
|
|
||||||
def test_in_batches_delete_all_should_not_delete_records_in_other_batches
|
def test_in_batches_delete_all_should_not_delete_records_in_other_batches
|
||||||
not_deleted_count = Post.where("id <= 2").count
|
not_deleted_count = Post.where("id <= 2").count
|
||||||
Post.where("id > 2").in_batches(of: 2).delete_all
|
Post.where("id > 2").in_batches(of: 2).delete_all
|
||||||
|
@ -363,6 +371,14 @@ class EachTest < ActiveRecord::TestCase
|
||||||
assert_equal not_deleted_count, Post.count
|
assert_equal not_deleted_count, Post.count
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_in_batches_delete_all_returns_rows_affected
|
||||||
|
assert_equal 11, Post.in_batches(of: 2).delete_all
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_in_batches_delete_all_returns_zero_when_no_batches
|
||||||
|
assert_equal 0, Post.where("1=0").in_batches(of: 2).delete_all
|
||||||
|
end
|
||||||
|
|
||||||
def test_in_batches_should_not_be_loaded
|
def test_in_batches_should_not_be_loaded
|
||||||
Post.in_batches(of: 1) do |relation|
|
Post.in_batches(of: 1) do |relation|
|
||||||
assert_not_predicate relation, :loaded?
|
assert_not_predicate relation, :loaded?
|
||||||
|
|
Loading…
Reference in a new issue