ActiveRecordのfind_eachでorderを指定できるようにする


はじめに

大量のレコードを扱うときに便利な find_each は order での順序指定ができません。その理由は http://qiita.com/yugo-yamamoto/items/5569c037e8917fdb59ae にある通り。

とはいえ、簡易なアプリを作成するにあたって find_each_with_order があったら良いなぁというので探してみたらこんな記事を見つけたので http://grosser.it/2009/09/09/activerecord-find_each_with_order-find_each-with-order/ rails4で使えるように書きなおしました。

見ての通り、limitとoffsetを使うのでパフォーマンスを求める場面では使えません。全件持ってくるのはメモリ的に無理だけど、多少効率悪いのは問題ない、くらいな状況では使っても良いかも。

ソース

こんな感じ

class ActiveRecord::Base
  def self.find_each_with_order(options={})
    page = 1
    limit = options[:limit] || 1000

    while
      offset = (page-1) * limit
      batch = limit(limit).offset(offset)
      page += 1

      batch.each{|x| yield x }

      break if batch.size < limit
    end
  end
end

使うときは下記の感じで。

User.order("followers desc").find_each_with_order do |user|
   # 処理
end