読者です 読者をやめる 読者になる 読者になる

初めてのRailsアプリ(その7)

railsubject_07

初めてのRailsアプリ(その7)

これでBatchはバッチリ

7. Batch on Rails

前回に引き続き、Railsでのバッチ処理を勉強する。前回は動作確認がメインだったので、今回はそれっぽい業務処理を実装する。

業務処理

仕様

こんな感じ。

  • 案件(Subject)はステータス(status)と開始日(start_at)と終了日(end_at)を持つ
  • ステータスは「未実施」「実施中」「実施済」のいづれか
  • バッチは2分毎に起動し、本日が開始日と終了日の間であれば、ステータを「実施中」に変更する

ER図

f:id:naotooncajon:20130729002657p:image

カラム追加

そういえば、まじめにカラム追加をしたことなかったと思うので、メモる。

マイグレファイルの作成

mba:railsubject 7010oncajon$ rails generate migration AddStatusToSubjects status:string begin_at:datetime end_at:datetime
      invoke  active_record
      create    db/migrate/20130728032128_add_status_to_subjects.rb

マイグレの実行

mba:railsubject 7010oncajon$ rake db:migrate
==  AddStatusToSubjects: migrating ============================================
-- add_column(:subjects, :status, :string)
   -> 0.0021s
-- add_column(:subjects, :begin_at, :datetime)
   -> 0.0008s
-- add_column(:subjects, :end_at, :datetime)
   -> 0.0007s
==  AddStatusToSubjects: migrated (0.0040s) ===================================

確認

mba:railsubject 7010oncajon$ rails db
SQLite version 3.7.17 2013-05-20 00:56:22
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> .schema subjects
CREATE TABLE "subjects" ("id" INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, "name" varchar(255), "content" varchar(255), "created_at" datetime NOT NULL, "updated_at" datetime NOT NULL, "status" varchar(255), "begin_at" datetime, "end_at" datetime);

コーディング

案件(Subject)に処理を追加。index.html.erbとshow.html.erbは省略。

f:id:naotooncajon:20130729002652p:image

バッチ処理

バッチファイル作成

仕様に則って、SubjectsBatch.update_status(./lib/batches/subjects_batch.rb)を実装する。

class Batches::SubjectsBatch
    def self.update_status
        # 開始日と終了日の間の案件は「実施中」にステータスを変更する
        subjects = Subject.where(["begin_at <= ? AND end_at >= ?", Time.now, Time.now]).where("status != ?", "実施中")
        subjects.each{|subject|
            subject.update_attributes!(:status => "実施中")
            CustomLogger.debug("batch", "MSG_INF_999", "#{subject.name_content}のステータスを更新しました。")
        }
    end
end

スケジューリング

仕様に則って、スケジューリング(./config/scedule.rb)

# 2分毎にSubjectsBatch.update_statusを実行する
every 2.minutes do
  runner "Batches::SubjectsBatch.update_status"
end

動作確認

案件詳細画面

案件を新規作成します。本日は、2013/07/29です。

f:id:naotooncajon:20130729002704p:image

案件詳細画面(2分後)

約2分後にステータスが変わりました。

f:id:naotooncajon:20130729002700p:image

Aplicationログ

ログもばっちりです。

2013/07/28 20:18:03.378722 #63190 DEBUG (batch) (subjects_batch.rb:27:in `update_status') 【案件1】rails案件のステータスを更新しました。 

終わりに

cronから直接rbを起動しかけど、shを挟んだほうが良いのかしら?

参考サイト

新しいマイグレーションを追加してテーブルを変