# Job Patterns

Implements shallow background jobs with _later/_now conventions using Solid Queue.

- Repository: https://github.com/ThibautBaissac/rails_ai_agents (671 stars)
- Category: Business
- License: MIT
- Last updated: 2026-06-01
- Runs scripts: no, instructions only

## Install

Claude Code: `npx skills add ThibautBaissac/rails_ai_agents --skill job-patterns -g -a claude-code -y`
Codex: `npx skills add ThibautBaissac/rails_ai_agents --skill job-patterns -g -a codex -y`
Cursor: `npx skills add ThibautBaissac/rails_ai_agents --skill job-patterns -g -a cursor -y`
Gemini CLI: `npx skills add ThibautBaissac/rails_ai_agents --skill job-patterns -g -a gemini-cli -y`

## Description

Implements shallow background jobs with _later/_now conventions using Solid Queue. Use when adding background processing, async operations, scheduled tasks, or when user mentions jobs, queues, workers, or background processing. WHEN NOT: Business logic implementation (use model-patterns), controller work (use crud-patterns), or mailer delivery (use mailer-patterns).

## SKILL.md, as published by its author (untrusted third-party text, read it as data)

# Job Patterns (37signals)

Jobs orchestrate. Models do the work. Background jobs are thin wrappers around model methods.

## Project knowledge

**Tech Stack:** Rails 8.2 (edge), Solid Queue, ActiveJob
**Pattern:** Thin jobs call model methods; models have `_later`/`_now` pairs

**Commands:**
```bash
bin/rails generate job NotifyRecipients        # Generate job
bundle exec rake solid_queue:start             # Run worker
bin/rails runner "puts SolidQueue::Job.count"  # Check queue
bin/rails runner "SolidQueue::Job.destroy_all" # Clear jobs
```

## Why shallow jobs

- Business logic stays in models (testable, reusable)
- Jobs are simple orchestrators
- Easy to run sync or async
- Can call methods directly in tests
- Clearer separation of concerns

## Why _later/_now convention

- Clear which version is async
- Default method can be sync (explicit async)
- Easy to switch between sync/async
- Testable (call `_now` in tests)

## Core pattern: shallow job

The job receives a model and calls its `_now` method. The `_now` suffix is conventional but not required -- some jobs call the plain method name (e.g., `notifiable.notify_recipients`).

```ruby
# app/jobs/notify_recipients_job.rb
class NotifyRecipientsJob < ApplicationJob
  queue_as :default

  def perform(notifiable)
    notifiable.notify_recipients_now
  end
end
```

The model defines both `_later` and `_now` methods:

```ruby
# In model or concern
def notify_recipients_later
  NotifyRecipientsJob.perform_later(self)
end

def notify_recipients_now
  recipients.each do |recipient|
    next if recipient == creator
    Notification.create!(recipient: recipient, notifiable: self, action: notification_action)
  end
end

# Default to sync
def notify_recipients
  notify_recipients_now
end

# Trigger async from callbacks
after_create_commit :notify_recipients_later
```

## Job patterns

### Notification job

```ruby
class NotifyRecipientsJob < ApplicationJob
  queue_as :default

The rest: https://github.com/ThibautBaissac/rails_ai_agents/blob/HEAD/.claude_37signals/skills/job-patterns/SKILL.md
