From rails-agent-skills
Guides selection of first failing RSpec spec or vertical slice for Ruby on Rails TDD, covering request/model/service/job/engine specs, escalation, and sequencing.
npx claudepluginhub igmarin/rails-agent-skills --plugin rails-agent-skillsThis skill uses the workspace's default tool permissions.
Use this skill when the hardest part of the task is deciding where TDD should start.
Orchestrates Rails TDD cycle: generates failing RSpec spec first, implements minimal code to pass, refactors, adds YARD docs, runs linters, and creates self-reviewed PR. For red-green-refactor feature development.
Writes, fixes, and refactors RSpec tests for Ruby/Rails apps using describe/it blocks, expect matchers, test doubles, FactoryBot, and TDD best practices. Activates on spec files or test queries.
Assists writing, reviewing, and improving RSpec tests for Ruby on Rails apps including model, controller, system, and integration specs using Better Specs and thoughtbot best practices.
Share bugs, ideas, or general feedback.
Use this skill when the hardest part of the task is deciding where TDD should start.
Core principle: Start at the highest-value boundary that proves the behavior with the least unnecessary setup.
| Change type | First spec | Path | Why |
|---|---|---|---|
| API contract, params, status code, JSON shape | Request spec | spec/requests/ | Proves the real HTTP contract |
| Domain rule on a cohesive record or value object | Model spec | spec/models/ | Fast feedback on domain behavior |
| Multi-step orchestration across collaborators | Service spec | spec/services/ | Focuses on the workflow boundary |
| Enqueue/run/retry/discard behavior | Job spec | spec/jobs/ | Captures async semantics directly |
| Critical Turbo/Stimulus or browser-visible flow | System spec | spec/system/ | Use only when browser interaction is the real risk |
| Engine routing, generators, host integration | Engine spec | spec/requests/ or engine path | Normal app specs miss engine wiring — see rails-engine-testing |
| Bug fix | Reproduction spec | Where the bug is observed | Proves the fix and prevents regression |
| Unsure between layers | Higher boundary first | — | Easier to prove real behavior before drilling down |
DO NOT choose the first spec based on convenience alone.
DO NOT start with a lower-level unit if the real risk is request, job, engine, or persistence wiring.
ALWAYS run the chosen spec and verify it fails for the right reason before implementation.
spec/requests/..., spec/services/..., spec/jobs/..., spec/models/...).rspec-best-practices, rspec-service-testing, rails-engine-testing, or the implementation skill that fits the slice.# Behavior: POST /orders validates params and returns 201 with JSON payload
# First slice: request spec
# Suggested path: spec/requests/orders/create_spec.rb
RSpec.describe "POST /orders", type: :request do
let(:user) { create(:user) }
let(:valid_params) { { order: { product_id: create(:product).id, quantity: 1 } } }
before { sign_in user }
it "creates an order and returns 201" do
post orders_path, params: valid_params, as: :json
expect(response).to have_http_status(:created)
expect(response.parsed_body["id"]).to be_present
end
end
# Behavior: Orders::CreateOrder validates inventory, persists, and enqueues follow-up work
# First slice: service spec
# Suggested path: spec/services/orders/create_order_spec.rb
RSpec.describe Orders::CreateOrder do
subject(:result) { described_class.call(user: user, product: product, quantity: 1) }
let(:user) { create(:user) }
let(:product) { create(:product, stock: 5) }
it "returns a successful result with the new order" do
expect(result).to be_success
expect(result.order).to be_persisted
end
end
After writing and running the first failing spec, pause before implementation and present the test for review:
CHECKPOINT: Test Design Review
1. Present: Show the failing spec(s) written
2. Ask:
- Does this test cover the right behavior?
- Is the boundary correct (request vs service vs model)?
- Are the most important edge cases represented?
- Is the failure reason correct (feature missing, not setup error)?
3. Confirm: Only proceed to implementation once test design is approved.
Why this matters: Implementing against a poorly designed test wastes the TDD cycle. A 2-minute review of the test now prevents a full rewrite later.
Hand off: After test design is confirmed → rspec-best-practices for the full TDD gate cycle.
| Pitfall | What to do |
|---|---|
| Starting with a PORO spec because it is easy | Easy ≠ high-signal — choose the boundary that proves the real behavior |
| Writing three spec types before running any | Pick one slice, run it, prove the failure, then proceed |
| Defaulting to request specs for everything | Some domain rules are better proven at the model or service layer |
| Defaulting to model specs for controller behavior | Controllers and APIs need request-level proof |
| Using controller specs as the default HTTP entry point | Prefer request specs unless the repo has an existing reason |
| Jumping to system specs too early | Reserve for critical browser flows that lower layers cannot prove |
| "We'll add the request spec later" | The spec is the gate — implement only after the first slice is failing for the right reason |
| First spec requires excessive factory setup | Excessive setup = wrong boundary. Simplify or move the slice. |
| Skill | When to chain |
|---|---|
| rspec-best-practices | After choosing the first slice, to enforce the TDD loop correctly |
| rspec-service-testing | When the first slice is a service object spec |
| rails-engine-testing | When the first slice belongs to an engine |
| rails-bug-triage | When the starting point is an existing bug report |
| refactor-safely | When the task is mostly structural and needs characterization tests first |