Cambio di proprietà in blocco dei primi post per Tag – Revisione script e suggerimenti

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 PostOwnerChanger per questo caso d’uso?
  • È consigliabile aggiornare anche il campo topic.user come 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!

1 Mi Piace