Changement de masse de propriété des premiers messages par Tag – Revue de script et suggestions

Bonjour,

Je cherche à changer le propriétaire de tous les messages d’ouverture dans les sujets d’événement étiquetés avec « ethan » afin que le propriétaire passe de « system » à l’utilisateur « Ethan_Hoom1 ». J’utilise une instance auto-hébergée et j’ai accès à la console Rails.

Après avoir examiné les recommandations dans Administrative Bulk Operations et Change ownership of all posts by a specific user, j’ai préparé le script suivant. J’apprécierais tout conseil ou meilleure pratique avant de l’exécuter en production :


# Trouver l'objet tag avec le nom "ethan"
tag = Tag.find_by(name: "ethan")

# Arrêter immédiatement si le tag n'est pas trouvé
raise "Tag not found" unless tag


# Trouver l'utilisateur qui doit devenir le nouveau propriétaire des messages
# username_lower est plus sûr que username (insensible à la casse)
new_owner = User.find_by(username_lower: "ethan_hoom1")

# Arrêter immédiatement si l'utilisateur cible n'existe pas
raise "New owner user not found" unless new_owner


# Trouver le compte utilisateur système
# Revenir à Discourse.system_user au cas où la recherche d'enregistrement échoue
system_user = User.find_by(username_lower: "system") || Discourse.system_user

# Arrêter immédiatement si l'utilisateur système ne peut pas être trouvé
raise "System user not found" unless system_user


# Si vrai, le script affichera uniquement ce qu'il EST sur le point de changer
# et ne modifiera rien dans la base de données
DRY_RUN = true

# Limite de sécurité optionnelle pour le premier essai (par exemple, 10 ou 50)
# Mettre à nil pour traiter tous les messages correspondants
LIMIT = nil


# Construire une requête ActiveRecord pour les messages que nous voulons modifier
scope = Post
  # Joindre les messages → sujets → topic_tags afin de pouvoir filtrer par tag
  .joins(topic: :topic_tags)

  # Cibler uniquement le message d'ouverture de chaque sujet
  .where(post_number: 1)

  # Cibler uniquement les messages actuellement détenus par l'utilisateur système
  .where(user_id: system_user.id)

  # Inclure uniquement les sujets qui ont le tag "ethan"
  .where(topic_tags: { tag_id: tag.id })

  # Exclure les messages privés et les sujets supprimés
  .where(topics: {
    archetype: Archetype.default,
    deleted_at: nil
  })


# Si LIMIT est défini, restreindre le nombre de messages traités
scope = scope.limit(LIMIT) if LIMIT


# Itérer sur les messages correspondants par lots pour éviter les problèmes de mémoire
scope.find_each(batch_size: 100) do |first_post|

  # Stocker l'ID du sujet pour la sortie de journalisation
  topic_id = first_post.topic_id


  # Si le mode dry-run est activé, ne rien modifier
  if DRY_RUN
    puts "[DRY RUN] Would change owner for topic #{topic_id} (post #{first_post.id})"
    next
  end


  begin
    # Utiliser le service officiel de changement de propriétaire de Discourse
    PostOwnerChanger.new(
      # Changer uniquement le propriétaire du message d'ouverture
      post_ids: [first_post.id],

      # Le sujet contenant le message
      topic_id: topic_id,

      # L'utilisateur qui doit devenir le nouveau propriétaire
      new_owner: new_owner,

      # L'utilisateur effectuant l'action (utilisateur système)
      acting_user: system_user,

      # Ne pas créer de révision de modification pour ce changement
      skip_revision: true
    ).change_owner!


    # Journaliser le succès dans la console
    puts "Changed owner for topic #{topic_id} (post #{first_post.id})"

  rescue => e
    # Si quelque chose échoue, journaliser l'erreur mais continuer à traiter les autres
    puts "FAILED topic #{topic_id} (post #{first_post.id}): #{e.class}: #{e.message}"
  end
end

Questions :

  • Y a-t-il des mises en garde ou des cas limites dont je devrais être conscient concernant PostOwnerChanger pour ce cas d’utilisation ?
  • Est-il conseillé de mettre également à jour le champ topic.user comme indiqué dans la ligne facultative ?
  • Avez-vous des recommandations pour améliorer davantage la sécurité ou les performances concernant ce processus par lots ?

Merci pour votre aide et pour toute la documentation excellente !

1 « J'aime »