Rails:迭代一个类型的所有对象,而不是一次加载它们

时间:2011-04-27 16:47:09

标签: ruby-on-rails

class Car << ActiveRecord::Base
end

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

这会将Car类型的所有对象加载到内存中(我认为)并遍历它们。我想要的是迭代遍历所有id并一次加载一个,如下所示:

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

但all_ids不存在,是否存在等价物?

4 个答案:

答案 0 :(得分:55)

对于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

答案 1 :(得分:13)

您可以使用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

答案 2 :(得分:6)

您可以执行以下操作:


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

for Rails 2.3,不熟悉3

修改

提高效率(减少查询)的一种可能解决方案:


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

答案 3 :(得分:3)

在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