Curated library of AI agent skills for Ruby on Rails development. Covers code review, architecture, security, testing (RSpec), engines, service objects, DDD patterns, and workflow automation.
73
91%
Does it follow best practices?
Impact
—
No eval scenarios have been run
Passed
No known issues
Use this skill when the task is to add, configure, or review background jobs in a Rails application.
Core principle: Design jobs for idempotency and safe retries. Prefer Active Job's unified API; choose backend based on Rails version and scale.
EVERY job MUST have its test written and validated BEFORE implementation.
1. Write the job spec (idempotency, retry, error handling)
2. Run the spec — verify it fails because the job does not exist yet
3. ONLY THEN write the job class
See rspec-best-practices for the full gate cycle.| Aspect | Rule |
|---|---|
| Arguments | Pass IDs, not objects. Load in perform. |
| Idempotency | Check "already done?" before doing work |
| Retries | retry_on for transient, discard_on for permanent errors |
| Job size | One responsibility. Call services for complex logic. |
| Backend (Rails 8) | Solid Queue (database-backed, no Redis) |
| Backend (Rails 7) | Sidekiq + Redis for high throughput |
| Recurring | config/recurring.yml (Solid Queue) or cron/sidekiq-cron |
EVERY job that performs side effects (charge, email, API call) MUST have
an idempotency check before the side effect.| Aspect | Rails 7 and earlier | Rails 8 |
|---|---|---|
| Default | No default; set queue_adapter (often Sidekiq) | Solid Queue (database-backed) |
| Dev/test | :async or :inline | Same |
| Recurring | External (cron, sidekiq-cron) | config/recurring.yml |
| Dashboard | Third-party (Sidekiq Web) | Mission Control Jobs |
perform.retry_on for transient errors, discard_on for permanent failures.Bad: Passing ActiveRecord object (can be stale/missing):
# In controller:
SomeJob.perform_later(@order) # @order is an ActiveRecord object
# In job:
class SomeJob < ApplicationJob
def perform(order) # If @order is stale or deleted, this will fail
order.process!
end
endGood: Passing only the ID (always reliable):
# In controller:
SomeJob.perform_later(@order.id) # Only pass the ID
# In job:
class SomeJob < ApplicationJob
def perform(order_id)
order = Order.find(order_id) # Always re-load fresh data inside the job
order.process!
end
endJob with idempotency and retry:
class NotifyOrderShippedJob < ApplicationJob
queue_as :default
retry_on Net::OpenTimeout, wait: :polynomially_longer, attempts: 5
discard_on ActiveRecord::RecordNotFound
def perform(order_id)
order = Order.find(order_id)
return if order.shipped_notification_sent?
OrderMailer.shipped(order).deliver_now
order.update!(shipped_notification_sent_at: Time.current)
end
endRecurring job (Solid Queue):
# config/recurring.yml
production:
nightly_cleanup:
class: "NightlyCleanupJob"
schedule: "0 2 * * *"
hourly_sync:
class: "HourlySyncJob"
schedule: "every 1 hour"
queue: low| Mistake | Reality |
|---|---|
| Passing ActiveRecord objects as arguments | Object may be deleted or stale by perform time. Pass IDs. |
| No idempotency check before side effects | Jobs run at-least-once. Double-charging, double-emailing. |
retry_on without attempts limit | Infinite retries on persistent errors |
Using :inline or :async in production | No persistence, no retry, no monitoring |
Complex business logic in perform | Keep perform thin. Delegate to service objects. |
Missing discard_on for permanent errors | Job retries forever on RecordNotFound |
:inline or :async in productionrecurring.yml or equivalentperform — exceptions silently discarded or retried endlessly| Skill | When to chain |
|---|---|
| rails-migration-safety | Solid Queue uses DB tables; add migrations safely |
| rails-security-review | Jobs receive serialized input; validate like any entry point |
| rspec-best-practices | TDD gate: write and validate job spec before implementation |
| ruby-service-objects | Keep perform thin; call service objects for business logic |
| rspec-best-practices | Use perform_enqueued_jobs to test; test idempotency |
api-rest-collection
create-prd
ddd-boundaries-review
ddd-rails-modeling
ddd-ubiquitous-language
generate-tasks
rails-agent-skills
rails-architecture-review
rails-background-jobs
rails-bug-triage
rails-code-conventions
rails-code-review
rails-engine-compatibility
rails-engine-docs
rails-engine-extraction
rails-engine-installers
rails-engine-release
rails-engine-reviewer
rails-engine-testing
rails-graphql-best-practices
rails-migration-safety
rails-review-response
rails-security-review
rails-stack-conventions
rails-tdd-slices
refactor-safely
rspec-best-practices
rspec-service-testing
ruby-api-client-integration
ruby-service-objects
strategy-factory-null-calculator
ticket-planning
yard-documentation