Ciao,
Sto cercando di cambiare la proprietà di tutti i post iniziali negli argomenti evento contrassegnati con “ethan” in modo che il proprietario cambi da “system” all’utente “Ethan_Hoom1”. Sto eseguendo un’istanza self-hosted e ho accesso alla console Rails.
Dopo aver esaminato le raccomandazioni in Administrative Bulk Operations e Change ownership of all posts by a specific user, ho preparato il seguente script. Apprezzerei qualsiasi suggerimento o best practice prima di eseguirlo in produzione:
# Trova l'oggetto tag con il nome "ethan"
tag = Tag.find_by(name: "ethan")
# Interrompi immediatamente se il tag non viene trovato
raise "Tag not found" unless tag
# Trova l'utente che dovrebbe diventare il nuovo proprietario dei post
# username_lower è più sicuro di username (case-insensitive)
new_owner = User.find_by(username_lower: "ethan_hoom1")
# Interrompi immediatamente se l'utente di destinazione non esiste
raise "New owner user not found" unless new_owner
# Trova l'account utente di sistema
# Ripiega su Discourse.system_user nel caso in cui la ricerca del record fallisca
system_user = User.find_by(username_lower: "system") || Discourse.system_user
# Interrompi immediatamente se l'utente di sistema non può essere trovato
raise "System user not found" unless system_user
# Quando è vero, lo script stamperà solo ciò che CAMBIEREBBE
# e non modificherà nulla nel database
DRY_RUN = true
# Limite di sicurezza opzionale per la prima esecuzione (es. 10 o 50)
# Impostato su nil per elaborare tutti i post corrispondenti
LIMIT = nil
# Costruisci una query ActiveRecord per i post che vogliamo modificare
scope = Post
# Unisci post → argomenti → topic_tags in modo da poter filtrare per tag
.joins(topic: :topic_tags)
# Mira solo al post iniziale in ogni argomento
.where(post_number: 1)
# Mira solo ai post attualmente di proprietà dell'utente di sistema
.where(user_id: system_user.id)
# Includi solo gli argomenti che hanno il tag "ethan"
.where(topic_tags: { tag_id: tag.id })
# Escludi messaggi privati e argomenti eliminati
.where(topics: {
archetype: Archetype.default,
deleted_at: nil
})
# Se LIMIT è impostato, limita il numero di post elaborati
scope = scope.limit(LIMIT) if LIMIT
# Itera attraverso i post corrispondenti in batch per evitare problemi di memoria
scope.find_each(batch_size: 100) do |first_post|
# Memorizza l'ID dell'argomento per l'output di log
topic_id = first_post.topic_id
# Se la modalità dry-run è abilitata, non modificare nulla
if DRY_RUN
puts "[DRY RUN] Would change owner for topic #{topic_id} (post #{first_post.id})"
next
end
begin
# Usa il servizio ufficiale di cambio proprietario di Discourse
PostOwnerChanger.new(
# Cambia la proprietà solo del post iniziale
post_ids: [first_post.id],
# L'argomento contenente il post
topic_id: topic_id,
# L'utente che dovrebbe diventare il nuovo proprietario
new_owner: new_owner,
# L'utente che esegue l'azione (utente di sistema)
acting_user: system_user,
# Non creare una revisione di modifica per questa modifica
skip_revision: true
).change_owner!
# Registra il successo sulla console
puts "Changed owner for topic #{topic_id} (post #{first_post.id})"
rescue => e
# Se qualcosa fallisce, registra l'errore ma continua a elaborare gli altri
puts "FAILED topic #{topic_id} (post #{first_post.id}): #{e.class}: #{e.message}"
end
end
Domande:
- Ci sono avvertenze o casi limite di cui dovrei essere a conoscenza con
PostOwnerChangerper questo caso d’uso? - È consigliabile aggiornare anche il campo
topic.usercome mostrato nella riga opzionale? - Hai qualche raccomandazione per ulteriori miglioramenti di sicurezza o prestazioni per quanto riguarda questo processo batch?
Grazie per il tuo aiuto e per tutta l’ottima documentazione!