Back to list
bastos

active-job

by bastos

Bastos' Claude Code Ruby Plugin Marketplace

0🍴 0📅 Jan 24, 2026

SKILL.md


name: active-job description: This skill should be used when the user asks about "background jobs", "Active Job", "perform_later", "perform_now", "queue adapters", "job retries", "job callbacks", "async tasks", "scheduled jobs", "job queues", or needs guidance on background processing in Rails applications. version: 1.0.0

Active Job

Comprehensive guide to background job processing in Rails with Active Job.

Creating Jobs

rails generate job ProcessOrder
# app/jobs/process_order_job.rb
class ProcessOrderJob < ApplicationJob
  queue_as :default

  def perform(order)
    # Process the order
    order.process!
    OrderMailer.confirmation(order).deliver_now
  end
end

Enqueueing Jobs

Immediate Enqueue

# Enqueue to run as soon as possible
ProcessOrderJob.perform_later(order)

# Enqueue multiple jobs at once
ActiveJob.perform_all_later(
  ProcessOrderJob.new(order1),
  ProcessOrderJob.new(order2)
)

Scheduled Execution

# Run at specific time
ProcessOrderJob.set(wait_until: Date.tomorrow.noon).perform_later(order)

# Run after delay
ProcessOrderJob.set(wait: 1.hour).perform_later(order)
ProcessOrderJob.set(wait: 5.minutes).perform_later(order)

# Run immediately (blocking, no queue)
ProcessOrderJob.perform_now(order)

Queue Selection

class ProcessOrderJob < ApplicationJob
  queue_as :high_priority
end

# Or dynamically
ProcessOrderJob.set(queue: :urgent).perform_later(order)

Priority

class LowPriorityJob < ApplicationJob
  queue_as :default
  queue_with_priority 50  # Higher number = lower priority
end

# Dynamic priority
ImportantJob.set(priority: 10).perform_later(data)

Queue Adapters

Configuration

# config/application.rb or config/environments/*.rb
config.active_job.queue_adapter = :async

Common Adapters

AdapterBest ForNotes
:asyncDevelopmentIn-process, not for production
:inlineTestingRuns immediately
:testTestingStores jobs for assertions

Retries and Error Handling

Automatic Retries

class ExternalApiJob < ApplicationJob
  retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 5
  retry_on CustomTransientError, wait: 5.seconds, attempts: 3

  def perform(record)
    ExternalApi.sync(record)
  end
end

Retry Options

OptionDescription
waitSeconds to wait (:polynomially_longer for backoff)
attemptsNumber of retry attempts
queueQueue for retried job
priorityPriority for retried job

Discard on Error

class DataImportJob < ApplicationJob
  discard_on ActiveJob::DeserializationError
  discard_on CustomPermanentError

  def perform(record_id)
    record = Record.find(record_id)
    # ...
  end
end

Custom Error Handling

class ProcessOrderJob < ApplicationJob
  rescue_from(PaymentError) do |exception|
    order = arguments.first
    order.mark_payment_failed!(exception.message)
    OrderMailer.payment_failed(order).deliver_later
  end

  def perform(order)
    PaymentService.charge(order)
  end
end

Callbacks

class ImportJob < ApplicationJob
  before_enqueue :log_enqueue
  after_enqueue :notify_enqueued

  before_perform :setup
  around_perform :measure_time
  after_perform :cleanup

  after_discard :log_discard

  private

  def log_enqueue
    Rails.logger.info "Enqueueing import job"
  end

  def setup
    @start_time = Time.current
  end

  def measure_time
    start = Time.current
    yield
    duration = Time.current - start
    Rails.logger.info "Job completed in #{duration}s"
  end

  def cleanup
    # Clean up resources
  end

  def log_discard(job, exception)
    Rails.logger.error "Job discarded: #{exception.message}"
  end
end

Job Arguments

Supported Types

Active Job automatically serializes:

  • Basic types (String, Integer, Float, NilClass, TrueClass, FalseClass, BigDecimal)
  • Symbol (as String)
  • Date, Time, DateTime
  • ActiveSupport::TimeWithZone
  • ActiveSupport::Duration
  • Hash (keys as strings)
  • ActiveSupport::HashWithIndifferentAccess
  • Array
  • Range
  • Module/Class
  • ActiveRecord objects (via GlobalID)

GlobalID Serialization

# ActiveRecord models are serialized via GlobalID
class NotifyUserJob < ApplicationJob
  def perform(user)
    # user is automatically deserialized from GlobalID
    UserNotifier.send_notification(user)
  end
end

NotifyUserJob.perform_later(User.find(1))
# Serialized as: "gid://myapp/User/1"

Custom Serializers

# app/serializers/money_serializer.rb
class MoneySerializer < ActiveJob::Serializers::ObjectSerializer
  def serialize(money)
    super("amount" => money.amount, "currency" => money.currency)
  end

  def deserialize(hash)
    Money.new(hash["amount"], hash["currency"])
  end

  private

  def klass
    Money
  end
end

# config/initializers/active_job.rb
Rails.application.config.active_job.custom_serializers << MoneySerializer

Mailer Integration

# Async email delivery
UserMailer.welcome(user).deliver_later
UserMailer.welcome(user).deliver_later(wait: 1.hour)
UserMailer.welcome(user).deliver_later(wait_until: Date.tomorrow.noon)

# Sync delivery (use in jobs)
UserMailer.welcome(user).deliver_now

Testing Jobs

Test Helper Methods

# test/jobs/process_order_job_test.rb
require "test_helper"

class ProcessOrderJobTest < ActiveJob::TestCase
  test "processes the order" do
    order = orders(:pending)

    ProcessOrderJob.perform_now(order)

    assert order.reload.processed?
  end

  test "enqueues job" do
    order = orders(:pending)

    assert_enqueued_with(job: ProcessOrderJob, args: [order]) do
      ProcessOrderJob.perform_later(order)
    end
  end

  test "sends confirmation email" do
    order = orders(:pending)

    assert_enqueued_emails 1 do
      ProcessOrderJob.perform_now(order)
    end
  end
end

Best Practices

  1. Keep jobs idempotent - Safe to run multiple times
  2. Use small arguments - Pass IDs, not large objects
  3. Handle missing records - Records may be deleted before job runs
  4. Set appropriate queues - Separate critical from low-priority work
  5. Monitor failed jobs - Use adapter's UI or custom monitoring
  6. Test with perform_now - Test job logic synchronously

Score

Total Score

65/100

Based on repository quality metrics

SKILL.md

SKILL.mdファイルが含まれている

+20
LICENSE

ライセンスが設定されている

+10
説明文

100文字以上の説明がある

0/10
人気

GitHub Stars 100以上

0/15
最近の活動

1ヶ月以内に更新

+10
フォーク

10回以上フォークされている

0/5
Issue管理

オープンIssueが50未満

+5
言語

プログラミング言語が設定されている

+5
タグ

1つ以上のタグが設定されている

+5

Reviews

💬

Reviews coming soon