Procesamiento en Background y Envío de Correos con Rails

Clase 30 de 33Curso de Creación de APIs con Ruby on Rails

Resumen

Domina el procesamiento en background en Rails con Active Job y prepara el envío de correos con ActionMailer. Aquí verás cómo generar un job que calcula un reporte de un post con conteo de palabras y histograma, siguiendo buenas prácticas: pasar IDs ligeros, usar clases modelo para datos y limpiar texto con Ruby.

¿Cómo integrar Active Job y ActionMailer en Rails sin gemas?

Rails incluye Active Job y ActionMailer, por lo que no se requieren dependencias externas. Además, hay generadores que crean la estructura base de forma rápida.

  • Generador de job: rails g job PostReport.
  • Clase del job: hereda de ApplicationJob y define perform.
  • Cola por defecto: anotación queue_as :default.
  • Adaptadores externos: Redis o Sidekiq permiten colas y prioridades.
  • Implementación por defecto: usa un thread pool; suficiente para empezar.

La recomendación clave es pasar IDs y no objetos completos. Así evitas problemas de serialización y mantienes mensajes ligeros. Con el ID se busca luego el registro con Rails.

¿Qué conviene pasar al job: IDs o modelos?

  • Pasa user_id y post_id en lugar de objetos User o Post.
  • Dentro del job, busca con User.find y Post.find.
  • Minimiza dependencias y evita cargas innecesarias.
rails g job PostReport
# app/jobs/post_report_job.rb
class PostReportJob < ApplicationJob
  queue_as :default

  def perform(user_id, post_id)
    user = User.find(user_id)
    post = Post.find(post_id)

    report = PostReport.generate(post)
    # Luego: usar ActionMailer para enviar el correo con report.
  end
end

¿Qué hace el background job PostReportJob?

El job genera un reporte de un post para un usuario y, en una fase posterior, se enviará por correo. Ese reporte incluye conteo de palabras y histograma de palabras. Crear una clase dedicada es una buena práctica: facilita crecer sin complicaciones.

¿Cómo estructurar la clase PostReport para escalar?

  • Define una clase PostReport en app/models.
  • Centraliza la lógica en un método de clase generate.
  • Expone atributos claros: word_count y word_histogram.
# app/models/post_report.rb
class PostReport
  attr_reader :word_count, :word_histogram

  def initialize(word_count:, word_histogram:)
    @word_count = word_count
    @word_histogram = word_histogram
  end

  def self.generate(post)
    words = post.content.split
                    .map { |w| w.gsub(/\W+/, "") }
                    .reject(&:empty?)

    new(
      word_count: words.count,
      word_histogram: calc_histogram(words)
    )
  end

  def self.calc_histogram(words)
    words.map(&:downcase)
         .group_by { |w| w }
         .transform_values(&:size)
  end
end

¿Cómo calcular word count e histograma con Ruby?

Para el conteo de palabras, se parte del contenido del post, se divide por espacios y se limpia la puntuación con gsub. Para el histograma, se normaliza todo a downcase, se agrupa con group_by y se cuenta con transform_values y size.

¿Cómo limpiar y normalizar el texto?

  • Separar por espacios: split.
  • Quitar puntuación: gsub con la expresión /\W+/.
  • Evitar vacíos: reject(&:empty?).
  • Normalizar: downcase.
content = "Hola, mundo. Hola!"
words = content.split
               .map { |w| w.gsub(/\W+/, "") }
               .reject(&:empty?)
# words => ["Hola", "mundo", "Hola"]

¿Cómo agrupar y contar ocurrencias?

  • Agrupar por palabra: group_by.
  • Contar por grupo: transform_values con size.
histogram = words.map(&:downcase)
                 .group_by { |w| w }
                 .transform_values(&:size)
# histogram => {"hola"=>2, "mundo"=>1}

¿Te gustaría ver el envío del correo con ActionMailer y cómo adjuntar este reporte? Comparte tus dudas o casos de uso en los comentarios.

      Procesamiento en Background y Envío de Correos con Rails