【Ruby on Rails】【通知機能】マイページ上でバッジが付与された時に通知する
はじめに
現在Ruby on Railsを使用し、技術記事投稿アプリを作成しております。
そのアプリ内で通知機能を作成しており、これまで「①自分の記事にいいねがついたとき / ②自分の記事にコメントが投稿されたとき / ③自分がコメントした内容にいいねが押された時」を実装しました。
①②に関しては、こちらの記事を参考に、③は上記記事を参考に自力で実装しました。(実装方法はこちらに投稿しております)
今回は4つ目の通知機能として、マイページ上でバッジが付与された時に通知されるよう実装しました。
(マイページの作成はこちらの記事、バッジ機能作成の記事はこちらご覧ください)
参考になりましたら幸いです。
環境
Rails 7.1.3.4
前提
- 投稿機能実装済み(この記事ではArticleモデル)
- 「自分の投稿した記事にいいねが付いた時の通知」「自分の投稿した記事にコメントが投稿された時の通知」「自分がコメントした内容にいいねが押された時」の通知は実装済み
- 上記3つ実装済のため、通知モデルの作成、通知モデルの関連付は設定済み
実装方法
ここからは、マイページ上でバッジが付与された時に通知する実装内容のみ記載させていただきます。
通知モデルの作成、モデルの関連付け
上記にも記載している通り、すでにNotificationモデル作成、Articleテーブルの関連づけは完了しているため割愛させていただきます。(詳細はこちらと、コメントへのいいねの通知記事ご確認ください)
通知作成メソッドを作る
- マイページ上でバッジが付与された際の通知に必要なid
アプリ内では、「1,3,5,10,20,30記事」投稿された際に、ユーザーへバッジが付与されるような実装としております。(この実装内容はこちら)
visitor_id | visited_id | article_id | action | checked |
---|---|---|---|---|
現在のユーザーid | 現在のユーザーのid | 該当の記事のid | badge | false |
これまでの通知機能の実装と異なる点
- visitor_id、visited_idが共に現在のユーザーidであること。
- 「1,3,5,10,20,30記事」投稿された際に通知される、という制約をつけていること。
ここまでがマイページ上でバッジが付与された際の通知に必要なidとなります。
この情報を元に通知作成メソッドを実装して行きます。今回マイページ上でバッジが付与された際の通知という内容ですが、読み換えると1,3,5,10,20,30記事が投稿された際に通知するという内容になるため、articleテーブルにメソッドを作成していきます。
その理由は下記の通り、今回バッジデーブルを作成していないためです。
articleテーブルに通知作成メソッドを作った方がわかりやすいと感じたため、下記のような実装をしております。
resources :users, only: %i[new create] do
collection do
get :my_articles
get :my_favorites
get :my_badges
end
end
resources :articles do
resources :favorites, only: %i[create destroy]
resources :comments, shallow: true do
resources :commentfavorites, only: %i[create destroy]
end
end
- app/models/article.rb
def create_notification_badge(current_user, article_id)
count = Article.published.where(user_id: current_user.id).count
if [1, 3, 5,10,20,30].include?(count)
save_notification_badge(current_user, article_id)
end
end
def save_notification_badge(current_user, _article_id)
notification = current_user.active_notifications.new(
article_id: id,
visitor_id: current_user.id,
visited_id: current_user.id,
action: 'badge'
)
notification.save if notification.valid?
end
end
-
count = Article.published.where(user_id: current_user.id).count
: 現在のユーザーが投稿した公開済みの記事の数をカウントしています。公開状態はpublishedスコープを通じて取得しています。 -
if [1, 3, 5,10,20,30].include?(count)
: この条件式は、記事数が特定の値(1, 3, 5, 10, 20, 30)に一致する場合にtrueを返します。これにより、これらの特定の数値に達したときのみ通知が作成されます。ここで適切に条件指定ができていないと、他の記事数の時にも通知が出てしまいます。 - save_notification_badgeメソッド: このメソッドでは、ユーザーに対する通知を作成しています。通知の詳細にはarticle_id、通知の送信者(visitor_id)、通知の受信者(visited_id)、そしてアクションタイプ(action)が含まれています。(ここではvisitor_id、visited_id共にcurrent_user.idになる)
-
notification.save if notification.valid?
: この行は、通知が有効である場合にのみ保存を試みます。この一文がない場合、通知が有効であっても保存されず、データベースに通知が記録されませんでした。
通知作成メソッドの呼び出し
1,3,5,10,20,30記事が投稿されたタイミングで、通知レコードが作成されます。
先ほど追加したメソッドを、articlesコントローラーのcreateアクションへ追加します。
app/controllers/articles_controller.rb
バッジ付与時の通知、と補足している箇所が通知作成メソッドの呼び出し箇所になります。
def create
@article = current_user.articles.build(article_params)
@article.status = if params[:draft].present?
:draft
else
:published
end
if @article.save
if @article.draft?
redirect_to article_path(@article), notice: '記事を下書きに入れました。'
else
redirect_to article_path(@article), notice: '投稿しました。'
# バッジ付与時の通知
@article.create_notification_badge(current_user, @article.id)
# ここまで
end
else
flash[:error] = 'タイトルと本文を入力しないと、投稿できません'
render :new, status: :unprocessable_entity
end
end
通知一覧画面の作成
1,3,5,10,20,30記事が投稿された通知のviewは下記となります。
app/views/notifications/_notification.html.erb
<% case notification.action %>
<% when 'badge' then %>
<%= link_to 'マイページ', my_badges_users_path, style: 'font-weight: bold;' %>上でバッジが付与されました。
<%= time_ago_in_words(notification.created_at).upcase %>
<% end %>
遷移先はマイページ上のバッジ先になります。
これまでの通知機能の実装と異なる点
- app/views/notifications/index.html.erbで、
<% notifications = @notifications.where(visitor_id: current_user.id) %>
の一文があります。
こちらの記事では、where.not
とすることで、visitor_idがcurrent_user.idの場合に通知が出ないよう実装しておりますが、今回の内容ではvisitor_id=current_user.idなのでnotを割愛しております。
(他の通知ではnot付けておいた方がいいのかもしれませんが、一旦このように実装しております)
<h3 class="text-center">通知</h3>
<% notifications = @notifications.where(visitor_id: current_user.id) %>
<% if notifications.exists? %>
<%= render notifications %>
<%= paginate notifications %>
<% else %>
<p>通知はありません</p>
<% end %>
通知作成メソッドが正常に呼び出された時のサーバーログ
記事が作成された後、Notification Createで処理が正常に行われていることがわかります。
また今回必要なidは["visitor_id", 1], ["visited_id", 1], ["article_id", 113], ["action", "badge"], ["checked", false]のため、["comment_id", nil]とcomment_idはnillになっていることもわかります。
通知作成メソッドが失敗している場合
1,3,5,10,20,30記事以外が投稿されたとき、またはそもそもデータベースに通知が記録されていない場合には記事が作成された後、Notification Createで処理が行われないためこのようなログになります。
最後に
個人記事を参考にこれまで4つの通知機能を作成しました。
記事を参考にして実装するだけでなく、自分でロジックを組み立て実装することで流れがより深く理解できました。
最後までお読みいただき、ありがとうございました。
Discussion