目標
管理者ユーザーに毎朝8時に総記事数、昨日投稿された記事情報を送る機能を実装します。
実装
実装の手順は
- Mailerの作成
- メールを送信できるか確認
- RakeタスクにMailerの処理を登録
- wheneverで定期実行
それでは行こう!
1. Mailerの作成
まずMailerを作成します。
コマンドで実行してもいいですが今回は手動でファイルを追加していきます。
app/mailers/にファイルを作成します。
$ touch app/mailers/admin.mailer.rb #命名は自由
作ったファイルはApplicationMailerを継承させメソッドを定義します。
このメソッドはMVCのControlerとViewの考え方と同じように一つ一つに送るメール内容であるViewが存在します。
今回は全体の記事数と昨日の記事情報の変数を定義しています。
class AdminMailer < ApplicationMailer
def report
@article_count = Article.count
@article_published_yesterday = Article.where(created_at: 1.day.ago.all_day)
mail(to:'admin@example.com', subject: '[定期連絡] 昨日の記事の集計結果')
end
end
mail(to:'admin@example.com', subject: '公開済記事の集計結果')
ここの部分はメールを送る相手のメールアドレスとメールの件名部分になります。
続いてメール本文部分のViewを作ります。
$ mkdir app/views/admin_mailer
$ touch app/views/admin_mailer/report.html.erb
作成したファイルにメール本文を入力します。
<p>総記事数: <%= @article_count %></p>
<% if @article_published_yesterday.present? %>
<% @article_published_yesterday.each do |article| %>
<p>タイトル: <%= article.title %></p>
<p>投稿者: <%= article.user.name %></p>
<% end %>
<% end %>
これでmailer部分は完成です。
2. メールを送信できるか確認
mailerができたので実際にメールを送れるのかを確認します。
確認方法はletter openerというgemを使っていきます。
Gemfileに以下を追記してbundle install
group :development do
gem 'letter_opener'
gem 'letter_opener_web', '~> 1.0'
end
$ bundle install
インストールできたら設定をしていきます。
以下を追加してください。
設定に関しては公式通りなので説明は特にしません。
config.action_mailer.delivery_method = :letter_opener_web
config.action_mailer.perform_deliveries = true
mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development?
ここまでできたらサーバーをたちあげてhttp://localhost:3000/letter_openerにアクセスしてください
以下のような画面がでできたらOKです。

ここで送られてきたメールの内容を見ることができます。
それではメールを送っていきましょう。
コンソールを立ち上げます。
$ rails c
deliver_nowというメソッドを使うことでメールを今すぐに送信してくれます。
irb(main):001:0> AdminMailer.report.deliver_now
ここでまたletter_openerを確認してメールが送られてきてたらOKです!
3. RakeタスクにMailerの処理を登録
メールが送れることを確認できたらメール送信の処理をRake タスクに登録していきます。
ターミナルでタスクを作成します。
$ rails g task article_report
作成されたタスクファイルにメール送信処理を登録します。
namespace :article_report do
desc '管理者に総記事数、昨日投稿された記事のタイトルと投稿者をメール送信' #解説
task mail_article_report: :environment do #タスク名
AdminMailer.report.deliver_now #実行したい処理
end
end
Rakeタスクからメールが送れるかを確認していきましょう。
$ rake -T
表示されているかを確認して表示されていれば実行していきます。
$ rake article_report:mail_article_report
ここでまたletter openerを確認して送信されていればOKです。
4. wheneverで定期実行
最後にwheneverを使ってメール送信の処理を定期実行できるようにしていきましょう!
gemをインストール。
gem 'whenever', require: false
$ bundle install
インストールできたら設定ファイルをインストールしていきます。
$ bundle exec wheneverize .
[add] writing `./config/schedule.rb'
[done] wheneverized!
ここでschedule.rbというファイルが作成されるのでそこに設定を書いていきます。
require File.expand_path(File.dirname(__FILE__) + '/environment')
# cronを実行する環境変数
rails_env = ENV['RAILS_ENV'] || :development
# cronを実行する環境変数をセット
set :environment, rails_env
# cronのログの吐き出し場所
set :output, "#{Rails.root}/log/cron.log"
# 時間指定
every 1.minutes do
rake 'article_report:mail_article_report'
end
every 1.minutes do
rake 'article_report:mail_article_report'
end
この部分にrakeタスクで登録した処理を書きます。
最初は実際に動いているかを確認するために1分毎にメールを送信することにします。
ターミナルでコマンドを入力することで反映されます。
まずエラーがないかを確認するので以下を入力
登録したRakeタスク名が入っていればOKです。
$ bundle exec whenever
次に現在設定されているcronを確認するために以下を入力
最初なので何も表示されないはずなのでそれでOK
$ crontab -l
そしたら設定を反映していきます。
以下を入力することで設定が反映されます
$ bundle exec whenever --update-crontab
反映されているかを確認するためにもう一度以下を入力
以下のような表示があれば設定が反映されています。
$ crontab -l
# Begin Whenever generated tasks for:...
# End Whenever generated tasks for:...
設定が反映されているのを確認できたら
実行状況を確認していきます。
ログファイルを開いて
/usr/bin/open file:////Users/asahi/Desktop/review/tmp/letter_opener/1625029929_4833531_b61109f/rich.html
のような記述があればOKです。
実際にletter openerでも確認しましょう。
確認ができたらこのまま1分毎にメール送信されるのは邪魔なので設定を変更していきます。
以下のコマンドでcronからデータを削除します。
$ bundle exec whenever --clear-crontab
実際に削除されているかを確認するために
$ crontab -l
を実行して何も表示がされなかったらOKです。
それではschedule.rbに毎朝8時にメールが届くように設定を書き換えていきます。
# Rails.rootを使用するために必要
require File.expand_path(File.dirname(__FILE__) + '/environment')
# cronを実行する環境変数
rails_env = ENV['RAILS_ENV'] || :development
# cronを実行する環境変数をセット
set :environment, rails_env
# cronのログの吐き出し場所
set :output, "#{Rails.root}/log/cron.log"
# 時間指定
every 1.day, at: '8am' do #変更場所
rake 'article_report:mail_article_report'
end
$ bundle exec whenever --update-crontab
ターミナルで反映したら完成です!
エラー対応
log/cron.logでOperation not permittedというエラーが出た方は(自分は出た)以下の記事が役立ったので参考にしてください。