我目前有一个处理用户活动通知系统的活动模型。当某个动作发生时(例如正在创建新文章),活动观察者会创建一个新活动。现在我想记录当前用户有多少活动通知没有看到(类似于 facebook 上的通知宝石)。每次用户单击他们的通知链接时,该数字应重置为 0,并且创建的每个通知都应将计数增加 1。我将在哪里为每个用户存储此数据?使用会话工作还是其他更好的方法?
2 回答
有几种可能的方法:规范化和非规范化。我将从标准化开始:
方法一:归一化
听起来您在这里使用了三个模型:活动、通知(“user_activities”)和用户。如果我在这里的假设有误,请纠正我:
- Activity belongs_to :user 和 has_many :notifications (一个用户执行一个活动,多个用户收到该活动的通知)
- 通知belongs_to :activity 和belongs_to :user 并具有“读取”属性/标志
- 用户 has_many :通知
在活动的 after_create 回调中,模型应该确定哪些用户需要该活动的通知,然后通过为每个用户创建通知对象来通知他们。
在通知上,您可以创建一个名为 unread 的类方法,它指定活动的读取标志为假的条件:
def self.unread
where(:read => false)
end
然后,要访问用户的未读通知计数,只需调用:
user.notifications.unread.count
当用户查看他的通知时,调用:
user.notifications.unread.update_all(:read => true)
方法 2:非规范化
在这种方法中,每当创建活动时,它应该为每个通知用户手动增加一个计数器。您可以通过以下任一方式完成此操作:
- 用户的“unseen_count”属性
- 非关系型数据库(如redis)中的键值对
在活动中:
def users_to_notify
# Find a list of users to notify
end
def notify_users(users)
users.each &:notify
end
def after_create
notify_users(users_to_notify)
end
在用户中:
def notify
update_attributes(:unseen_count => unseen_count + 1)
end
def see_activities
update_attributes(:unseen_count => 0)
end
这种方法的缺点是您已经消除了通知模型,因此用户只有原始的通知计数,并且无法查看通知及其相关活动的详细列表。您可以使用混合方法,但请记住,处理两个真相来源以获得未见通知计数是有风险的。
附带说明:在观察者中调用 notify_users而不是直接在模型上调用 after_create可能更有意义:
class ActivityObserver < ActiveRecord::Observer
def after_create(activity)
activity.users_to_notify.each &:notify
end
end
如果您使用观察者,您可以删除 Activity#notify_users 和 Activity#after_create。
请看看这个宝石:
https ://github.com/ledermann/unread
它由我编写,并以更高效的方式处理任何 ActiveRecord 对象的已读/未读状态。