ActiveRecordをSequelっぽく扱う
module ActiveRecordHelper def each(opts={}) rows = find(:all, opts) while rows.any? rows.each{|v| yield v} conditions = if opts.key? :conditions _conditions = opts[:conditions].clone _conditions.first.insert(0, 'id > ? and ') _conditions.insert(1, rows.last.id) else ["id > ?", rows.last.id] end new_opts = opts.merge({:conditions => conditions}) rows = find(:all, new_opts) end end end class ActiveRecord::Base extend ActiveRecordHelper end
とかやっておくと ActiveRecordでeachメソッドが使えるようになる。テーブル全体をなめるバッチ処理などに便利、メールのキューから全部メールを送る場合なんかは
def send_mail v # メールを送る処理 end MailQueue.each(:limit => 100, :order => :id, :conditions => ["status = ?", 'undeliver']){|v| send_mail(v) }
みたいな感じで処理できる。limitは取り出す数ではなくて、一度にフェチする数を指しているので、件数が多くても大丈夫。 :order には idを指定しないとまずい。