Olá,
Estou procurando alterar a propriedade de todas as postagens de abertura em tópicos de eventos marcados com “ethan” para que o proprietário mude de “system” para o usuário “Ethan_Hoom1”. Estou executando uma instância auto-hospedada e tenho acesso ao console do Rails.
Após revisar as recomendações em Administrative Bulk Operations e Change ownership of all posts by a specific user, preparei o seguinte script. Agradeceria quaisquer sugestões ou melhores práticas antes de executá-lo em produção:
# Encontra o objeto de tag com o nome "ethan"
tag = Tag.find_by(name: "ethan")
# Para imediatamente se a tag não for encontrada
raise "Tag not found" unless tag
# Encontra o usuário que se tornará o novo proprietário das postagens
# username_lower é mais seguro que username (insensível a maiúsculas e minúsculas)
new_owner = User.find_by(username_lower: "ethan_hoom1")
# Para imediatamente se o usuário de destino não for encontrado
raise "New owner user not found" unless new_owner
# Encontra a conta de usuário do sistema
# Retorna para Discourse.system_user caso a busca pelo registro falhe
system_user = User.find_by(username_lower: "system") || Discourse.system_user
# Para imediatamente se o usuário do sistema não puder ser encontrado
raise "System user not found" unless system_user
# Quando verdadeiro, o script apenas imprimirá o que MUDARIA
# e não modificará nada no banco de dados
DRY_RUN = true
# Limite de segurança opcional para a primeira execução (ex: 10 ou 50)
# Defina como nil para processar todas as postagens correspondentes
LIMIT = nil
# Constrói uma consulta ActiveRecord para as postagens que queremos modificar
scope = Post
# Junta postagens → tópicos → topic_tags para que possamos filtrar por tag
.joins(topic: :topic_tags)
# Visa apenas a postagem de abertura em cada tópico
.where(post_number: 1)
# Visa apenas postagens atualmente pertencentes ao usuário do sistema
.where(user_id: system_user.id)
# Inclui apenas tópicos que têm a tag "ethan"
.where(topic_tags: { tag_id: tag.id })
# Exclui mensagens privadas e tópicos excluídos
.where(topics: {
archetype: Archetype.default,
deleted_at: nil
})
# Se LIMIT estiver definido, restringe quantas postagens são processadas
scope = scope.limit(LIMIT) if LIMIT
# Itera sobre as postagens correspondentes em lotes para evitar problemas de memória
scope.find_each(batch_size: 100) do |first_post|
# Armazena o ID do tópico para saída de log
topic_id = first_post.topic_id
# Se o modo dry-run estiver ativado, não modifique nada
if DRY_RUN
puts "[DRY RUN] Would change owner for topic #{topic_id} (post #{first_post.id})"
next
end
begin
# Usa o serviço oficial de alteração de propriedade do Discourse
PostOwnerChanger.new(
# Altera a propriedade apenas da postagem de abertura
post_ids: [first_post.id],
# O tópico contendo a postagem
topic_id: topic_id,
# O usuário que se tornará o novo proprietário
new_owner: new_owner,
# O usuário que está realizando a ação (usuário do sistema)
acting_user: system_user,
# Não cria uma revisão de edição para esta alteração
skip_revision: true
).change_owner!
# Registra o sucesso no console
puts "Changed owner for topic #{topic_id} (post #{first_post.id})"
rescue => e
# Se algo falhar, registra o erro, mas continua processando os outros
puts "FAILED topic #{topic_id} (post #{first_post.id}): #{e.class}: #{e.message}"
end
end
Perguntas:
- Existem quaisquer ressalvas ou casos extremos que eu deva estar ciente com o
PostOwnerChangerpara este caso de uso? - É aconselhável atualizar também o campo
topic.usercomo mostrado na linha opcional? - Você tem alguma recomendação para maior segurança ou melhorias de desempenho em relação a este processo em lote?
Obrigado pela sua ajuda e por toda a ótima documentação!