#実装機能
フォローまたはチャットの通知を一覧で受け取る
未読のものがあった場合、ヘッダー部分に未読マークをつける
#モデル作成
$ rails g model Notification
00000000000_create_notifications.rb
class CreateNotifications < ActiveRecord::Migration[5.2]
def change
create_table :notifications do |t|
t.integer :visitor_id, null: false
t.integer :visited_id, null: false
t.integer :relationship_id
t.integer :chat_id
t.string :action, default: '', null: false
t.boolean :checked, default: false, null: false
t.timestamps
end
add_index :notifications, :visitor_id
add_index :notifications, :visited_id
add_index :notifications, :relationship_id
add_index :notifications, :chat_id
end
end
・visitor_id (通知を送ったユーザーのid)
・visited_id (通知を送られたユーザーのid)
・relationship_id (フォローid)
・chat_id (チャットid)
・action (通知の種類(フォロー、チャット))
・checked (通知を送られたユーザーが通知を確認したかどうか)
$ rails db:migrate
#関連付け アソシエーション
app/models/user.rb
has_many :active_notifications, class_name: 'Notification', foreign_key: 'visitor_id', dependent: :destroy
has_many :passive_notifications, class_name: 'Notification', foreign_key: 'visited_id', dependent: :destroy
・active_notifications(自分からの通知)
・passive_notifications(相手からの通知)
app/models/relationship.rb
has_many :notifications, dependent: :destroy
app/models/chat.rb
has_many :notifications, dependent: :destroy
app/models/notification.rb
class Notification < ApplicationRecord
default_scope -> { order(created_at: :desc) }
belongs_to :relationship, optional: true
belongs_to :chat, optional: true
belongs_to :visitor, class_name: 'User', foreign_key: 'visitor_id', optional: true
belongs_to :visited, class_name: 'User', foreign_key: 'visited_id', optional: true
end
・optional: true (nilを許容)
#通知メソッド実装
フォローされた時、チャットが送られてきた時に通知がnotificationテーブルに登録されるように
app/models/chat.rb
def create_notification_chat!(current_user, chat_id, room_id, visited_id)
# チャットしている相手を取得し、通知を送る
temp_ids = Chat.select(:user_id).where(room_id: room_id).where.not(user_id: current_user.id).distinct
temp_ids.each do |temp_id|
save_notification_chat!(current_user, chat_id, temp_id['user_id'])
end
# もしチャットが空だったら、投稿者に通知を送る
save_notification_chat!(current_user, chat_id, visited_id) if temp_ids.blank?
end
def save_notification_chat!(current_user, chat_id, visited_id)
# チャットは複数回することが考えられるため、複数回通知する
notification = current_user.active_notifications.new(
chat_id: chat_id,
visited_id: visited_id,
action: 'chat'
)
# 自分のチャットの場合は、通知済みとする
if notification.visitor_id == notification.visited_id
notification.checked = true
end
notification.save if notification.valid?
end
app/models/user.rb
# フォロー通知
def create_notification_follow!(current_user)
temp = Notification.where(["visitor_id = ? and visited_id = ? and action = ? ",current_user.id, id, 'follow'])
if temp.blank?
notification = current_user.active_notifications.new(
visited_id: id,
action: 'follow'
)
notification.save if notification.valid?
end
end
#コントローラー作成
$ rails g controller notifications
app/controllers/notifications_controller.rb
class NotificationsController < ApplicationController
def index
@notifications = current_user.passive_notifications.page(params[:page]).per(20)
@notifications.where(checked: false).each do |notification|
notification.update_attributes(checked: true)
end
end
end
通知一覧表示
見たら未読false→既読trueと変わるよう指定
#ルーティング
config/routes.rb
resources :notifications, only: :index
#ビュー
部分テンプレート
app/views/notifications/_notification.html.erb
<% visitor = notification.visitor %>
<% visited = notification.visited %>
<div class='m-2'>
<%= link_to user_path(visitor) do %>
<span class="visitor_user_image_box"><%= attachment_image_tag visitor, :image, class:"visitor_user_image", fallback: "logo.png" %></span>
<%= visitor.nickname %>
<% end %>
<span>さんが</span>
<% case notification.action %>
<% when 'follow' then %>
<%= "あなたをフォローしました" %>
<% when 'chat' then %>
<%= link_to 'あなたにメッセージ', chat_path(notification.visitor), style:"font-weight: bold;", class: "border-bottom" %>
<%= "を送りました" %>
<% end %>
<span><%= " (#{time_ago_in_words(notification.created_at)}前)" %></span><br>
</div>
app/views/notifications/index.html.erb
<div class="text-center">
<% notifications = @notifications.where.not(visitor_id: current_user.id) %>
<!--自分の投稿に対するいいね、コメントは通知に表示しない-->
<% if notifications.exists? %>
<%= render notifications %>
<%= paginate notifications %>
<% else %>
<p>通知はありません</p>
<% end %>
</div>
#未読の通知があることを知らせる
app/views/layouts/application.html.erb
<% if unchecked_notifications.any? %>
<span>
<i class="fas fa-circle n-circle"></i>
</span>
<% end %>
<%= link_to "通知一覧", notifications_path %>
・fas fa-circle(fontawesome)
・n-circle(CSSで色付け color: #efa04c;)