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.
Generates and manages Rails background jobs with Active Job, including queueing, retries, callbacks, and testing.
npx claudepluginhub bastos/ruby-plugin-marketplaceThis skill inherits all available tools. When active, it can use any tool Claude has access to.
Comprehensive guide to background job processing in Rails with Active Job.
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
# 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)
)
# 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)
class ProcessOrderJob < ApplicationJob
queue_as :high_priority
end
# Or dynamically
ProcessOrderJob.set(queue: :urgent).perform_later(order)
class LowPriorityJob < ApplicationJob
queue_as :default
queue_with_priority 50 # Higher number = lower priority
end
# Dynamic priority
ImportantJob.set(priority: 10).perform_later(data)
# config/application.rb or config/environments/*.rb
config.active_job.queue_adapter = :async
| Adapter | Best For | Notes |
|---|---|---|
:async | Development | In-process, not for production |
:inline | Testing | Runs immediately |
:test | Testing | Stores jobs for assertions |
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
| Option | Description |
|---|---|
wait | Seconds to wait (:polynomially_longer for backoff) |
attempts | Number of retry attempts |
queue | Queue for retried job |
priority | Priority for retried job |
class DataImportJob < ApplicationJob
discard_on ActiveJob::DeserializationError
discard_on CustomPermanentError
def perform(record_id)
record = Record.find(record_id)
# ...
end
end
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
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
Active Job automatically serializes:
# 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"
# 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
# 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
# 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
perform_now - Test job logic synchronouslyActivates when the user asks about AI prompts, needs prompt templates, wants to search for prompts, or mentions prompts.chat. Use for discovering, retrieving, and improving prompts.
Search, retrieve, and install Agent Skills from the prompts.chat registry using MCP tools. Use when the user asks to find skills, browse skill catalogs, install a skill for Claude, or extend Claude's capabilities with reusable AI agent components.
Creating algorithmic art using p5.js with seeded randomness and interactive parameter exploration. Use this when users request creating art using code, generative art, algorithmic art, flow fields, or particle systems. Create original algorithmic art rather than copying existing artists' work to avoid copyright violations.