Rails でバッチ処理してみる

Rails の環境で、定期実行する bat はどう作るのか気になって調べていました。
振り返ると、今まで作ったPOSTSON1h.nodecronで処理を定期実行させて、メール送信したり書き込みを消したりしていました。
DB にアクセスする処理を固めたクラスとかの読み込み含めて1から作成をしていたわけですが、
Rails では、Rails の実行環境を生かしてバッチ処理をできることがわかりました。

今回はそれを試します。

目次


参考

Rails ガイドには、実行方法は書いています。
ただし、書き方とか記載が無いので、個人で書かれた記事を参照する手っ取り早いです。

実装方針

前回、「CarriarWave」を用いて作成した写真のアップロードアプリのアップロード一覧をバッチ処理で取得してみる事にします。

とりあえず

rails runner -hを実行して、ヘルプを確認します。
rails runner 'puts Rails.env'を例として出されているので、こちらを試します。
たぶん、developmentと表示されたはずです。
とりあえず動作することは確認できました。

実装

作成

lib/script/record_view.rb を作成します。
module で囲んであげる必要もないようですが、参考に倣います。

lib/script/record_view.rb
1
2
3
4
5
6
7
8
9
10
11
module Script
class RecordView
def self.accounts
Account.all.each do |a|
puts "ID:#{a.id} \tName:#{a.name} \tIconFileName:#{a.icon_identifier} \tCreated:#{a.created_at}"
end
end
end
end

Script::RecordView.accounts()

確認

rails runner lib\script\record_view.rbで実行します。

実行すると、以下の表示になります。

1
2
3
4
5
6
7
ID:3    Name:rubynogazou        IconFileName:   Created:2019-11-19 13:39:22 UTC
ID:4 Name:rubyの画像 IconFileName:ruby.png Created:2019-11-19 13:41:10 UTC
ID:5 Name:xxx IconFileName: Created:2019-11-19 14:40:59 UTC
ID:6 Name:xxx IconFileName:0a7b2b40.png Created:2019-11-19 14:41:21 UTC
ID:7 Name:rubyの画像 IconFileName: Created:2019-11-19 15:34:05 UTC
ID:8 Name:rubyの画像 IconFileName:ruby.png Created:2019-11-19 15:46:30 UTC
ID:10 Name:rubyの画像 IconFileName:0r.png Created:2019-11-28 15:01:07 UTC

(\tで整形すると文字数でズレますね。まぁしょうがない。)
表示ができました。
保存した画像の名前や、レコードの作成時刻が取得できました。
ActiveRecord を扱えるので、更新や削除なども可能ですね。

Rails の環境を読み込むからなのか、bat と思って実行すると表示まで結構かかるなーという印象でした。

定期実行  whenever(12/10 追記)

定期実行は、wheneverを使用している方が多いようです。
cron に実行内容を登録する仕組みのようなので、Windows ではこの方法はとれないですね。残念。
近日追記します。以下追記です。実行環境が Mac に変わります。

whenever gem 導入

Gemfileに追記
1
gem 'whenever'

bundle exec wheneverize .を実行。
実行することで、config/schedule.rb が作成される。

定期実行対象を設定

config/schedule.rb を以下のように編集する。

config/schedule.rb
1
2
3
every 1.minute do
runner "lib/script/record_add.rb",:environment => "development"
end

:environment => "development"で明示的に”development”を指定しないといけない。
デフォルト値は”production”になっている。

実行対象を作成

lib/script/record_add.rb を作成する。

lib/script/record_add.rb
1
2
3
4
5
6
7
8
9
module Script
class RecordAdd
def self.add
Account.create()
end
end
end

Script::RecordAdd.add()

呼び出されるとレコードを追加するようにします。
定期的にレコードが増えることを確認したいだけなので、カラムの値は空にしときます。

crontab へ展開

bundle exec whenever --update-crontabを実行。
実行することで crontab に config/schedule.rb で指定した内容が展開される。

crontab -lを実行することで crontab の内容確認ができる。
ちなみに設定された内容は以下の通りでした。

crontab -l 結果(コメント除く)
1
* * * * * /bin/bash -l -c 'cd [railsアプリへのパス] && bundle exec bin/rails runner -e development '\''lib/script/record_add.rb'\'''

確認

bundle exec rails sを実行し、確認する。
1 分ごとに、レコードが増えていることが確認できるはず。

注意点

crontab に展開しているので rails アプリケーションを実行していなくても、定期的に実行されてしまう。

whenever から crontab に展開したものを消すには、以下を実行する。
bundle exec whenever --clear-crontab


今回は Rails 環境でバッチ実行する方法を確認しました。
Rails コンソールで操作するより決まった動作をするなら。楽でいいですね。

whenever の動作を確認することで、定期実行処理のやり方も分かったので定期削除等々を作れる事も確認できました。

ではでは
(さっさと、whenever の追記準備します)