👝
通知機能の実装 Part2 (通知を受け取れるようにする)
この記事で分かること
- 通知機能の基礎
- いいね、フォロー、コメント、DMの通知を受け取る
前提条件
- ポリモーフィック関連付けが完成している
- いいねなどの通知を送りたい機能が実装済みである
「ポリモーフィック関連付け」は前記事で紹介しました。
また今回の実装は以下の記事を参考にし実装しました。
前回の「ポリモーフィック関連付け」では、いいね、コメント、フォローの部分を関連付けていましたが、プラスでDMも通知を受け取れるように再設定しています。
それでは、よろしくお願いします。
完成イメージ
ER図
全体のER図
実装手順
- 各モデルにアクションを追加する
- コントローラに記述
- viewの記述
- helper.rbでリンクの場合わけ
実装方法
実装手順に沿って紹介します。
各モデルにアクションを追加する
notification.rb
belongs_to :subject, polymorphic: true
belongs_to :user
enum action_type: { commented_to_own_post: 0, favorited_to_own_post: 1, followed_me: 2, chated_to_own_post: 3}
【Point(notification)】
- ポリモーフィックの関連付けを(blongs_to)で示す
- (action_type)で何の(いいねやコメントなどの)通知なのかを数値で場合わけ
favorite.rb
has_one :notification, as: :subject, dependent: :destroy
after_create_commit :create_notifications
private
def create_notifications
Notification.create!(subject: self, user: item.user, action_type: :favorited_to_own_post)
end
post_comment.rb
has_one :notification, as: :subject, dependent: :destroy
after_create_commit :create_notifications
private
def create_notifications
Notification.create!(subject: self, user: item.user, action_type: :commented_to_own_post)
end
relationships.rb
has_one :notification, as: :subject, dependent: :destroy
after_create_commit :create_notifications
private
def create_notifications
Notification.create!(subject: self, user: follower, action_type: :followed_me)
end
chats.rb
has_one :notification, as: :subject, dependent: :destroy
after_create_commit :create_notifications
private
def create_notifications # 1. チャットが属する部屋を取得
room = self.room # 2. チャットが属する部屋の中で、自分以外のユーザーを取得
other_users = room.users.where.not(id: self.user.id) # 3. 最初の相手ユーザーを取得
recipient_user = other_users.first # 4. 相手ユーザーに通知を作成
Notification.create!(subject: self, user: recipient_user, action_type: :chated_to_own_post)
end
end
【Point】
- (after_create_commit)は、ここでは「そのモデルの機能が保存されたらこのアクションを行ってね」という意味
- (create_notifications)は、「subject:自身のモデル,user: どのユーザに通知を届ける?,行うアクションは?」という順で記載
- relationshipsの「user: どのユーザに通知を届ける?」では「ログインユーザーがフォローしているユーザーのソース名」を記述
- chatsでは、先に相手ユーザーの情報を取得するようにコードを記述(DMの実装方法によって異なる)
- privateで記述すること(同じメソッド名を使うため)
Routeingの設定
routes.rb
resources :notifications, only: [:index]
Controllerの記述
notifications_controller
def index
@notifications = current_user.notifications.order(created_at: :desc)
end
Viewを作成
続いてViewの作成をしていきます。
基盤となるviewを作成
notifications/index.html.erb
<div class= "container py-5 px-sm-0">
<div class= "row">
<div class="col-10 offset-1">
<% if @notifications.present? %>
<h4>通知一覧<span class= "text-warning"><i class="fa-sharp fa-solid fa-bell"></i></span></h4>
<% @notifications.each do |notification| %>
<table class='table table_group'>
<%= render notification.action_type, notification: notification %>
</table>
<% end %>
<% else %>
<div class="text-center">
通知はありません
<% end %>
</div>
</div>
</div>
<%= render notification.action_type, notification: notification %>とは
renderで(notification.action_type)ファイルを呼び出すことができます。
これにより、タイプ名と同じファイルを作成することで、「いいね通知ではこの記述で」のように文章を記述できます。
タイプ別でviewを作成
現在のnotificationタイプは以下の4つです。
- commented_to_own_post・・・コメント通知
- favorited_to_own_post・・・いいね通知
- followed_me・・・フォロー通知
- chated_to_own_post・・・DM通知
これら上記の文章を作っていきます。
タイプ名と同じファイル名でviewを作成
notifications/commented_to_own_post.html.erb
<td>
<%= image_tag notification.subject.user.get_profile_image(30,30),class: "img_icon" %>
<%= link_to notification.subject.user.name, user_path(notification.subject.user) %>
さんがあなたの
<%= link_to '投稿', item_path(notification.subject.item) %>
にコメントしました!(<%= notification.subject.created_at.strftime('%Y/%m/%d') %>)
</td>
notifications/favorited_to_own_post.html.erb
<td>
<%= image_tag notification.subject.user.get_profile_image(30,30),class: "img_icon" %>
<%= link_to notification.subject.user.name, user_path(notification.subject.user) %>
さんがあなたの
<%= link_to '投稿', item_path(notification.subject.item) %>
にいいねしました!(<%= notification.subject.created_at.strftime('%Y/%m/%d') %>)
</td>
notifications/followed_me.html.erb
<td>
<%= image_tag notification.subject.following.get_profile_image(30,30),class: "img_icon" %>
<%= link_to notification.subject.following.name, user_path(notification.subject.following) %>
さんがあなたをフォローしました!(<%= notification.subject.created_at.strftime('%Y/%m/%d') %>)
</td>
notifications/chated_to_own_post.html.erb
<td>
<%= link_to checked_notification_path(notification), method: :PATCH do %>
<%= image_tag notification.subject.user.get_profile_image(30,30),class: "img_icon" %>
<%= link_to notification.subject.user.name, chat_path(notification.subject.user) %>
さんからメッセージが届いています!(<%= notification.subject.created_at.strftime('%Y/%m/%d') %>)
<% end %>
</td>
ヘッダーにリンクを追加したら完成です。
_header.html.erb
<%= link_to notifications_path do %>
<span class= "text-warning"><i class="fa-sharp fa-solid fa-bell"></i></span>
<% end %>
既読機能の追加
感想
DMなら相手ユーザーに通知を届けたいのに自身のみに通知が届くなど、上手くいかないことが多かったです。ヘルパーやrenderの使い方など新しいことが知れたので時間はかかったが実装できてよかったです。このまま既読機能と削除機能の作成に移ります。
この記事をかいた人
23/6/1にDWCに入学し、主にRailsの学習に取り組みました。卒業が近づきこれから何で学習をするか悩んだときに、技術ブログをしようと考えました。初心者ですがよろしくお願いします。
Discussion