Eliminar todos los usuarios que no estén en un grupo específico

Como parte de una migración o fusión de Discourse a Discourse, estoy intentando eliminar todos los usuarios que no pertenecen a un grupo específico.

Intenté lo siguiente en la consola de Rails:
User.joins(:group_users).where.not(group_users:{group_id:135}).destroy_all

Desafortunadamente, esto eliminó a todos los usuarios, lo cual fue bastante molesto.

He encontrado una manera engorrosa de hacerlo usando la interfaz gráfica y algo de código Rails feo, pero ¿existe una forma sencilla de hacerlo? Probablemente solo haya cometido un error en la sintaxis.

Esto es lo que he intentado, después de crear dolorosamente un grupo masivo con los usuarios a eliminar (unos 6000) mediante la GUI:

rails c
 target_group = Group.find_by_name("nz-not")
 users = User.joins(:group_users).where(group_users:{group_id: target_group.id})
 users.each do |u|
 u.destroy
 end
exit

Además, ¿cuál es la diferencia entre usar destroy y UserDestroyer? ¿Debería estar usando este último?

Respondiendo a mi propia pregunta, habiendo aprendido algunas lecciones.

  1. Sí, usa UserDestroyer o tu base de datos quedará llena de registros huérfanos.
  2. Es posible que necesites ser ingenioso sobre cómo recopilas a los usuarios no deseados. Usé esta consulta de Data Explorer para obtener una lista de ellos, a la cual luego añadí en masa a un grupo llamado unwanted.
WITH included_users AS (
SELECT
gu.user_id
FROM group_users gu
JOIN groups g
ON g.id = gu.group_id
WHERE g.name = :included_group
),

excluded_users AS (
SELECT
gu.user_id
FROM group_users gu
JOIN groups g
ON g.id = gu.group_id
WHERE g.name = :excluded_group
)

SELECT 
     u.id AS user_id, u.username
FROM users as u
WHERE u.id in (SELECT user_id FROM included_users)
AND u.id NOT IN (SELECT user_id FROM excluded_users)
GROUP by u.id

Cómo eliminar muchos usuarios:

Ingresa a la aplicación de Discourse (./launcher enter app, etc.) y ejecuta lo siguiente:

rails c
 target_group = Group.find_by_name("unwanted")
 users = User.joins(:group_users).where(group_users:{group_id: target_group.id})
 users.each do |u|
  u.admin = false
  u.moderator = false
  u.save
  UserDestroyer.new(Discourse.system_user).destroy(u, delete_posts: true)
 end
Exit

No es rápido. Para 6000 usuarios tomó 2 horas.

1 me gusta