В Rails как использовать метод find_each с индексом?
Я могу использовать метод Rails find_each, например:
User.find_each(:batch_size => 10000) do |user|
------
end
С методом find_each есть ли способ получить индекс массива? как:
User.find_each(:batch_size => 10000).with_index do |user, index|
------
end
Ответы
Ответ 1
Как видно из определения метода, это невозможно.
def find_each(options = {})
find_in_batches(options) do |records|
records.each { |record| yield record }
end
end
Чтобы выполнить то, что вы хотите сделать, вам нужно либо создать свою собственную модифицированную версию метода
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
или используйте переменную экземпляра.
index = 0
User.find_each(:batch_size => 10000) do |user|
# ...
index += 1
end
Нет другого решения по умолчанию, как показано в реализации метода.
Ответ 2
Как обновление этого вопроса. Active Record 4.1.4 добавила поддержку find_each.with_index
как указано в документации.
User.find_each(:batch_size => 1000).with_index do |user, index|
user.call_method(index)
end
Ответ 3
Ваш вопрос уже реализован в главной ветке Rails. Чтобы получить это, для этого требуется использовать Rails edge, так как это еще не слилось ни с одной версией. См. Этот запрос с объединенным тягой: https://github.com/rails/rails/pull/10992.
Поэтому добавьте это в свой Gemfile:
gem 'rails', github: 'rails/rails'
Это позволит вам запустить код, который вы описали:
User.find_each(batch_size: 10000).with_index do |user, index|
puts "UserID: #{user.id.to_s} has index ##{index.to_s}"
end
Разумеется, работа на выпуске края опасна, поэтому не делайте этого в процессе производства. Но посмотрите на запрос на pull, чтобы увидеть небольшое количество добавленного кода, чтобы заставить это работать. Вы можете патч обезьяны, пока он не будет объединен в релиз Rails.
Ответ 4
Просто используйте локальную переменную:
index = 0
User.find_each(:batch_size => 10000) do |user|
------
index += 1
end
Ответ 5
Вы можете получить всех пользователей и отправить их через блок вместе со своим соответствующим индексом следующим образом.
User.all.each_with_index do |user, index|
puts "email is " + "#{user.email}" + " and user index is " + "#{index}"
end