🍣

chat機能に通知機能を持たせる

に公開

今回、chat機能に対して、通知機能をポリモーフィックで作成しました。

ポリモーフィックとはなに?
簡単にいうと、カラムを使いまわせるよ、的なニュアンスのもの。

まずは、通知モデルを作成していきます。
下記のコマンドを入力して、通知モデルを作成してください。

$ rails g model Notification user:references notifiable:references{polymorphic} read:boolean

ここでのポイントは、referencesを使用している点です。
referencesを指定すると、モデル同士の関連付けを行う場合に通常必要になるNOT NULL制約や、外部キー制約といったオプションをマイグレーションファイルに自動的に設定します。

class CreateNotifications < ActiveRecord::Migration[6.1]
  def change
    create_table :notifications do |t|
      t.references :user, null: false, foreign_key: true
      t.references :notifiable, polymorphic: true, null: false
      t.boolean :read, default: false, null: false # 追記
      t.timestamps
    end
  end
end

で、migrateをかけてください。

notificationmodel

class Notification < ApplicationRecord
  belongs_to :user
  belongs_to :notifiable, polymorphic: true
end

chatmodel

class Chat < ApplicationRecord
belongs_to :user
belongs_to :room
has_many :notifications, as: :notifiable, dependent: :destroy
after_create_commit :create_notifications

  def create_notifications
    # self.user_id は、このチャットを作成したユーザーのIDです。
    self.room.user_rooms.where.not(user_id: self.user_id).each do |user|
      # ここで各ユーザーに対して通知を作成します。
      Notification.create!(
        user_id: user.user_id,  # 通知を受けるユーザー
        notifiable: self,  # 関連するチャット
      )
    end
  end
end

好きなところにこれを追加します。

   <li class="dropdown">
            <button class="btn btn-secondary dropdown-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
              Notification
              <span class="badge badge-danger"><%= current_user.notifications.where(read: false).count %></span>
            </button>
            <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
              <% if current_user.notifications.where(read: false).any? %>
                <small class="dropdown-item disabled">直近5件の未読の通知を表示しています</small>
                <% current_user.notifications.where(read: false).limit(5).order(created_at: :desc).each do |notification| %>
                  <%= link_to notification_message(notification), notification_path(notification), method: :patch, class: "dropdown-item" %>
                <% end %>
              <% else %>
                <span class="dropdown-item disabled">未読の通知はありません</span>
              <% end %>
            </div>
          </li>

次回はコントローラーと、ルート設定を公開します。
チャット機能の作成手順はこのリンクを参照してください
https://qiita.com/mi-1109/items/660ec3630e76f11d1f16

Discussion