Подтвердить что ты не робот

Rails: итерация по всем объектам типа без загрузки их сразу

class Car << ActiveRecord::Base
end

Car.all.each do |car|
  # do stuff
end

Это загружает все объекты типа Car в память (я думаю) и повторяется через них. Вместо этого я хочу перебрать все идентификаторы и загрузить их по одному так:

Car.all_ids.each do |id|
  c = Car.find id
  # do stuff
end

Но all_ids не существует, есть ли эквивалент?

4b9b3361

Ответ 1

Вы можете сделать следующее:


Car.find(:all, :select => :id).each do |car_id|
  c = Car.find(car_id.id)
end

для Rails 2.3, не знакомый с 3 еще

Edit

Одним из возможных решений является более эффективное (меньше запросов):


Car.find(:all, :select => :id).map(&:id).each_slice(5) do |ids|
  cars_slice = Car.find(ids)
end

Ответ 2

Для Rails 2.3 и выше (включая Rails 3) самым простым решением является find_each:

Car.find_each do |car|
  # do stuff
end

Выполняет запрос автоматически, автоматически. Размер партии по умолчанию - 1000, но вы можете установить свой собственный. Он также работает вместе с названными областями и ActiveRecord:: Relations:

Car.hotrods.where(:color => 'red').find_each(:batch_size => 10) { do |car| ... }

См. http://guides.rubyonrails.org/active_record_querying.html#retrieving-multiple-objects-in-batches

Ответ 3

Вы можете использовать find_in_batches, который извлекает записи x за раз, где x настраивается и по умолчанию 1000.

  Person.where("age > 21").find_in_batches do |group|
    # group is an array of 1000 records
    group.each { |person| person.party_all_night! }
  end

Ответ 4

В Rails 4+ я нахожу pluck очень полезным.

Car.pluck(:id).each do |id|
  c = Car.find id
  # do stuff
end

Car.pluck(:id) возвращает массив записей. Вы можете вырезать любой другой столбец вашей модели, изменив параметр. Кроме того, вы можете вырвать комбинацию столбцов. Например:

Car.pluck(:id, :make, :model).each do |id, make, model|
  c = Car.find id
  # access make and model as well
end