52

现在 ActiveRecord::Relation#all 在 Rails 4 中已被弃用,你应该如何迭代所有记录?

曾经是这样的:

Foo.all.each do |foo|
  # whatever
end

我现在可以像这样近似它,但感觉很脏:

Foo.where(true).each do |foo|
  # whatever
end

有没有更好的办法?

4

4 回答 4

71

根据Rails Guide on Active Record Query Interface,遍历所有记录的正确方法是使用find_each.

Using会将整个Foo.all.each表加载到内存中,实例化所有行;然后遍历实例。分批执行此操作,这在内存使用方面更有效。find_each

从指南:

find_each方法检索一批记录,然后将每个记录作为模型单独生成到块中。在以下示例中,将检索 1000 条记录(和find_each的当前默认值),然后将每条记录作为模型单独生成到块中。重复此过程,直到处理完所有记录:find_eachfind_in_batches

User.find_each do |user|
  NewsLetter.weekly_deliver(user)
end

参考:

于 2013-12-11T23:49:41.813 回答
15

是的,Foo.all

all在 ActiveRecord::Relation(例如Foo.where(true))上不推荐使用,而不是在 ActiveRecord::Base 上。

http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-all

于 2013-08-11T04:16:30.707 回答
13

Rails 4 的发行说明:

Model.all 现在返回一个 ActiveRecord::Relation,而不是一个记录数组。如果你真的想要一个数组,请使用 Relation#to_a。

因此,您的代码将如下所示:

Foo.all.to_a.each do |foo|
  # whatever
end

http://guides.rubyonrails.org/4_0_release_notes.html#active-record

于 2014-03-14T22:50:52.520 回答
0

这似乎是 Rails 中某处的不正确弃用警告。从 Rails 4.0.2 开始,警告信息仍然存在。尝试运行 Foo.all 时出现以下错误:

弃用警告:Relation#all 已弃用。如果你想预先加载一个关系,你可以调用#load(例如Post.where(published: true).load)。如果要从关系中获取记录数组,可以调用#to_a(例如Post.where(published: true).to_a)。

我几乎 100% 确定我在 RailsCasts 中看到 #all 被更改为返回 Rails 4 中的关系(而不是数组)——没有提到弃用。

于 2013-12-11T23:20:18.937 回答