Elimina tutti gli utenti non appartenenti a un gruppo specifico

Come parte di una migrazione o fusione da Discourse a Discourse, sto cercando di eliminare tutti gli utenti che non fanno parte di un gruppo specifico.

Ho provato questo nella console di Rails:
User.joins(:group_users).where.not(group_users:{group_id:135}).destroy_all

Purtroppo, questo ha eliminato tutti gli utenti, il che è stato piuttosto fastidioso!

Ho trovato un modo macchinoso per farlo utilizzando l’interfaccia utente e un po’ di codice Rails poco elegante, ma esiste un modo più semplice? Probabilmente ho solo sbagliato la sintassi.

Ecco cosa ho provato, dopo aver creato con fatica un mega-gruppo contenente gli utenti da eliminare (circa 6000) tramite 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

Inoltre, qual è la differenza tra l’uso di destroy e UserDestroyer? Dovrei usare quest’ultimo?

Rispondo alla mia stessa domanda, avendo imparato alcune lezioni.

  1. Sì, usa UserDestroyer o il tuo database sarà pieno di record orfani.
  2. Potresti dover essere creativo su come raccogliere gli utenti indesiderati. Ho usato questa query di Data Explorer per ottenere un elenco di questi utenti, che ho poi aggiunto in blocco a un gruppo chiamato 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

Come eliminare molti utenti:

Entra nell’app Discourse (./launcher enter app, ecc.) ed esegui questi comandi:

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

Non è veloce. Per 6000 utenti ci sono volute 2 ore.

1 Mi Piace