Rails中使用Noticed Gem时多态评论通知无法标记为已读问题
解决多态评论下Noticed Gem通知标记已读失效问题
问题分析
从你提供的信息来看,核心问题有两个:
- 原方法执行了UPDATE但无实际修改,说明查询条件未匹配到目标通知——因为你的通知是由多态评论触发的,直接关联到
Comment而非Post,@post.notifications_as_post这个关联可能根本找不到对应的通知记录,控制台的UPDATE实际影响行数为0。 - 修改后的方法报错是因为
@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:通过模型关联查询(更优雅)
先完善模型间的关联关系:
- 在
Comment模型中添加与Notification的关联:
class Comment < ApplicationRecord belongs_to :commentable, polymorphic: true # 关联到触发该评论的通知 has_many :notifications, as: :notifiable, class_name: "Notification" end
- 在
Post模型中通过评论关联到通知:
class Post < ApplicationRecord has_many :comments, as: :commentable # 通过评论间接关联到所有相关通知 has_many :notifications, through: :comments, source: :notifications end
- 简化
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
验证步骤
- 执行代码后,查看Rails控制台的UPDATE语句,确认
WHERE条件正确且rows affected大于0。 - 在irb中重新查询对应的Notification对象,检查
read_at字段是否已被赋值。 - 刷新应用页面,查看通知计数器是否更新。
内容的提问来源于stack exchange,提问作者DebakeDSP94
相关产品推荐
相关产品推荐

