きっかけ
経緯
就活中の選考での課題として
[投稿者のレビューにいいねをしたユーザに、その投稿者が新規でレビューしたときにメールでお知らせする機能]
の作成が出てきましたので、アウトプット用に記載いたします。
開発環境
Ruby 3.1.2
Rails 6.1.7.3
手順
この機能を実装するためには、以下の手順で行うことにします。
①モデルの設定
ユーザとレビュー、いいねのモデルを設定します。ユーザとレビュの関連付け、いいねとユーザ・レビューとの関連付けをします。
class User < ApplicationRecord
has_many :contents
has_many :favorites
end
class Content < ApplicationRecord
belongs_to :user
has_many :favorites
end
class Favorite < ApplicationRecord
belongs_to :user
belongs_to :content
end
②投稿者が新規でレビューを作成した時の処理
レビューが新たに作成されるたびに、その投稿者の過去レビューにいいねしたユーザのリストを取得します。
class Content < ApplicationRecord
# 以上に諸々の処理を記載
# 新しいレビューがデータベースに保存された後に以下のメソッドが実行する。(コールバック)
after_create :send_message_to_favorited_users
private
# いいねしたユーザのIDリストを取得するメソッド
def send_message_to_favorited_users
favorited_users = Favorite.where(content_id: self.user.contents.pluck(:id)).pluck(:user_id).uniq
favorited_users.each do |user_id|
user = User.find(user_id)
# 投稿した本人にメールを送信しない
unless user_id == self.user.id
FavoritedUserMailer.new_content_message_email(user, self).deliver_now
end
end
end
end
コールバックで処理
まず、after_create
はActive Record モデル内で使用されるコールバックの1つです。レビューが新規作成された後に send_message_to_favorited_users メソッド
が自動的に呼び出されるようにするためのものです。
過去にいいねしたユーザをリスト化する処理
次に、以下のコードの処理について
favorited_users = Favorite.where(content_id: self.user.contents.pluck(:id)).pluck(:user_id)`
Favoriteモデル
から、指定された条件に合致するレコードを取得しています。
今回の指定した条件は、content_id
カラムでレビューしたユーザが投稿したレビューのIDリストに含まれているものです。つまり、レビューを「いいね」したレコードを取得しています。
さらに、.pluck(:user_id)
で上記のクエリ結果(Favorite レコード)から、user_id カラムの値を取得しています。これにより、レビューを「いいね」したユーザーのIDリストを取得することができます。
最後に、favorited_users =
で上記の手順で取得した「いいね」したユーザリストを、favorited_users変数
に代入しています。
つまり、上記コードは簡単に言うと投稿者が作成したレビューの中で「いいね」されたレコードを抽出するためのものです。
リスト化したユーザにメール送信する処理
user = User.find(user_id)
先ほどの、favorited_users変数
から「いいね」したユーザIDを使用して、対応するユーザをデータベースから取得します。
unless user_id == self.user.id
FavoritedUserMailer.new_content_message_email(user, self).deliver_now
end
そして、投稿者を除外するunless文
を用いて、投稿者以外にメールを送信します。
③通知メールの送信
取得したいいねユーザリスト
に対して、通知メールを送信する処理を行います。RailsではAction Mailer
を使用してメールを送信できますので、メール文を決め、Action Mailerを設定します。
Action Mailerを生成する
まず、メール送信するために必要なApplicationMailerを継承するクラスは、generateコマンドから作成します。ターミナルで以下のコマンドを行います。
$ rails generate mailer FavoritedUserMailer
以上で、以下のフォルダ、ファイルが作成されました。
Running via Spring preloader in process 616
create app/mailers/favorited_user.rb
create app/mailers/application_mailer.rb
invoke erb
create app/views/favorited_user
invoke test_unit
create test/mailers/favorited_user_test.rb
create test/mailers/previews/favorited_user_preview.rb
メールの宛先や件名を指定する
class FavoritedUserMailer < ApplicationMailer
def new_content_message_email(user, content)
@user = user
@content = content
mail(to: @user.email, subject: 'いいねしたユーザが新しいレビューを投稿しました!')
end
end
今回、いいねしたユーザに送るメールということでFavoritedUserMailerクラス
でnew_content_message_emailメソッド
を作成します。
to(メールの送信先アドレス)
を指定したり、subject
で件名を指定することできます。
※Railsのコントローラと似た形式でコーディングを行います。
さらに、下記のようにdefault from:...
で差出人のメールアドレスを指定できます。
class ApplicationMailer < ActionMailer::Base
default from: 'totono-ru@saunar.com'
layout 'mailer'
end
ビューの生成(メール内容の作成)
mailer
で定義した変数はビューで使えます。今回はapp/views/favorited_user_mailer
に例えば以下のようなメッセージを作成することができます。
<!DOCTYPE html>
<html>
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type" />
</head>
<body>
<h1> <%= @user.name %> 様</h1>
<h3>いつもご利用いただきありがとうございます。</h3>
<p><%= @content.user.name %> さんが新しいレビューを投稿しました!</p>
<p>詳細な内容を見るには以下のリンクをクリックしてください。</p>
<p>レビュータイトル: <%= @content.title %></p>
<a href="<%= content_url(@content) %>">新しいレビューを見る</a>
<br>
<p>以上です。</p>
<p>今後ともご愛顧いただきますよう、よろしくお願いいたします。</p>
</body>
</html>
ビューでURLを生成する方法
<a href="<%= content_url(@content) %>">新しいレビューを見る</a>
リンク先としてURLを記載するには、以下の記事を参考にして設定変更を行いました。
メール送信のトリガーの確認
FavoritedUserMailer.new_content_message_email(user, self).deliver_now
今回は先ほど作成したcontentモデル
で作成した以上のコーディングをトリガーにして送信を行います。
④letter_opener_webでメールをブラウザでプレビューする
開発環境では、テストなどでメールを送信する代わりにデフォルトのブラウザでプレビューする方が楽です。それでは、以下に手順を記載します。
導入手順
まずhはGem導入から
group :development do
gem 'letter_opener_web', '~> 1.0'
end
次に、routes.rb
にletter_opener用のルーティングを追加します。
Rails.application.routes.draw do
# 下記を追加
mount LetterOpenerWeb::Engine, at: '/letter_opener' if Rails.env.development?
# 既存のルーティングが以下に続く
end
そして、
require 'active_support/core_ext/integer/time'
Rails.application.configure do
...
# 下記を追加
config.action_mailer.delivery_method = :letter_opener_web
end
以上で、letter_opener_web
の導入は完了しました。
送信メールの内容を確認
メール送受信を確認するには、http://localhost:3000/letter_opener/
のようにrootにletter_opener/
追加してアクセスすると下記のような画面が表示されていれば設定は完了しています。
終わりに
以上で、いいねしたユーザのリスト化からメール送信、開発環境でのメールブラウザ確認までを行いました。
メール設定など基本を改めて勉強できてよかったです。誤りがありましたらコメントいただけると幸いです!
最後まで閲覧いただき、ありがとうございました。
参考にした記事
以下の記事を参考に作成させていただきました。ありがとうございます!