В настоящее время у меня есть модель активности, которая обрабатывает систему уведомлений о деятельности пользователя. Наблюдатель активности создает новое действие, когда происходит какое-либо действие (например, создаваемая новая статья). Теперь я хочу сохранить запись о том, сколько из этих уведомлений о деятельности, которых не видел текущий пользователь (аналогично уведомлению на facebook). Каждый раз, когда пользователь нажимает на свою ссылку на уведомления, номер должен reset до 0, и каждое созданное уведомление должно увеличивать количество на 1. Где я буду хранить эти данные для каждого пользователя? Использует ли сеанс работу или что-то еще лучше?
Rails: учет количества непрочитанных уведомлений пользователей
Ответ 1
Существует несколько возможных подходов к этому: нормализованный и денормализованный. Я начну с нормализации:
Подход 1: Нормализованный
Похоже, у вас здесь три модели: действия, уведомления ( "user_activities" ) и пользователи. Исправьте меня, если я ошибаюсь в своих предположениях здесь:
- Деятельность принадлежит_у: user и has_many: уведомления (один пользователь выполняет активность, и несколько пользователей получают уведомление об активности)
- Уведомление принадлежит_у: activity и принадлежит_to: пользователю и имеет атрибут "читать" /флаг
- Пользователь has_many: уведомления
В обратном вызове after_create на активность модель должна определить, какие пользователи должны получать уведомления об этом действии, а затем уведомлять их, создавая объекты уведомлений для каждого из них.
В уведомлениях вы можете создать метод класса, называемый непрочитанным, который указывает условие, что флаг чтения активности имеет значение false:
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
В User:
def notify
update_attributes(:unseen_count => unseen_count + 1)
end
def see_activities
update_attributes(:unseen_count => 0)
end
Недостатком этого подхода является то, что вы исключили модель уведомления, так что у пользователя есть только количество уведомлений и не может просмотреть подробный список уведомлений и связанных с ними действий. Вы можете использовать гибридный подход, но помните, что рискованно иметь дело с двумя источниками истины для подсчета невидимых уведомлений.
На стороне примечания: может быть более целесообразно вызвать notify_users в observer вместо after_create непосредственно в модели:
class ActivityObserver < ActiveRecord::Observer
def after_create(activity)
activity.users_to_notify.each &:notify
end
end
Если вы используете наблюдателя, вы можете удалить Activity # notify_users и Activity # after_create.
Ответ 2
Пожалуйста, посмотрите на этот камень:
https://github.com/ledermann/unread
Он написан мной и обрабатывает прочитанный/непрочитанный статус любых объектов ActiveRecord более эффективным образом.