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
PostOwnerChangerpour ce cas d’utilisation ? - Est-il conseillé de mettre également à jour le champ
topic.usercomme 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 !