aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2012-09-16 05:30:10 -0700
committerCarlos Antonio da Silva <carlosantoniodasilva@gmail.com>2012-09-16 05:30:10 -0700
commitaa81bf74574629ab585de57f5aa18689de723b9d (patch)
tree3be6eea9bbeef057a0ab55796e1e693e76af0226
parent56c60cab563a1adf778e18c5c8d0935fac26b6b8 (diff)
parent761bc751d31c22e2c2fdae2b4cdd435b68b6d783 (diff)
downloadrails-aa81bf74574629ab585de57f5aa18689de723b9d.tar.gz
rails-aa81bf74574629ab585de57f5aa18689de723b9d.tar.bz2
rails-aa81bf74574629ab585de57f5aa18689de723b9d.zip
Merge pull request #7652 from toshi-kawanishi/find_in_batches
Fix find_in_batches with customized primary_key
-rw-r--r--activerecord/CHANGELOG.md15
-rw-r--r--activerecord/lib/active_record/relation/batches.rb13
-rw-r--r--activerecord/test/cases/batches_test.rb11
-rw-r--r--activerecord/test/models/post.rb5
4 files changed, 38 insertions, 6 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 8c99a3929e..71dc960309 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,5 +1,20 @@
## Rails 4.0.0 (unreleased) ##
+* Fix `find_in_batches` when primary_key is set other than id.
+ You can now use this method with the primary key which is not integer-based.
+
+ Example:
+
+ class Post < ActiveRecord::Base
+ self.primary_key = :title
+ end
+
+ Post.find_in_batches(:start => 'My First Post') do |batch|
+ batch.each { |post| post.author.greeting }
+ end
+
+ *Toshiyuki Kawanishi*
+
* You can now override the generated accessor methods for stored attributes
and reuse the original behavior with `read_store_attribute` and `write_store_attribute`,
which are counterparts to `read_attribute` and `write_attribute`.
diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb
index 4d14506965..d32048cce1 100644
--- a/activerecord/lib/active_record/relation/batches.rb
+++ b/activerecord/lib/active_record/relation/batches.rb
@@ -36,12 +36,12 @@ module ActiveRecord
# want multiple workers dealing with the same processing queue. You can
# make worker 1 handle all the records between id 0 and 10,000 and
# worker 2 handle from 10,000 and beyond (by setting the +:start+
- # option on that worker).
+ # option on that worker). You can also use non-integer-based primary keys
+ # if start point is set.
#
# It's not possible to set the order. That is automatically set to
- # ascending on the primary key ("id ASC") to make the batch ordering
- # work. This also mean that this method only works with integer-based
- # primary keys. You can't set the limit either, that's used to control
+ # ascending on the primary key (e.g. "id ASC") to make the batch ordering
+ # work. You can't set the limit either, that's used to control
# the batch sizes.
#
# Person.where("age > 21").find_in_batches do |group|
@@ -62,7 +62,8 @@ module ActiveRecord
ActiveRecord::Base.logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size")
end
- start = options.delete(:start).to_i
+ start = options.delete(:start)
+ start ||= 0
batch_size = options.delete(:batch_size) || 1000
relation = relation.reorder(batch_order).limit(batch_size)
@@ -70,7 +71,7 @@ module ActiveRecord
while records.any?
records_size = records.size
- primary_key_offset = records.last.id
+ primary_key_offset = records.last.send(primary_key)
yield records
diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb
index cdd4b49042..3b4ff83725 100644
--- a/activerecord/test/cases/batches_test.rb
+++ b/activerecord/test/cases/batches_test.rb
@@ -124,4 +124,15 @@ class EachTest < ActiveRecord::TestCase
assert_equal special_posts_ids, posts.map(&:id)
end
+ def test_find_in_batches_should_use_any_column_as_primary_key
+ title_order_posts = Post.order('title asc')
+ start_title = title_order_posts.first.title
+
+ posts = []
+ PostWithTitlePrimaryKey.find_in_batches(:batch_size => 1, :start => start_title) do |batch|
+ posts.concat(batch)
+ end
+
+ assert_equal title_order_posts.map(&:id), posts.map(&:id)
+ end
end
diff --git a/activerecord/test/models/post.rb b/activerecord/test/models/post.rb
index c995f59a15..9858f68c4a 100644
--- a/activerecord/test/models/post.rb
+++ b/activerecord/test/models/post.rb
@@ -186,3 +186,8 @@ class SpecialPostWithDefaultScope < ActiveRecord::Base
self.table_name = 'posts'
default_scope { where(:id => [1, 5,6]) }
end
+
+class PostWithTitlePrimaryKey < ActiveRecord::Base
+ self.table_name = 'posts'
+ self.primary_key = :title
+end