Cambio masivo de propiedad de las primeras publicaciones por etiqueta: revisión y sugerencias de script

Hola,

Estoy buscando cambiar la propiedad de todas las publicaciones iniciales en temas de eventos etiquetados con “ethan” para que el propietario cambie de “system” al usuario “Ethan_Hoom1”. Estoy ejecutando una instancia autoalojada y tengo acceso a la consola de Rails.

Después de revisar las recomendaciones en Administrative Bulk Operations y Change ownership of all posts by a specific user, he preparado el siguiente script. Agradecería cualquier sugerencia o mejores prácticas antes de ejecutarlo en producción:


# Encuentra el objeto de etiqueta con el nombre "ethan"
tag = Tag.find_by(name: "ethan")

# Detente inmediatamente si la etiqueta no se encuentra
raise "Tag not found" unless tag


# Encuentra el usuario que se convertirá en el nuevo propietario de las publicaciones
# username_lower es más seguro que username (insensible a mayúsculas y minúsculas)
new_owner = User.find_by(username_lower: "ethan_hoom1")

# Detente inmediatamente si el usuario de destino no existe
raise "New owner user not found" unless new_owner


# Encuentra la cuenta de usuario del sistema
# Recurre a Discourse.system_user en caso de que la búsqueda del registro falle
system_user = User.find_by(username_lower: "system") || Discourse.system_user

# Detente inmediatamente si no se puede encontrar el usuario del sistema
raise "System user not found" unless system_user


# Cuando sea verdadero, el script solo imprimirá lo que CAMBIARÍA
# y no modificará nada en la base de datos
DRY_RUN = true

# Límite de seguridad opcional para la primera ejecución (ej. 10 o 50)
# Establécelo en nil para procesar todas las publicaciones coincidentes
LIMIT = nil


# Construye una consulta ActiveRecord para las publicaciones que queremos modificar
scope = Post
  # Une publicaciones → temas → topic_tags para poder filtrar por etiqueta
  .joins(topic: :topic_tags)

  # Solo apunta a la publicación inicial en cada tema
  .where(post_number: 1)

  # Solo apunta a las publicaciones actualmente propiedad del usuario del sistema
  .where(user_id: system_user.id)

  # Solo incluye temas que tienen la etiqueta "ethan"
  .where(topic_tags: { tag_id: tag.id })

  # Excluye mensajes privados y temas eliminados
  .where(topics: {
    archetype: Archetype.default,
    deleted_at: nil
  })


# Si LIMIT está configurado, restringe cuántas publicaciones se procesan
scope = scope.limit(LIMIT) if LIMIT


# Itera a través de las publicaciones coincidentes por lotes para evitar problemas de memoria
scope.find_each(batch_size: 100) do |first_post|

  # Almacena el ID del tema para la salida de registro
  topic_id = first_post.topic_id


  # Si el modo dry-run está habilitado, no modifiques nada
  if DRY_RUN
    puts "[DRY RUN] Would change owner for topic #{topic_id} (post #{first_post.id})"
    next
  end


  begin
    # Usa el servicio oficial de cambio de propietario de Discourse
    PostOwnerChanger.new(
      # Solo cambia la propiedad de la publicación inicial
      post_ids: [first_post.id],

      # El tema que contiene la publicación
      topic_id: topic_id,

      # El usuario que se convertirá en el nuevo propietario
      new_owner: new_owner,

      # El usuario que realiza la acción (usuario del sistema)
      acting_user: system_user,

      # No crear una revisión de edición para este cambio
      skip_revision: true
    ).change_owner!


    # Registra el éxito en la consola
    puts "Changed owner for topic #{topic_id} (post #{first_post.id})"

  rescue => e
    # Si algo falla, registra el error pero continúa procesando otros
    puts "FAILED topic #{topic_id} (post #{first_post.id}): #{e.class}: #{e.message}"
  end
end

Preguntas:

  • ¿Hay alguna advertencia o caso extremo que deba tener en cuenta con PostOwnerChanger para este caso de uso?
  • ¿Es aconsejable actualizar también el campo topic.user como se muestra en la línea opcional?
  • ¿Tiene alguna recomendación para mejorar aún más la seguridad o el rendimiento con respecto a este proceso por lotes?

¡Gracias por su ayuda y por toda la excelente documentación!

1 me gusta