You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rails中使用Noticed Gem时多态评论通知无法标记为已读问题

解决多态评论下Noticed Gem通知标记已读失效问题

问题分析

从你提供的信息来看,核心问题有两个:

  1. 原方法执行了UPDATE但无实际修改,说明查询条件未匹配到目标通知——因为你的通知是由多态评论触发的,直接关联到Comment而非Post,@post.notifications_as_post这个关联可能根本找不到对应的通知记录,控制台的UPDATE实际影响行数为0。
  2. 修改后的方法报错是因为@commentable是CollectionProxy(比如@post.comments这类集合),而非单个Comment对象,集合没有notifications方法。

从你给出的Notification对象可以看到,通知的params里包含了触发它的Comment,且该Comment的commentable就是目标Post,所以我们需要通过这个关联来定位通知。

解决方案

方案1:直接通过Notification的params查询(无需修改模型关联)

修改PostsController中的mark_notifications_as_read方法,直接通过通知的params字段匹配关联到当前帖子的评论:

def mark_notifications_as_read
  if current_member
    # 定位所有和当前帖子相关的CommentNotification,且接收者是当前member
    Notification.where(
      type: "CommentNotification",
      recipient: current_member,
      # 用JSON路径查询params里的comment关联信息
      "params->'comment'->>'commentable_id'": @post.id.to_s,
      "params->'comment'->>'commentable_type'": "Post"
    ).update_all(read_at: Time.zone.now)
  end
end

方案2:通过模型关联查询(更优雅)

先完善模型间的关联关系:

  1. 在Comment模型中添加与Notification的关联:
class Comment < ApplicationRecord
  belongs_to :commentable, polymorphic: true
  # 关联到触发该评论的通知
  has_many :notifications, as: :notifiable, class_name: "Notification"
end
  1. 在Post模型中通过评论关联到通知:
class Post < ApplicationRecord
  has_many :comments, as: :commentable
  # 通过评论间接关联到所有相关通知
  has_many :notifications, through: :comments, source: :notifications
end
  1. 简化mark_notifications_as_read方法:
def mark_notifications_as_read
  if current_member
    @post.notifications.where(recipient: current_member).update_all(read_at: Time.zone.now)
  end
end

验证步骤

  1. 执行代码后,查看Rails控制台的UPDATE语句,确认WHERE条件正确且rows affected大于0。
  2. 在irb中重新查询对应的Notification对象,检查read_at字段是否已被赋值。
  3. 刷新应用页面,查看通知计数器是否更新。

内容的提问来源于stack exchange,提问作者DebakeDSP94

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 21:17:12