diff options
author | Marc-Andre Lafortune <github@marc-andre.ca> | 2014-01-29 14:53:54 -0500 |
---|---|---|
committer | Marc-Andre Lafortune <github@marc-andre.ca> | 2014-02-05 16:49:29 -0500 |
commit | d37f395be86d131d0218dadd189771f99b06874f (patch) | |
tree | 2e7e4fd9e918142725a263bc61f611a787b28e38 /activerecord | |
parent | 4499ab5fdeca46416cfc4a50a376eba4eb8e16b4 (diff) | |
download | rails-d37f395be86d131d0218dadd189771f99b06874f.tar.gz rails-d37f395be86d131d0218dadd189771f99b06874f.tar.bz2 rails-d37f395be86d131d0218dadd189771f99b06874f.zip |
Return sized enumerator from Batches#find_in_batches
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG.md | 6 | ||||
-rw-r--r-- | activerecord/lib/active_record/relation/batches.rb | 13 | ||||
-rw-r--r-- | activerecord/test/cases/batches_test.rb | 10 |
3 files changed, 25 insertions, 4 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index d14b5b27f8..4bc31457c0 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,3 +1,9 @@ +* `find_in_batches` now returns an `Enumerator` that can calculate its size. + + See also #13938. + + *Marc-André Lafortune* + * Make sure transaction state gets reset after a commit operation on the record. If a new transaction was open inside a callback, the record was loosing track diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index 666cef80a9..a06da659cb 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -96,17 +96,22 @@ module ActiveRecord # the batch sizes. def find_in_batches(options = {}) options.assert_valid_keys(:start, :batch_size) - return to_enum(:find_in_batches, options) unless block_given? relation = self + start = options[:start] + batch_size = options[:batch_size] || 1000 + + unless block_given? + return to_enum(:find_in_batches, options) do + total = start ? where(table[primary_key].gteq(start)).size : size + (total - 1).div(batch_size) + 1 + end + end if logger && (arel.orders.present? || arel.taken.present?) logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size") end - start = options[:start] - batch_size = options[:batch_size] || 1000 - relation = relation.reorder(batch_order).limit(batch_size) records = start ? relation.where(table[primary_key].gteq(start)).to_a : relation.to_a diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb index 8216d74cb3..4ee09a640e 100644 --- a/activerecord/test/cases/batches_test.rb +++ b/activerecord/test/cases/batches_test.rb @@ -191,4 +191,14 @@ class EachTest < ActiveRecord::TestCase end end end + + if Enumerator.method_defined? :size + def test_find_in_batches_should_return_a_sized_enumerator + assert_equal 11, Post.find_in_batches(:batch_size => 1).size + assert_equal 6, Post.find_in_batches(:batch_size => 2).size + assert_equal 4, Post.find_in_batches(:batch_size => 2, :start => 4).size + assert_equal 4, Post.find_in_batches(:batch_size => 3).size + assert_equal 1, Post.find_in_batches(:batch_size => 10_000).size + end + end end |