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
|
||||
`ActiveSupport::Duration` when loading records from database and
|
||||
serialization to ISO 8601 formatted duration string on save.
|
||||
|
|
|
@ -41,19 +41,35 @@ module ActiveRecord
|
|||
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
|
||||
# People.where('age < 10').in_batches.destroy_all
|
||||
# People.in_batches.update_all('age = age + 1')
|
||||
[:delete_all, :update_all, :destroy_all].each do |method|
|
||||
define_method(method) do |*args, &block|
|
||||
@relation.to_enum(:in_batches, of: @of, start: @start, finish: @finish, load: false).each do |relation|
|
||||
relation.public_send(method, *args, &block)
|
||||
end
|
||||
# Person.in_batches.delete_all
|
||||
#
|
||||
# See Relation#delete_all for details of how each batch is deleted.
|
||||
def delete_all
|
||||
sum(&:delete_all)
|
||||
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
|
||||
|
||||
# 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.
|
||||
#
|
||||
# Person.in_batches.each do |relation|
|
||||
|
|
|
@ -356,6 +356,14 @@ class EachTest < ActiveRecord::TestCase
|
|||
assert_equal Post.all.pluck(:title), ["updated-title"] * Post.count
|
||||
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
|
||||
not_deleted_count = Post.where("id <= 2").count
|
||||
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
|
||||
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
|
||||
Post.in_batches(of: 1) do |relation|
|
||||
assert_not_predicate relation, :loaded?
|
||||
|
|
Loading…
Reference in a new issue