はじめに
現場で使える Ruby on Rails 5速習実践ガイドでインプットを行っており、アウトプットで投稿しています。
サンプルは、タスク管理アプリです。今回の投稿では、ユーザーがタスクを登録したときに、「○○タスクが登録されました」というメールを送る機能を実装します。
目次
メイラーの作成
メイラーとは、ActionMailerのことで、railsに搭載されているメールを送る機能です。controllerが、templateに情報を渡し画面出力を行っているのと同様に、Mailerもtemplateに情報を渡しメールを送信します。
まずは、今回実装するTaskMailerを作成します。以下のコマンドを実行します。
rails g mailer TaskMailer
メソッドを追加
先程のコマンドでapp/mailer/task_mailer.rb
というファイルが作成されます。そこに、今回送信するメールのメソッド「creation_email」を定義します。
def creation_email(task)
@task = task
mail(
subject: 'タスク作成完了メール',
to: 'user@example.com',
from: 'task@example.com'
)
end
こちらのメソッドを呼び出すときに、追加されたタスクを引数として渡してもらいます。taskの内容をtemplateで表示するのでインスタンス変数に格納しています。
テンプレート作成
次にテンプレートを作成します。ユーザーの受信環境によっては、html形式のメールを表示できない可能性があります。text形式のファイルを合わせて作成し、html形式と合わせて送信しますのでファイルを二種類作成します。
| 以下のタスクを作成しました
ul
li
| 名称:
= @task.name
li
| 詳しい説明
= simple_format(@task.description)
| 以下のタスクを作成しました
= "\n"
| 名称:
= @task.name
= "\n"
| 詳しい説明
= "\n"
= @task.description
送信処理実装
ここまで来たらあとは、送信する処理を記述するのみです!
今回は、タスクの保存処理と合わせてメールを送信するため、tasks_controllerのcreateメソッドに送信処理を書きます。
略
if @task.save
TaskMailer.creation_email(@task).deliver_now
SampleJob.perform_later
logger.debug "task:「#{@task.attributes.inspect}」を登録しました"
redirect_to tasks_url, notice: "タスク「#{@task.name}」を登録しました。"
else
render :new
end
略
deliver_now
は文字通り、即時に送信する命令です。5分後にメールを送りたいときは、deliver_later(wait: 5minutes)
とします。
動作確認
メールが送信されたか、メールの内容は意図したとおりになっているか。これを確かめるために、「mailcatcher」というgemを使用します。
gem install mailcatcher
上記のコマンドを実行し、railsの設定ファイルに以下の記述を行います。
# Don't care if the mailer can't send.
config.action_mailer.raise_delivery_errors = false
# 以下二行を追記
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = { address: '127.0.0.1', port: 1025}
上記は開発環境の設定ですが、本番環境の設定は、procuction.rbに記述をします。
設定ファイルの記述が完了したら、サーバーを再起動してください。
確認の手順は、
- ターミナルで
mailcatcher
を実行 - メール送信のフローを実行後、
http://127.0.0.1:1080/
にアクセス
そうすると、送信メールの確認ができます。
テスト作成
まずは、mailerのSpec用にディレクトリを作成します。
mkdir spec/mailers
作成したフォルダの中にtask_mailer_spec.rb
を作成し、以下のように記述します。
require 'rails_helper'
describe TaskMailer, type: :mailer do
end
これで枠組みは完成なので、実際にテストを書いていきます。
require "rails_helper"
RSpec.describe TaskMailer, type: :mailer do
let(:task){FactoryBot.create(:task, name: 'メイラーSpecを書く', description: '送信したメールの内容を確認します')}
let(:text_body) do
part = mail.body.parts.detect{|part| part.content_type == 'text/plain; charset=UTF-8'}
part.body.raw_source
end
let(:html_body) do
part = mail.body.parts.detect{|part| part.content_type == 'text/html; charset=UTF-8'}
part.body.raw_source
end
describe '#creation_email' do
let(:mail){TaskMailer.creation_email(task)}
it "想定通りのメールが生成されている" do
expect(mail.subject).to eq('タスク作成完了メール')
expect(mail.to).to eq(['user@example.com'])
expect(mail.from).to eq(['taskleaf@example.com'])
expect(text_body).to match('以下のタスクを作成しました')
expect(text_body).to match('メイラーSpecを書く')
expect(text_body).to match('送信したメールの内容を確認します')
expect(html_body).to match('以下のタスクを作成しました')
expect(html_body).to match('メイラーSpecを書く')
expect(html_body).to match('送信したメールの内容を確認します')
end
end
end
以下のコマンドを実行し通るか確認します。
bundle exec rspec spec/mailers/task_mailer_spec.rb