LoginSignup
29
43

More than 3 years have passed since last update.

Rails メール自動配信機能をActionMailerとwheneverを使用して実装する

Last updated at Posted at 2020-04-09

Railsで毎日メールを送るためのバッチ処理を、ActionMailerとgemのwheneverを使用して実装しました。

手順

  1. gem 'whenever'導入
  2. schedule.rbにバッチ処理を記述
  3. schedule.rbの内容を登録
  4. メールを送信するメソッドを定義
  5. viewに送信するメール本文を作成
  6. logファイルを確認して実行されているか確認

環境

ruby '2.5.7'
gem 'rails', '~> 5.2.4', '>= 5.2.4.1'

前提

  1. Userテーブルにemailカラムがあること
  2. ActionMailerで送信するサーバーの設定が出来ていること
  3. メール送信するために必要なApplicationMailerを継承するクラスを作成していること

※ (UserMailerという名前で作成済)

1. gem 'whenever'導入

'whenever'って?
自動的にメール送信するなど、バッチ処理を行うためにはcronというものを使ってcrontabにそのための記述をします。
でもその小難しいものを簡単に書けるようにするgemが'whenever'です。

それではgem 'whenever'をインストールします。
gemファイルに入力。

Gemfile
gem 'whenever', require: false

ターミナルでGemをインストールします。

$ bundle install

2. schedule.rbにバッチ処理を記述する

まずはschedule.rb ファイルを作成します。
以下をターミナルに入力する

$ wheneverize .
 [add]  writing './config/schedule.rb'
 [done] wheneverized!

今作ったschedule.rbの中にバッチ処理を記述します

config/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に定義されたメソッドを呼び出すために使用します。
今回の場合はUserMailernotify_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全員にメールを送信するようにしてます。

mailers/user_mailer
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を全て取得する。

mailers/application_mailer
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など変数が呼び出せます。

user_mailer/notify_user.text.erb

内容を書きます

6. logファイルで実行されているか確認する

実行されているか確認したい場合は、1分毎にメールが送られる設定に書き換えてみましょう。logを確認するためです、仕方ない。
every 1.days, at: '9:00 am' do
をコメントアウトして、以下の一文に書き換えます。
every 1.minutes do

config/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.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にめっちゃメールが送られているのが分かる。

log/cron.log
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

29
43
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
29
43