smithery/ZempTime

vanilla-rails-jobs

Use when writing background jobs or async operations - enforces thin job wrappers (3-5 lines) that delegate to models using _later/_now naming pattern

Installation

$ npx skills add smithery/ZempTime --skill vanilla-rails-jobs

Similar popular skills

Related neighbors and high-traction skills in the same topics — useful to compare before installing.

Also in this package

Other skills from smithery/ZempTime.

npx skills add smithery/ZempTime

Browse all from smithery/ZempTime

More details

Agent compatibility

Declared targets from SKILL.md / docs. Unmarked agents are not listed — the skill may still install via the CLI.

Claude Code Not declared
Cursor Not declared
Codex Not declared
GitHub Copilot Not declared
Windsurf Not declared
Gemini CLI Not declared
Cline Not declared
OpenCode Not declared

Package contents

Files included with this skill beyond the listing page.

  • skill md SKILL.md 2,522 B
  • docs SUMMARY.md 176 B

History

  1. First recorded snapshot · 0 installs

SKILL.md

Vanilla Rails Jobs

Jobs are thin wrappers (3-5 lines). ALL business logic lives in models.

The Pattern

# Model concern - WHERE THE LOGIC LIVES
module Card::ClosureNotifications
  extend ActiveSupport::Concern

  included do
    after_update :notify_watchers_later, if: :just_closed?
  end

  def notify_watchers_later
    Card::ClosureNotificationJob.perform_later(self)
  end

  def notify_watchers_now
    watchers.each do |watcher|
      CardMailer.closure_notification(watcher, self).deliver_now
      Notification.create!(user: watcher, card: self, action: 'closed')
    end
  end
end

# Job - ONLY delegates (3 lines)
class Card::ClosureNotificationJob < ApplicationJob
  def perform(card)
    card.notify_watchers_now
  end
end

Flow: Callback → later → enqueue job → job calls now → logic executes

Why Thin Jobs

  • Test _now synchronously — no job infrastructure needed
  • Reusable — call _now in console, tests, anywhere
  • Debuggable — stack traces point to model, not job framework

Edge Cases

Multi-model — primary model orchestrates:

class User::DigestJob < ApplicationJob
  def perform(user); user.send_digest_now; end
end

Utility/cleanup — use class methods:

class Session::CleanupJob < ApplicationJob
  def perform; Session.cleanup_expired_now; end
end

Error handling — ActiveJob retries + model errors:

class Card::SyncJob < ApplicationJob
  retry_on ExternalAPI::Error, wait: 5.minutes
  def perform(card); card.sync_to_external_system_now; end
end

Red Flags

Red flag Fix
Job > 5 lines (excluding retry_on) Move logic to model
Business logic in job Move to _now method on model
perform(card_id) then Card.find perform(card) — let ActiveJob serialize
No later/now naming Add suffixes
Missing _now method Always create — needed for testing
Job sends emails directly Model orchestrates, mailer delivers
Job has conditionals/loops Domain logic goes in model

Quick Check

  • Job is 3-5 lines, calls one model method
  • Receives model instance (not ID)
  • No queries, conditionals, or loops in job
  • Model has _later method (enqueues)
  • Model has _now method (logic)