С тех пор (очевидно, это заняло некоторое время!) я нашел два способа решить эту задачу. Можно сделать это через интерфейс, что хорошо работает для небольших категорий (и небольших групп). Нужно проявлять осторожность, чтобы не отправлять ненужные уведомления в процессе, но это вполне выполнимо.
Альтернативный вариант — использовать консоль Rails (при условии, что у вас собственная установка), что быстрее и гораздо мощнее.
Через интерфейс
- Удалите остальных участников группы из группы (но сохраните список имен пользователей/адресов электронной почты, чтобы легко добавить их обратно). Это предотвратит отправку уведомлений.
- Пройдитесь по каждой теме в категории, преобразуя каждую из них в личное сообщение (PM) с помощью меню администратора (иконка гаечного ключа)
- Я нахожу, что удобнее всего открывать каждую тему в отдельной вкладке, а затем последовательно переключаться между ними
- Добавьте группу к каждой из тем (теперь это личные сообщения)
- Добавьте участников группы обратно в группу
- Очистите / удалите все «маленькие сообщения» в каждом личном сообщении по желанию
В консоли Rails
Доступ к консоли осуществляется путем входа в контейнер и запуска консоли:
./launcher enter app
rails c
Установите категорию и группу, затем скопируйте приведенный ниже скрипт в консоль:
category_id = =CategoryID=
group_name = '=GroupName='
group = Group.find_by('lower(name) = ?', group_name.downcase)
about_id = Category.find(category_id).topic_id
topic_ids = Topic.where(category_id: category_id).where.not(id: about_id).pluck(:id)
Topic.where(id: topic_ids).find_each do |topic|
topic.archetype = Archetype.private_message
topic.category_id = nil
topic.subtype = 'user_to_user'
topic.save!
TopicAllowedGroup.find_or_create_by!(topic_id: topic.id, group_id: group.id)
Post.where(topic_id: topic.id).pluck(:user_id).uniq.each do |uid|
TopicAllowedUser.find_or_create_by!(topic_id: topic.id, user_id: uid)
end
end
Этот скрипт вообще не уведомляет пользователей и корректно сохраняет участников постов (на случай, если они не входят в группу).
Обратите внимание: если вы хотите удалить категорию до того, как фоновая задача пересчитает всё, возможно, потребуется запустить это в консоли Rails:
Jobs::CategoryStats.new.execute(category_id: category_id)
Скрипт для обратного процесса (из входящих группы в категорию), нажмите, чтобы раскрыть
Этот скрипт должен корректно перенести данные в обратном направлении (не проверено)
category_id = =CategoryID=
group_name = '=GroupName='
group = Group.find_by('LOWER(name) = ?', group_name.downcase)
raise "Группа не найдена" unless group
topic_ids = TopicAllowedGroup.where(group_id: group.id).pluck(:topic_id)
topics = Topic.where(id: topic_ids, archetype: Archetype.private_message, deleted_at: nil)
topics.find_each do |topic|
topic.archetype = Archetype.default # или "regular"
topic.subtype = nil
topic.category_id = target_category_id
topic.save!
end