🦡
DM機能つけたけど、DM気づかないよね通知機能
DM機能がつけられても、いちいちフォロー/フォロワーのマイページへ行って、DMを送るをしないとDMが来てるかどうかわからない。現実的じゃないから、通知機能をつけたい。けど、さっぱりわからないので、まとめ
モデル作成
rails g model Notification user:references message:references read:boolean default:false
rails db:migrate
- さっきの記事でも書いた、referencesは既にあるテーブルを参照。
-
read:boolean default:false
は、
notifications(通知って意味)テーブルに新しい通知が作成された時に、
その通知が未読であることを示すために使う。
read:boolean default:falseの使用目的
- 新しい通知が作成されると、自動的に
readカラム
がfalse
に設定 - ユーザーが通知を確認した時に、
readカラム
をtrue
に更新することで、
どの通知が既読であるかを追跡できる。
モデルファイルの編集
app/models/notification.rb
class Notification < ApplicationRecord
belongs_to :user
belongs_to :message
validates :user_id, presence: true
validates :message_id, presence: true
validates :read, inclusion: { in: [true, false] }
end
-
presence: true
は空文字を許可しない -
validates :read, inclusion: { in: [true, false] }
`inclusionを使うことで、readカラムに格納される値が、true
,false
のどちらかになる。
通知コントローラー
app/controllers/public/messages_controller.rb
class Public::MessagesController < ApplicationController
before_action :authenticate_user!
def create
@message = current_user.messages.build(message_params)
if @message.save
create_notification(@message)
redirect_to room_path(@message.room)
else
redirect_back(fallback_location: root_path)
end
end
private
def message_params
params.require(:message).permit(:room_id, :message)
end
def create_notification(message)
room = message.room
recipient_entry = room.entries.where.not(user_id: message.user_id).first
recipient = recipient_entry.user
Notification.create(user: recipient, message: message)
end
end
- 解説
def create
@message = current_user.messages.build(message_params)
if @message.save
create_notification(@message)
redirect_to room_path(@message.room)
@message = current_user.messages.build(message_params)
現在のユーザーに紐づいた新しいメッセージを作成する。
「 buildメソッド 」の使い方
- 関連するモデルの新しいインスタンスを作成するために使用する
- 特定の関連付けを持つ親モデルで使用されるため、新しいインスタンスが自動的に親モデルに関連づけられる
まとめ
buildメソッド
はそのコレクションに新しいメッセージを追加するけど、
保存はできないため、データベースに保存するには、saveメソッド
が必要。
そして、createメソッド
記述して、新しいインスタンスを作成し、即座にデータベースに保存させる。
buildメソッド
↓
saveメソッド
↓
createメソッド
else
redirect_back(fallback_location: root_path)
end
- メッセージの保存が失敗した時の処理で、
保存されなかったら、元のページへリダイレクト。元のページがわからない場合は、ホームページへリダイレクトする。
params.require(:message).permit(:room_id, :message)
-
room_id
とmessage
を許可。
def create_notification(message)
room = message.room
recipient_entry = room.entries.where.not(user_id: message.user_id).first
recipient = recipient_entry.user
Notification.create(user: recipient, message: message)
end
end
-
room = message.room
メッセージが属するチャットルーム取得 -
recipient_entry = room.entries.where.not(user_id: message.user_id).first
[recipientが受信者って意味]
メッセージを送信したユーザー以外のユーザーエントリーを取得する -
recipient = recipient_entry.user
上記で取得したエントリーから、通知を受け取るユーザーを取得する。 -
Notification.create(user: recipient, message: message)
受信者(recipient)とメッセージを指定して、新しい通知を作成する(create)
まとめ
create_notificationメソッド
を使って、新しいメッセージが送信された時に自動的に通知が生成される。
通知の表示
app/controllers/public/notifications_controller.rb
class Public::NotificationsController < ApplicationController
def index
@notifications = current_user.notifications.where(read: false)
end
def mark_as_read
notification = current_user.notifications.find(params[:id])
notification.update(read: true)
redirect_to notifications_path
end
end
- 解説
def index
@notifications = current_user.notifications.where(read: false)
end
- 現在ログインしてるユーザー(current_user)の未読通知(read: false)を取得するよう記述
- 取得した未読通知は、インスタンス変数`@notificationsに格納され、ビューで通知を表示できるようになる
def mark_as_read
notification = current_user.notifications.find(params[:id])
notification.update(read: true)
redirect_to notifications_path
end
-
mark_as_read
アクションは、特定の通知を既読にするため -
params[:id]
を使って、現在ログインしてるユーザーの特定の通知を見つける。この通知のIDはパラメーターとして渡される。 -
notification.update(read: true)
「read: false」から「true」にupdateする。これにより、通知が既読としてマークされる。
ルーティング
config/routes.rb
scope module: 'public' do
resources :notifications, only: [:index] do
member do
patch 'mark_as_read'
-
member
は個別の追加ルートを定義。ここでは、特定の通知に対するpatch
リクエストを定義している。 -
patch 'mark_as_read
通知を既読にするためのルートを定義している
[ PATCH /notifications/:id/mark_as_read ] - indexアクション = "全ての未読通知を一覧表示"するためのルート
(get/notifications) - mark_as_readアクション = "特定の通知を既読"にするためのルート
ビュー作成
app/views/layouts/application.html.erb
<header>
<%= link_to notifications_path, class: "btn btn-sm btn-light" do %>
<i class="fa-solid fa-bell" style="color: #af7546;"></i> 通知
<% if current_user.notifications.where(read: false).any? %>
<span class="badge badge-danger"><%= current_user.notifications.where(read: false).count %></span>
<% end %>
<% end %>
</header>
application.html.erbに追記した(ヘッダーに)
-
<% if current_user.notifications.where(read: false).any? %>
条件文で、未読の通知があるかどうかをチェックする -
where(read: false)
は、read属性がfalse(未読)の通知。
any?
で未読通知が1つでもあるかどうかを確認します。
未読通知があれば、true
なければfalse
を返す。 -
<%= current_user.notifications.where(read: false).count %>
は、未読通知の数を表示する
以上 !
Discussion