Railsで毎日メールを送るためのバッチ処理を、ActionMailer
とgemのwhenever
を使用して実装しました。
##手順
- gem
'whenever'
導入 -
schedule.rb
にバッチ処理を記述 -
schedule.rb
の内容を登録 - メールを送信するメソッドを定義
- viewに送信するメール本文を作成
- logファイルを確認して実行されているか確認
##環境
ruby '2.5.7'
gem 'rails', '~> 5.2.4', '>= 5.2.4.1'
##前提
- Userテーブルにemailカラムがあること
-
ActionMailer
で送信するサーバーの設定が出来ていること - メール送信するために必要な
ApplicationMailer
を継承するクラスを作成していること
※ (UserMailer
という名前で作成済)
1. gem 'whenever'
導入
'whenever'
って?
自動的にメール送信するなど、バッチ処理を行うためにはcronというものを使ってcrontabにそのための記述をします。
でもその小難しいものを簡単に書けるようにするgemが'whenever'です。
それではgem 'whenever'をインストールします。
gemファイルに入力。
gem 'whenever', require: false
ターミナルでGemをインストールします。
$ bundle install
2. schedule.rb
にバッチ処理を記述する
まずはschedule.rb
ファイルを作成します。
以下をターミナルに入力する
$ wheneverize .
[add] writing './config/schedule.rb'
[done] wheneverized!
今作ったschedule.rb
の中にバッチ処理を記述します
# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
# Example:
#
# 絶対パスから相対パス指定
env :PATH, ENV['PATH']
# ログファイルの出力先
set :output, 'log/cron.log'
# ジョブの実行環境の指定
set :environment, :development
#
# every 12.hours do
# command "/usr/bin/some_great_command"
# runner "MyModel.some_method"
# rake "some:great:rake:task"
# end
#
every 1.days, at: '9:00 am' do
# Rails内のメソッド実行
runner "UserMailer.notify_user"
end
# Learn more: http://github.com/javan/whenever
絶対パスから相対パス指定
env :PATH, ENV['PATH']
ENV['PATH']
を特に何も定義してないけど書いたら上手くいった。
これがないとエラーになるので注意。
ログファイルの出力先
set :output, 'log/cron.log'
log/cron.log
が新規作成され、バッチ処理の記録が入る。
####ジョブの実行環境の指定
set :environment, :development
environment
が環境という意味。
:development
rails内の開発環境。今回はこれを指定してます。
:production
デプロイ後の本番環境
:test
テスト実行環境(Rspecなど)
####バッチ処理の記述
every 1.days, at: '9:00 am' do
英文そのまま。毎日朝の9時に行います。
runner "UserMailer.notify_user"
UserMailer
内のnotify_user
メソッドを実行します。
※ApplicationMailer
を継承するクラスの中のメソッドを指定しています。
runner
Railsに定義されたメソッドを呼び出すために使用します。
今回の場合はUserMailer
のnotify_user
メソッドを呼び出すのでこれに当てはまる。
(UserMailer
は以前に自分で作成したものです)
※ユーザーに直接関係のある機能の場合に使用する。コントローラやモデルを呼び出せる。
rake
実行させたいrakeファイルを指定する場合に使用します。
今回は使ってません。使用する場合は別途rakeファイルを作成する。
※システムの管理上必要な機能の場合に使用する。定時になると自動的にデータを削除するなど。
##3. schedule.rb
の内容を登録する
現状のcrontab
に何が記述されているのかを確認します。
$ crontab -e
中はいろいろ書いてるけど、先ほど記述したUserMailer.notify_user
の一文があればOK
※nanoエディタが起動されます。
終了する時は焦らずにCtrl + x
問題がなければ以下のコマンドを実行して登録します。
$ bundle exec whenever --update-crontab
上記のコマンドで、作成したジョブがcrontab
に登録されました。
反映されているか確認します。
$ crontab -l
ちゃんとUserMailer.notify_user
の記述があれば登録されてます
##4. メールを送信するメソッドを定義
メールを送信するnotify_user
メソッドを定義します。
user全員にメールを送信するようにしてます。
class UserMailer < ApplicationMailer
def notify_user
default to: -> { User.pluck(:email) }
mail(subject: "everyday Bookers!yay!")
end
end
default to: -> { User.pluck(:email) }
宛先を指定します。pluckでUserのemailを全て取得する。
class ApplicationMailer < ActionMailer::Base
default from: 'from@example.com'
layout 'mailer'
end
application_mailer
には全部のメールに共通する設定を記述します。
default from: 'from@example.com'
サーバーに登録してあるメールアドレスが勝手に入ります。
##5. viewに送信するメール本文を作成する
user_mailer
内にnotify_user.text.erb
と新規作成する。
※textで作成しましたがhtmlでも良い。user.nameなど変数が呼び出せます。
内容を書きます
##6. logファイルで実行されているか確認する
実行されているか確認したい場合は、1分毎にメールが送られる設定に書き換えてみましょう。logを確認するためです、仕方ない。
every 1.days, at: '9:00 am' do
をコメントアウトして、以下の一文に書き換えます。
every 1.minutes do
# Use this file to easily define all of your cron jobs.
#
# It's helpful, but not entirely necessary to understand cron before proceeding.
# http://en.wikipedia.org/wiki/Cron
# Example:
#
# 絶対パスから相対パス指定
env :PATH, ENV['PATH']
# ログファイルの出力先
set :output, 'log/cron.log'
# ジョブの実行環境の指定
set :environment, :development
#
# every 12.hours do
# command "/usr/bin/some_great_command"
# runner "MyModel.some_method"
# rake "some:great:rake:task"
# end
#
every 1.minutes do ##ここを追加
# every 1.days, at: '9:00 am' do ##ここをコメントアウト
# Rails内のメソッド実行
runner "UserMailer.notify_user"
end
# Learn more: http://github.com/javan/whenever
忘れずにターミナルで設定を登録します。
$ bundle exec whenever --update-crontab
logファイルを見ると1分毎にメールが送られているのが確認できます。
下記の通りに1分毎に一行増えて表示されていたらOK
Userにめっちゃメールが送られているのが分かる。
Running via Spring preloader in process 8692
Running via Spring preloader in process 8714
Running via Spring preloader in process 8731
Running via Spring preloader in process 8748
##おまけ
そんな頻繁にメールが送られてきたらいやだからcrontab
の中身を消しましょう。
以下のコマンドで消せます。
$ whenever --clear-crontab
バッチ処理を再開したい時は以下のコマンドを入力。
またメールが送られるようになります。
$ bundle exec whenever --update-crontab
##参考にさせて頂きました
https://freecamp.life/rails-whenever/
https://qiita.com/Esfahan/items/e7a924f7078faf3294f2
https://www.school.ctc-g.co.jp/columns/masuidrive/masuidrive22.html