Пакетное преобразование тем из категории в личные сообщения группы

Я планирую перевести ряд тем в групповые личные сообщения, чтобы вывести из употребления малоиспользуемые категории. Сделать это через интерфейс нельзя (только по одной), и я не могу найти способ выполнить это массово.

Насколько я понимаю, это должно работать через консоль:

  1. Определить темы по их категории.
  2. Изменить topic.archetype на private_message.
  3. Изменить topic.subtype на ‘user_to_user’.
  4. Установить topic.category в Null.
  5. В таблице topic_groups (или, возможно, topic_allowed_groups) добавить запись с соответствующими group_id и topic_id.

Имеет ли смысл такой подход? Сначала, конечно, мне нужно разобраться в различиях между этими таблицами topic и groups. И начать с тестовой среды!

Это может сработать. Также, если вы не знаете, можно сделать что-то вроде:

 topics = Topic.where(category: 10)

  topics.update_all(archetype: xxx, topic_category: nil)

Или что-то подобное. Если вы знали о методе update_all, то это не новость.

Спасибо, Джей! Это было бы приятно и быстро для первой половины. Однако мне также нужно убедиться, что они в итоге станут групповыми менеджерами проектов.

Есть ли у вас идеи, что мне нужно сделать с таблицами topic_groups / topic_allowed_groups? Я не думаю, что смогу обойтись простым update_all для них.

С тех пор (очевидно, это заняло некоторое время!) я нашел два способа решить эту задачу. Можно сделать это через интерфейс, что хорошо работает для небольших категорий (и небольших групп). Нужно проявлять осторожность, чтобы не отправлять ненужные уведомления в процессе, но это вполне выполнимо.

Альтернативный вариант — использовать консоль Rails (при условии, что у вас собственная установка), что быстрее и гораздо мощнее.

Через интерфейс

  1. Удалите остальных участников группы из группы (но сохраните список имен пользователей/адресов электронной почты, чтобы легко добавить их обратно). Это предотвратит отправку уведомлений.
  2. Пройдитесь по каждой теме в категории, преобразуя каждую из них в личное сообщение (PM) с помощью меню администратора (иконка гаечного ключа)
    • Я нахожу, что удобнее всего открывать каждую тему в отдельной вкладке, а затем последовательно переключаться между ними
  3. Добавьте группу к каждой из тем (теперь это личные сообщения)
  4. Добавьте участников группы обратно в группу
  5. Очистите / удалите все «маленькие сообщения» в каждом личном сообщении по желанию

В консоли 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