In Rails how do I use find_each method with index?

Your question is already implemented in the Rails master branch. To get this, it requires using Rails edge, as this has not been merged into any release as of yet. See this merged pull request: https://github.com/rails/rails/pull/10992.

So add this to your Gemfile:

gem 'rails', github: 'rails/rails'

This will allow you to run the code you described:

User.find_each(batch_size: 10000).with_index do |user, index|
  puts "UserID: #{user.id.to_s} has index ##{index.to_s}"
end

Granted, running on the edge release is risky, so don't do this in production. But look at the pull request to see the small amount of code added to get this working. You can monkey patch until it is merged into a Rails release.


Update: As of Rails 4.1.4 this is possible. See this answer for more. Example:

User.find_each(:batch_size => 1000).with_index do |user, index|
  user.call_method(index)
end

As you can see from the method definition, this is not possible.

def find_each(options = {})
  find_in_batches(options) do |records|
    records.each { |record| yield record }
  end
end

In order to accomplish what you want to do, you need to either create your own modified version of the method

class User
  def find_each(options = {})
    find_in_batches(options) do |records|
      records.each_with_index { |record| yield record, index }
    end
  end
end

User.find_each(:batch_size => 10000) do |user, index|
  ------
end 

or use an instance variable.

index = 0
User.find_each(:batch_size => 10000) do |user|
  # ...
  index += 1
end 

There is no other default solution as shown by the method implementation.


As an update to this question. Active Record 4.1.4 has added support for find_each.with_index as pointed in the documentation.

User.find_each(:batch_size => 1000).with_index do |user, index|
  user.call_method(index)
end