Claude Code Prompts for Ruby on Rails

Copy-paste Claude Code prompts for Rails 7.1 + Hotwire — models, strong_params controllers, ActiveJob workers, RSpec specs. Matches modern Rails idioms.

💥 50p impulse-buy: Power Prompts PDF (first 10 buyers) 30 battle-tested Claude Code prompts · 8-page PDF · paste into CLAUDE.md and never re-type a prompt again · 50p impulse-buy, no commitment

Rails benefits hugely from Claude Code because the conventions are dense — generators, naming, file layout. Once Claude knows your team's deviations (service objects? ViewComponent? Trailblazer?) it produces idiomatic diffs. The prompts below assume Rails 7.1 and adjust easily.

Prompt 1 — Generate a resource with constraints

Add a Subscription resource.

Schema:
- belongs_to :account
- enum :status, [:trialing, :active, :past_due, :canceled], default: :trialing
- monetary :amount_cents, currency_column: :currency
- t.datetime :current_period_end, null: false
- indexes: (account_id, status), (current_period_end)

Constraints:
- Read app/models/charge.rb first as the template — match its style.
- Service object in app/services/subscriptions/ (one class per action). DO NOT
  put business logic in the controller or model.
- Controller follows the resource_controller pattern used by ChargesController.
- StrongParameters list explicit — no permit!.
- RSpec specs in spec/models/, spec/requests/. Use FactoryBot factories
  matching spec/factories/charges.rb.
- Don't run db:migrate. Generate the migration file only.
- Skip system specs for now.

Prompt 2 — Background job with idempotency

Write an ActiveJob worker SubscriptionsBillingJob that:
- Charges every active subscription whose current_period_end <= Time.current
- Runs hourly via solid_queue cron
- Is idempotent: if a charge for (subscription_id, current_period_end) already
  exists, skip — don't double-charge

Constraints:
- Queue: :billing (defined in config/queue.yml — read it first)
- Use Stripe::Charge.create with idempotency_key = "sub:#{id}:period:#{period_end.to_i}"
- Wrap each subscription in a transaction
- Log to Rails.logger.tagged('billing') with subscription_id
- Failure of one subscription must NOT abort the rest of the batch — rescue and
  send to ErrorTracker.notify
- Spec: stub Stripe with VCR cassette in spec/jobs/. Verify idempotency by
  running the job twice on the same data.

Prompt 3 — Refactor a fat controller

app/controllers/orders_controller.rb has 380 lines. Read it.

Identify the top 5 candidates for extraction:
- Each candidate: lines X-Y, what it does (1 sentence), where it should live
  (service / model method / concern / helper), and the destination class name.

Constraints:
- Do NOT extract things that are used only once and are < 5 lines.
- Service objects only if there's actual side-effect coordination (multiple
  models, jobs, external calls). Otherwise prefer model methods.
- Specify which existing patterns in this app you're matching (cite a file).
- Output the plan first. Wait for me to approve before writing the refactor.

CLAUDE.md anchor block for Rails

## Stack
Rails 7.1, Ruby 3.3, Postgres 16, Sidekiq (legacy) + SolidQueue (new code).
Hotwire (Turbo + Stimulus). ViewComponent for shared UI.

## Conventions
- Service objects in app/services//.rb, one public .call method.
- Form objects in app/forms/. No model-as-form-backing-store.
- Validations live on models. Authorisation in Pundit policies.
- Specs: RSpec, request specs over controller specs, system specs only for critical flows.
- Never use scaffold generators — too noisy.

Related: Claude API from Ruby, refactoring prompts.

Frequently asked questions

Does Claude write Rails 7 or older Rails?
It defaults to Rails 7.1 (Hotwire, encrypted attributes, async queries). Lock the version in CLAUDE.md if you're on 6.x — Claude will avoid 7+ helpers if told.
Can Claude follow Rails conventions automatically?
Mostly yes — Rails has strong conventions in training data. The failure mode is when your team deviates (e.g. service objects, dry-rb, ViewComponent). Document those deviations in CLAUDE.md so Claude doesn't 'correct' them back to vanilla Rails.
How do I get Claude to write RSpec instead of Minitest?
Say `Tests are RSpec, in spec/. Never generate test/ files or use ActiveSupport::TestCase` in CLAUDE.md. Claude alternates between the two without that hint.

Free tools

Cost Calculator → API Cookbook → Diff Summarizer → Skills Browser →

More examples

Claude API Python QuickstartClaude API Node.js / TypeScript QuickstartClaude API Streaming in PythonClaude API Streaming in Node.js / TypeScriptClaude API Tool Use in PythonClaude API Tool Use in Node.js / TypeScript