💬

通知機能実装時の困りごと

2024/03/11に公開

内容

PF作成の時にメンターさんに教えて頂いたことをいつもで引き出せるように書いておこうと思います。
通知作成時にエラー解決で困った事を記載します。

***_create_notifications.rb

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

t.references :notifiable, polymorphic: true, null: false
このように書く事で、notifiableカラムが複数の異なるモデルと関連付けられます。同じ外部キーを複数の異なるモデルに対して使えます。

notification.rb

class Notification < ApplicationRecord
  # モデルの中でxxx_pathメソッドを使用するために必要
  include Rails.application.routes.url_helpers
  belongs_to :user
  belongs_to :notifiable, polymorphic: true

  # 通知の表示
  def message
    case notifiable_type
    :
    :
    when "StudyReview"
      "<i class='fa-solid fa-book-open'></i> #{notifiable.user.name}さんがレビューを投稿しました".html_safe
    end
  end

  # 通知の遷移先
  def notifiable_path
    case notifiable_type
    :
    :
    when "StudyReview"
      study_study_review_path(study_id: notifiable.study_id, id: notifiable.id)
    end
  end
end

belongs_to :user
通知がどのユーザーに属するかを示しています

belongs_to :notifiable, polymorphic: true
通知が異なる種類のリソースと関連していることを示しています

通知メッセージを生成するためのメソッド(message)、通知がクリックされたときに遷移すべきパスを生成するメソッド(notifiable_path)を作成します。

study_review.rb

class StudyReview < ApplicationRecord
  belongs_to :user
  belongs_to :study
  has_many :notification, as: :notifiable, dependent: :destroy

  # レビュー作成時に各フォロワーに通知を作成
  after_create do
    user.followers.each do |follower|
      notification = follower.notifications.build(notifiable: self)
      notification.save
    end
  end

end

大分端折ってますが、ここが本題で、after_createでstudy_reviewが作成された時に、通知(notification)を作成するようにしています。

user.followers.each do |follower|
 notification = follower.notifications.build(notifiable: self)
 notification.save
end
新しい通知が作成された後に、通知を受け取るユーザー(フォロワー)すべてにその通知を複製するようにしてます。

今回間違えたのが、一人に対して通知を作成するではなく、複数人(フォロワー)全てに通知を作成しているところで、study_reviewに対して通知は複数作られる事になります。

そのためアソシエーションは、has_many :notification, as: :notifiable, dependent: :destroy となるところを、has_one :notification, as: :notifiable, dependent: :destroy と記載してました。

has_oneでは、study_reviewを削除した時に、複製した通知を参照できず、通知データを一緒に削除できず、エラーになってました。

まとめ

そもそもエラーを見つけられたのが、偶然だったので、エラーが潜んでないか入念にチェックしないといけないと思いました。

Discussion