Эта ошибка существует уже давно. Я исследовал её в прошлом году, и вот шаги для её воспроизведения:
- Как администратор, установите
max favorite badges(максимальное количество избранных значков) в значение 2 и создайте хотя бы один значок, который можно получить несколько раз. - Как обычный пользователь, добавьте два значка в избранное, один из которых — значок, который можно получить несколько раз (назовём его Значок A).
- Как администратор, выдайте пользователю Значок A повторно.
- Как обычный пользователь, обновите страницу и попробуйте убрать звезду с Значка A. Вы столкнётесь с ошибкой.
Причина ошибки заключается в том, что каждый раз при выдаче значка, который можно получить несколько раз, в базе данных создаётся новая запись user_badge. Однако, если пользователь уже добавил этот значок в избранное, а затем получил его снова, новая запись user_badge автоматически не помечается как is_favorite. Когда пользователь пытается убрать звезду с Значка A, фронтенд по умолчанию отправляет ID самой свежей записи user_badge. Поскольку эта запись не помечена как is_favorite, бэкенд предполагает, что пользователь пытается добавить новый значок в избранное (вместо того чтобы убрать его из избранного), что превышает лимит max favorite badges, и возникает ошибка.
Соответствующий код находится по адресу:
Одно из возможных решений — изменить строку 131 следующим образом:
if UserBadge.where(badge: user_badge.badge, user: user_badge.user).pluck(:is_favorite).any? &&
Однако это не устраняет полностью несоответствие записей в базе данных.
Как временное решение, обычный пользователь может убрать все значки из избранного, выполнив следующий JavaScript-код в консоли:
const user_name = require("discourse/models/user").default.current().username;
const badges = await require("discourse/models/user-badge").default.findByUsername(user_name);
const favorites = new Map();
badges.filter((b)=>b.is_favorite).forEach((b)=>favorites.set(b.badge_id,b));
favorites.forEach((b)=>b.favorite());