script/runner OR script/rails runner がクソ重い。どうしてくれんのよ?(Railsでのバッチ処理の手軽な方法)

Rails でバッチ処理といえば、 3.0 未満では script/runner、Rails 3.0 以上では script/rails runner コマンドがありますが、環境を全部ロードするのでスタートアップがクソ重いですよね。daemon_generatorとかを使うという手もありますが、やや大仰だなぁ、という時に手軽な方法をお教えします。

簡単に言うと、actionに処理内容を書いて、ローカルのスクリプトからHTTPアクセスして叩く、という方法です。手動やcron/crontabで処理しようと思ってたなら使えると思います。

app/controllers/hoge_controller.rb

class HogeController < ActionController::Base
  def batch
    # IP制限しないと怖いですよ……
    raise NotFoundError.new unless request.remote_ip == "127.0.0.1"

    # 処理内容を書く
    ...

    render :text => "ok", :status => 200
  end
end

IPアドレスを制限するのがポイントです。GET/POST/PUT/DELETEは処理内容に合わせて下さい。

バッチスクリプトの方は、
script/batch.rb

#!/usr/bin/env ruby

require "net/http"
Net::HTTP.version_1_2

if __FILE__ == $0
  Net::HTTP.start('127.0.0.1', 80) do |http|
    response = http.get("/hoge/batch")
    unless response == Net::HTTPSuccess
      # log にエラーを吐くとか……適当に。
    end
  end
end

こんな感じで、cron/crontabに設定しておけば良いでしょう。こっちもGET/POST/PUT/DELETEは処理内容に合わせて下さい。

あ、NotFoundError(名前は任意)を定義するのを忘れないようにして下さいね。
app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  ...

  class NotFoundError < StandardError; end
  rescue_from NotFoundError, :with => :record_not_found

  def record_not_found
    render :file => File.join(RAILS_ROOT, 'public', '404.html'), :status => 404
  end
end

すでにロードされているので激速です!オススメ!


それでは、楽しいRails開発を!

twitter で無償 Rails サポートボランティアをやっています。"Rails" という単語で監視していますので、つぶやくと、解決方法を知っている場合は reply 致します。24時間監視はできませんので、なんらかの返事が欲しい場合は、直接 @babie までメッセージを下さい。また、動作確認・保証は行いませんのでご了承ください。