Rails 4 で ActiveRecord::Relation#all が非推奨になった今、すべてのレコードをどのように反復処理すればよいのでしょうか?
以前は次のようでした:
Foo.all.each do |foo|
# whatever
end
私は今それを近似することができますが、それは汚い感じです:
Foo.where(true).each do |foo|
# whatever
end
より良い方法はありますか?
Rails 4 で ActiveRecord::Relation#all が非推奨になった今、すべてのレコードをどのように反復処理すればよいのでしょうか?
以前は次のようでした:
Foo.all.each do |foo|
# whatever
end
私は今それを近似することができますが、それは汚い感じです:
Foo.where(true).each do |foo|
# whatever
end
より良い方法はありますか?
Rails Guide on Active Record Query Interfaceによると、すべてのレコードを反復処理する正しい方法は、find_each
.
を使用すると、テーブル全体Foo.all.each
がメモリにロードされ、すべての行がインスタンス化されます。次に、インスタンスを反復処理します。これは、メモリ使用量の点でより効率的なバッチで行われます。find_each
ガイドから:
この
find_each
メソッドは、レコードのバッチを取得し、各レコードをモデルとしてブロックに個別に生成します。次の例では、find_each
は 1000 レコード ( と の両方の現在のデフォルト) を取得しfind_each
、find_in_batches
各レコードを個別にモデルとしてブロックに渡します。このプロセスは、すべてのレコードが処理されるまで繰り返されます。
User.find_each do |user|
NewsLetter.weekly_deliver(user)
end
参考文献:
はいFoo.all
。
all
Foo.where(true)
は、ActiveRecord::Base ではなく、ActiveRecord::Relation (例: ) では非推奨です。
http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Named/ClassMethods.html#method-i-all
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を参照
これは、Rails のどこかで誤った非推奨の警告のようです。Rails 4.0.2 の時点で、警告メッセージはまだ存在します。Foo.all を実行しようとすると、次のエラーが発生します。
非推奨の警告: Relation#all は非推奨です。リレーションをeager-loadしたい場合は、#load (例:
Post.where(published: true).load
) を呼び出すことができます。リレーションからレコードの配列を取得したい場合は、#to_a を呼び出すことができます (例:Post.where(published: true).to_a
)。
Rails 4 で (配列ではなく) Relation を返すように #all が変更されていることを RailsCasts で見たのをほぼ 100% 確信しています。