Agents asked to test a Rails endpoint write a controller spec that checks the status code and stops there. The bugs that matter go untested: an unscoped find that shows another user's record, an owner_id accepted from the request body, a missing params key that turns into a 500. This loadout gives your agent RSpec rules for Rails 8.1. It uses request specs, not controller specs, with params.expect strong params and lookups scoped to the current owner. FactoryBot keeps the minimum valid record, with traits for variants. A skill lists what every endpoint's spec must cover and ships a complete, passing example. The verifier runs it in a Rails 8.1.4 API app on rspec-rails 8.0.4 in random order, runs rubocop with rubocop-rspec, and checks that removing the owner scope fails the 404 spec.
What's in it
- Request specs through routing, middleware and params, not controller specs
- Every endpoint: happy path, 422, 400, someone else's record (404) and mass assignment
- params.expect strong params; ownership set from the session, never the body
- FactoryBot sequences and traits; build_stubbed where no database is needed
- Verified on Rails 8.1.4, rspec-rails 8.0.4 and rubocop-rspec 3.10.2
You'll need
- Tools:
ruby,bundle
Verification
| Check | Result | What we found |
|---|---|---|
| Listinglisting.yaml matches the schema and declares every file in the folder. | Pass | Schema valid; 11 files declared, none missing or extra
|
| Files parseJSON parses; SKILL.md and .mdc front matter is valid YAML with the fields each agent needs; code fences are closed. | Pass | All 11 files parse; front matter valid |
| AdaptersCLAUDE.md imports @AGENTS.md, GEMINI.md imports @./AGENTS.md, and both match the generator. | Pass | CLAUDE.md and GEMINI.md import AGENTS.md and are up to date
|
| Install pathsEvery file lands where each agent documents it, with no collisions, and the laid-out project is re-discovered correctly. | Pass | Correct paths for all 6 agents; layouts re-discovered
|
| MCP configmcp.json is structurally valid, converts to each agent's format, declares no literal secrets, and referenced packages exist on npm/PyPI. | Not applicable | No MCP servers in this loadout |
| Safety scanThe intake scanner finds no credentials, risky shell, hidden Unicode or prompt-injection wording, and the listing's network flag is honest. | Pass | Clean: no credentials, risky shell or hidden text
|
| ReferencesLinks and file paths between the loadout's files resolve, including for each agent's installed layout. | Pass | 1 reference between files resolves for every agent |
| Size limitsFile count and sizes are within the submission limits; SKILL.md bodies stay under 500 lines. | Pass | 11 files, 11.2 KB total; largest skills/rspec-request-spec/references/projects_spec.rb 3.0 KB
|
| LicenceA recognised SPDX licence, with the licence text available. | Pass | MIT, by Agent Loadout; text in the repository LICENSE |
| Starter buildA minimal fixture project with the loadout applied installs and builds or type-checks, and the loadout's own code examples compile. | Pass | The rspec-request-spec skill's controller, model, factory and request spec run in a Rails 8.1.4 API app on rspec-rails 8.0.4 and FactoryBot 6.5.1: ten examples pass in random order, rubocop (omakase, rubocop-rspec, rubocop-rspec_rails) is clean, and removing the owner scope from the lookup fails the
|
What this means: a script checked the files themselves: they parse, they install where each agent looks, any MCP config is sound, the safety scan is clean, references between files resolve, and, where a free and repeatable fixture exists, a small starter project builds with the loadout applied. No AI agent was run. Per-agent results ("tested with agent") are separate and stay untested until an agent actually runs.
Install
Choose your agent. Run the commands from your project root, or download a zip already laid out in the right folders.
Claude Code reads CLAUDE.md (imports AGENTS.md with @AGENTS.md) and skills from .claude/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/AGENTS.md curl -fsSL --create-dirs -o CLAUDE.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/CLAUDE.md curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/SKILL.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/SKILL.md curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/references/projects_controller.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_controller.rb curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/references/project.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/project.rb curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/references/projects_factory.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_factory.rb curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/references/projects_spec.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_spec.rb curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/references/rails_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rails_helper.rb curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/references/spec_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/spec_helper.rb curl -fsSL --create-dirs -o .claude/skills/rspec-request-spec/references/rubocop.yml https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rubocop.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
CLAUDE.md | CLAUDE.md |
skills/rspec-request-spec/SKILL.md | .claude/skills/rspec-request-spec/SKILL.md |
skills/rspec-request-spec/references/projects_controller.rb | .claude/skills/rspec-request-spec/references/projects_controller.rb |
skills/rspec-request-spec/references/project.rb | .claude/skills/rspec-request-spec/references/project.rb |
skills/rspec-request-spec/references/projects_factory.rb | .claude/skills/rspec-request-spec/references/projects_factory.rb |
skills/rspec-request-spec/references/projects_spec.rb | .claude/skills/rspec-request-spec/references/projects_spec.rb |
skills/rspec-request-spec/references/rails_helper.rb | .claude/skills/rspec-request-spec/references/rails_helper.rb |
skills/rspec-request-spec/references/spec_helper.rb | .claude/skills/rspec-request-spec/references/spec_helper.rb |
skills/rspec-request-spec/references/rubocop.yml | .claude/skills/rspec-request-spec/references/rubocop.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Codex CLI reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/SKILL.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/SKILL.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_controller.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_controller.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/project.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/project.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_factory.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_factory.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_spec.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_spec.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rails_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rails_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/spec_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/spec_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rubocop.yml https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rubocop.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/rspec-request-spec/SKILL.md | .agents/skills/rspec-request-spec/SKILL.md |
skills/rspec-request-spec/references/projects_controller.rb | .agents/skills/rspec-request-spec/references/projects_controller.rb |
skills/rspec-request-spec/references/project.rb | .agents/skills/rspec-request-spec/references/project.rb |
skills/rspec-request-spec/references/projects_factory.rb | .agents/skills/rspec-request-spec/references/projects_factory.rb |
skills/rspec-request-spec/references/projects_spec.rb | .agents/skills/rspec-request-spec/references/projects_spec.rb |
skills/rspec-request-spec/references/rails_helper.rb | .agents/skills/rspec-request-spec/references/rails_helper.rb |
skills/rspec-request-spec/references/spec_helper.rb | .agents/skills/rspec-request-spec/references/spec_helper.rb |
skills/rspec-request-spec/references/rubocop.yml | .agents/skills/rspec-request-spec/references/rubocop.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Cursor reads AGENTS.md + .cursor/rules/*.mdc and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/SKILL.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/SKILL.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_controller.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_controller.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/project.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/project.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_factory.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_factory.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_spec.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_spec.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rails_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rails_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/spec_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/spec_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rubocop.yml https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rubocop.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/rspec-request-spec/SKILL.md | .agents/skills/rspec-request-spec/SKILL.md |
skills/rspec-request-spec/references/projects_controller.rb | .agents/skills/rspec-request-spec/references/projects_controller.rb |
skills/rspec-request-spec/references/project.rb | .agents/skills/rspec-request-spec/references/project.rb |
skills/rspec-request-spec/references/projects_factory.rb | .agents/skills/rspec-request-spec/references/projects_factory.rb |
skills/rspec-request-spec/references/projects_spec.rb | .agents/skills/rspec-request-spec/references/projects_spec.rb |
skills/rspec-request-spec/references/rails_helper.rb | .agents/skills/rspec-request-spec/references/rails_helper.rb |
skills/rspec-request-spec/references/spec_helper.rb | .agents/skills/rspec-request-spec/references/spec_helper.rb |
skills/rspec-request-spec/references/rubocop.yml | .agents/skills/rspec-request-spec/references/rubocop.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Gemini CLI reads GEMINI.md (imports AGENTS.md with @./AGENTS.md) and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/AGENTS.md curl -fsSL --create-dirs -o GEMINI.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/GEMINI.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/SKILL.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/SKILL.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_controller.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_controller.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/project.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/project.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_factory.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_factory.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_spec.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_spec.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rails_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rails_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/spec_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/spec_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rubocop.yml https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rubocop.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
GEMINI.md | GEMINI.md |
skills/rspec-request-spec/SKILL.md | .agents/skills/rspec-request-spec/SKILL.md |
skills/rspec-request-spec/references/projects_controller.rb | .agents/skills/rspec-request-spec/references/projects_controller.rb |
skills/rspec-request-spec/references/project.rb | .agents/skills/rspec-request-spec/references/project.rb |
skills/rspec-request-spec/references/projects_factory.rb | .agents/skills/rspec-request-spec/references/projects_factory.rb |
skills/rspec-request-spec/references/projects_spec.rb | .agents/skills/rspec-request-spec/references/projects_spec.rb |
skills/rspec-request-spec/references/rails_helper.rb | .agents/skills/rspec-request-spec/references/rails_helper.rb |
skills/rspec-request-spec/references/spec_helper.rb | .agents/skills/rspec-request-spec/references/spec_helper.rb |
skills/rspec-request-spec/references/rubocop.yml | .agents/skills/rspec-request-spec/references/rubocop.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Antigravity CLI reads AGENTS.md (read natively; GEMINI.md is also read) and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/SKILL.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/SKILL.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_controller.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_controller.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/project.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/project.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_factory.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_factory.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_spec.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_spec.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rails_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rails_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/spec_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/spec_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rubocop.yml https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rubocop.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/rspec-request-spec/SKILL.md | .agents/skills/rspec-request-spec/SKILL.md |
skills/rspec-request-spec/references/projects_controller.rb | .agents/skills/rspec-request-spec/references/projects_controller.rb |
skills/rspec-request-spec/references/project.rb | .agents/skills/rspec-request-spec/references/project.rb |
skills/rspec-request-spec/references/projects_factory.rb | .agents/skills/rspec-request-spec/references/projects_factory.rb |
skills/rspec-request-spec/references/projects_spec.rb | .agents/skills/rspec-request-spec/references/projects_spec.rb |
skills/rspec-request-spec/references/rails_helper.rb | .agents/skills/rspec-request-spec/references/rails_helper.rb |
skills/rspec-request-spec/references/spec_helper.rb | .agents/skills/rspec-request-spec/references/spec_helper.rb |
skills/rspec-request-spec/references/rubocop.yml | .agents/skills/rspec-request-spec/references/rubocop.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
GitHub Copilot reads AGENTS.md and skills from .agents/skills/.
curl -fsSL --create-dirs -o AGENTS.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/AGENTS.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/SKILL.md https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/SKILL.md curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_controller.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_controller.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/project.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/project.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_factory.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_factory.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/projects_spec.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/projects_spec.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rails_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rails_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/spec_helper.rb https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/spec_helper.rb curl -fsSL --create-dirs -o .agents/skills/rspec-request-spec/references/rubocop.yml https://loadout.jnw-it.com/raw/rails-rspec/1.0.0/skills/rspec-request-spec/references/rubocop.yml
| File | Goes to |
|---|---|
AGENTS.md | AGENTS.md |
skills/rspec-request-spec/SKILL.md | .agents/skills/rspec-request-spec/SKILL.md |
skills/rspec-request-spec/references/projects_controller.rb | .agents/skills/rspec-request-spec/references/projects_controller.rb |
skills/rspec-request-spec/references/project.rb | .agents/skills/rspec-request-spec/references/project.rb |
skills/rspec-request-spec/references/projects_factory.rb | .agents/skills/rspec-request-spec/references/projects_factory.rb |
skills/rspec-request-spec/references/projects_spec.rb | .agents/skills/rspec-request-spec/references/projects_spec.rb |
skills/rspec-request-spec/references/rails_helper.rb | .agents/skills/rspec-request-spec/references/rails_helper.rb |
skills/rspec-request-spec/references/spec_helper.rb | .agents/skills/rspec-request-spec/references/spec_helper.rb |
skills/rspec-request-spec/references/rubocop.yml | .agents/skills/rspec-request-spec/references/rubocop.yml |
Already have an AGENTS.md or CLAUDE.md? The commands above overwrite it — download the file instead and merge the sections you want.
Files
Rules AGENTS.md Rules for a Rails 8.1 app tested with RSpec request specs and FactoryBot. 26 lines
# AGENTS.md: Rails app tested with RSpec
A Rails 8.1 app whose tests are RSpec (`rspec-rails`) with FactoryBot. Check `Gemfile.lock` for exact versions before
using an API.
## Commands
- Tests: `bundle exec rspec` (random order). One file: `bundle exec rspec spec/requests/projects_spec.rb:42`.
- Lint: `bundle exec rubocop` (rubocop-rails-omakase plus rubocop-rspec and rubocop-rspec_rails).
- Migrations: `bin/rails db:migrate`, then commit `db/schema.rb`. The test database follows the schema
(`maintain_test_schema!`).
- Done means: the new specs fail without the change and pass with it, and the whole suite and rubocop are green.
## Rules
- Every controller action has request specs (`spec/requests/`): the happy path, the validation error (422,
`:unprocessable_content`), missing params (400), and another user's record (404). Use the `rspec-request-spec`
skill.
- Strong params with `params.expect(model: [...])`. Never permit ownership or role fields. Set them from the
authenticated user.
- Scope every lookup to the current user or account (`current_user.projects.find(...)`). An unscoped `Model.find`
in a controller is a bug.
- Model specs for validations and scopes use `build` or `build_stubbed`, and hit the database only when the
behaviour needs it.
- FactoryBot factories hold the minimum valid record. Variants go in traits. Unique fields use `sequence`.
- No controller specs, no `allow_any_instance_of`, no `sleep`, no real HTTP in specs.
- Do not change `.rspec`, `spec_helper.rb` or `rails_helper.rb` to make a failing spec pass. Adapter CLAUDE.md Imports AGENTS.md for Claude Code. 11 lines
# CLAUDE.md
@AGENTS.md
## Claude Code notes
- Skills from this loadout live in `.claude/skills/`: `rspec-request-spec`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From the Agent Loadout "Rails request specs with RSpec and FactoryBot" v1.0.0 — https://loadout.jnw-it.com/loadouts/rails-rspec/ --> Adapter GEMINI.md Imports AGENTS.md for Gemini CLI. 11 lines
# GEMINI.md
@./AGENTS.md
## Gemini CLI notes
- Skills from this loadout live in `.agents/skills/`: `rspec-request-spec`. Use them when their description matches the task.
- Follow AGENTS.md above; where this file and AGENTS.md disagree, AGENTS.md wins.
<!-- From the Agent Loadout "Rails request specs with RSpec and FactoryBot" v1.0.0 — https://loadout.jnw-it.com/loadouts/rails-rspec/ --> Skill skills/rspec-request-spec/SKILL.md What every endpoint spec covers, and how to write and run it. 50 lines
---
name: rspec-request-spec
description: Write RSpec request specs for a Rails JSON endpoint with FactoryBot, covering the happy path, validation errors, missing params and access scoping, then run rspec and rubocop-rspec. Use when adding or changing a controller action, route or API response in a Rails app tested with RSpec.
---
# Request specs for a Rails endpoint
The references hold a complete, passing set: `projects_controller.rb`, `project.rb`, `projects_factory.rb`
(goes in `spec/factories/projects.rb`), `projects_spec.rb` (goes in `spec/requests/`), `rails_helper.rb`,
`spec_helper.rb` and `rubocop.yml`.
## What every endpoint's spec covers
1. **Happy path**, with status and the body fields that matter: `response.parsed_body`, compared with `eq` or
`include`.
2. **Validation failure**: `have_http_status(:unprocessable_content)` and the error message for the field.
3. **Missing or malformed params**: `params.expect` raises, and Rails answers 400.
4. **Scoping**: another user's record returns 404, and the list never includes it. The spec catches an unscoped
`find`.
5. **Mass assignment**: a forbidden attribute in the body (`owner_id`, `admin`, `role`) is ignored.
6. **Side effects**: `expect { ... }.to change(Model, :count).by(n)` for creates and deletes.
## How to write them
- Request specs (`spec/requests/`), not controller specs. They go through routing, middleware and params parsing.
- Use `as: :json` for JSON bodies. With `wrap_parameters`, a flat JSON body is wrapped under the model key, so test a
missing key with a form post.
- Use `create` only when the database is needed, and `build` or `build_stubbed` in model and unit specs. Use a
factory `sequence` for unique fields and traits (`:archived`) for variants. Never use a fixed id.
- `let` for data an example uses. Create records inside the example when their order or count is the point.
- Follow arrange, act, assert with blank lines between, and one behaviour per example. Name examples for the
behaviour ("hides another owner's project behind a 404"), not the implementation.
- No `sleep`, no real network and no `allow_any_instance_of`. Freeze time with `travel_to` when a time is asserted.
## Run
```bash
bundle exec rspec spec/requests/projects_spec.rb
bundle exec rspec # the whole suite, random order
bundle exec rubocop app spec
```
Random order is on (`config.order = :random`). If a spec fails only in some orders, it leaks state. Fix the leak;
do not pin the seed.
## Done means
The new examples fail before the change and pass after it. The whole suite and rubocop (omakase, rubocop-rspec and
rubocop-rspec_rails) are green. Skill file skills/rspec-request-spec/references/projects_controller.rb Owner-scoped JSON controller with params.expect. 54 lines
# JSON API for projects, scoped to the current owner. In a real app the owner
# comes from authentication; here it is a header so the specs can show the scoping.
class ProjectsController < ApplicationController
before_action :require_owner
before_action :set_project, only: %i[show update destroy]
def index
render json: Project.owned_by(@owner_id).order(:name).limit(100)
end
def show
render json: @project
end
def create
project = Project.new(project_params.merge(owner_id: @owner_id))
if project.save
render json: project, status: :created, location: project
else
render json: { errors: project.errors }, status: :unprocessable_content
end
end
def update
if @project.update(project_params)
render json: @project
else
render json: { errors: @project.errors }, status: :unprocessable_content
end
end
def destroy
@project.destroy!
head :no_content
end
private
def require_owner
@owner_id = Integer(request.headers.fetch("X-Owner-Id"))
rescue KeyError, ArgumentError
head :unauthorized
end
# Another owner's project is a 404, not a 403: do not confirm that it exists.
def set_project
@project = Project.owned_by(@owner_id).find_by(id: params[:id])
head :not_found unless @project
end
def project_params
params.expect(project: %i[name status])
end
end Skill file skills/rspec-request-spec/references/project.rb Model with validations and an owner scope. 10 lines
class Project < ApplicationRecord
STATUSES = %w[active archived].freeze
validates :name, presence: true, length: { maximum: 80 }, uniqueness: { scope: :owner_id }
validates :status, inclusion: { in: STATUSES }
validates :owner_id, presence: true
scope :owned_by, ->(owner_id) { where(owner_id: owner_id) }
end Skill file skills/rspec-request-spec/references/projects_factory.rb FactoryBot factory with a sequence and a trait. 12 lines
Skill file skills/rspec-request-spec/references/projects_spec.rb Ten request specs covering every case. 98 lines
require "rails_helper"
RSpec.describe "Projects API" do
let(:owner_headers) { { "X-Owner-Id" => "1" } }
let(:json) { response.parsed_body }
describe "GET /projects" do
it "lists only the current owner's projects, by name" do
create(:project, name: "Beta")
create(:project, name: "Alpha")
create(:project, name: "Not mine", owner_id: 2)
get "/projects", headers: owner_headers
expect(response).to have_http_status(:ok)
expect(json.pluck("name")).to eq(%w[Alpha Beta])
end
it "rejects a request with no owner" do
get "/projects"
expect(response).to have_http_status(:unauthorized)
end
end
describe "GET /projects/:id" do
it "hides another owner's project behind a 404" do
other = create(:project, owner_id: 2)
get "/projects/#{other.id}", headers: owner_headers
expect(response).to have_http_status(:not_found)
end
end
describe "POST /projects" do
it "creates a project for the current owner" do
expect {
post "/projects", params: { project: { name: "Launch" } }, headers: owner_headers, as: :json
}.to change(Project, :count).by(1)
expect(response).to have_http_status(:created)
expect(json).to include("name" => "Launch", "status" => "active", "owner_id" => 1)
end
it "ignores an owner_id in the body" do
post "/projects", params: { project: { name: "Sneaky", owner_id: 2 } }, headers: owner_headers, as: :json
expect(Project.last.owner_id).to eq(1)
end
it "returns 422 with errors for a duplicate name" do
create(:project, name: "Launch")
post "/projects", params: { project: { name: "Launch" } }, headers: owner_headers, as: :json
expect(response).to have_http_status(:unprocessable_content)
expect(json.dig("errors", "name")).to include("has already been taken")
end
# JSON bodies are wrapped under "project" by wrap_parameters, so send a form post
# to reach params.expect with the key missing.
it "returns 400 when the project key is missing" do
post "/projects", params: { name: "Flat" }, headers: owner_headers
expect(response).to have_http_status(:bad_request)
end
end
describe "PATCH /projects/:id" do
it "archives a project" do
project = create(:project)
patch "/projects/#{project.id}", params: { project: { status: "archived" } }, headers: owner_headers, as: :json
expect(response).to have_http_status(:ok)
expect(project.reload.status).to eq("archived")
end
it "rejects an unknown status" do
project = create(:project)
patch "/projects/#{project.id}", params: { project: { status: "deleted" } }, headers: owner_headers, as: :json
expect(response).to have_http_status(:unprocessable_content)
end
end
describe "DELETE /projects/:id" do
it "deletes the owner's project" do
project = create(:project)
expect { delete "/projects/#{project.id}", headers: owner_headers }.to change(Project, :count).by(-1)
expect(response).to have_http_status(:no_content)
end
end
end Skill file skills/rspec-request-spec/references/rails_helper.rb rails_helper with FactoryBot and transactional fixtures. 19 lines
require "spec_helper"
ENV["RAILS_ENV"] ||= "test"
require_relative "../config/environment"
abort("The Rails environment is running in production mode!") if Rails.env.production?
require "rspec/rails"
# Load the schema into the test database. Apps with a persistent test database use
# ActiveRecord::Migration.maintain_test_schema! instead.
ActiveRecord::Schema.verbose = false
load Rails.root.join("db/schema.rb")
RSpec.configure do |config|
config.fixture_paths = [ Rails.root.join("spec/fixtures") ]
config.use_transactional_fixtures = true
config.infer_spec_type_from_file_location!
config.filter_rails_from_backtrace!
config.include FactoryBot::Syntax::Methods
end Skill file skills/rspec-request-spec/references/spec_helper.rb spec_helper with random order and verified doubles. 13 lines
RSpec.configure do |config|
config.expect_with :rspec do |expectations|
expectations.include_chain_clauses_in_custom_matcher_descriptions = true
end
config.mock_with :rspec do |mocks|
mocks.verify_partial_doubles = true
end
config.shared_context_metadata_behavior = :apply_to_host_groups
config.disable_monkey_patching!
config.order = :random
Kernel.srand config.seed
end Skill file skills/rspec-request-spec/references/rubocop.yml RuboCop config: omakase plus RSpec plugins. 18 lines
All files: source zip · Licence MIT · By Agent Loadout · First listed
Credits
Public work that inspired this loadout. The wording here is our own; follow the links for the originals.
Installing and testing
How do I install Rails request specs with RSpec and FactoryBot in Claude Code?
From your project root, put AGENTS.md, CLAUDE.md, skills/rspec-request-spec/SKILL.md at .claude/skills/rspec-request-spec/SKILL.md, skills/rspec-request-spec/references/projects_controller.rb at .claude/skills/rspec-request-spec/references/projects_controller.rb, skills/rspec-request-spec/references/project.rb at .claude/skills/rspec-request-spec/references/project.rb, skills/rspec-request-spec/references/projects_factory.rb at .claude/skills/rspec-request-spec/references/projects_factory.rb, skills/rspec-request-spec/references/projects_spec.rb at .claude/skills/rspec-request-spec/references/projects_spec.rb, skills/rspec-request-spec/references/rails_helper.rb at .claude/skills/rspec-request-spec/references/rails_helper.rb, skills/rspec-request-spec/references/spec_helper.rb at .claude/skills/rspec-request-spec/references/spec_helper.rb, skills/rspec-request-spec/references/rubocop.yml at .claude/skills/rspec-request-spec/references/rubocop.yml. The "Claude Code" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/rails-rspec/claude-code.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Rails request specs with RSpec and FactoryBot in Codex CLI?
From your project root, put AGENTS.md, skills/rspec-request-spec/SKILL.md at .agents/skills/rspec-request-spec/SKILL.md, skills/rspec-request-spec/references/projects_controller.rb at .agents/skills/rspec-request-spec/references/projects_controller.rb, skills/rspec-request-spec/references/project.rb at .agents/skills/rspec-request-spec/references/project.rb, skills/rspec-request-spec/references/projects_factory.rb at .agents/skills/rspec-request-spec/references/projects_factory.rb, skills/rspec-request-spec/references/projects_spec.rb at .agents/skills/rspec-request-spec/references/projects_spec.rb, skills/rspec-request-spec/references/rails_helper.rb at .agents/skills/rspec-request-spec/references/rails_helper.rb, skills/rspec-request-spec/references/spec_helper.rb at .agents/skills/rspec-request-spec/references/spec_helper.rb, skills/rspec-request-spec/references/rubocop.yml at .agents/skills/rspec-request-spec/references/rubocop.yml. The "Codex CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/rails-rspec/codex.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Rails request specs with RSpec and FactoryBot in Cursor?
From your project root, put AGENTS.md, skills/rspec-request-spec/SKILL.md at .agents/skills/rspec-request-spec/SKILL.md, skills/rspec-request-spec/references/projects_controller.rb at .agents/skills/rspec-request-spec/references/projects_controller.rb, skills/rspec-request-spec/references/project.rb at .agents/skills/rspec-request-spec/references/project.rb, skills/rspec-request-spec/references/projects_factory.rb at .agents/skills/rspec-request-spec/references/projects_factory.rb, skills/rspec-request-spec/references/projects_spec.rb at .agents/skills/rspec-request-spec/references/projects_spec.rb, skills/rspec-request-spec/references/rails_helper.rb at .agents/skills/rspec-request-spec/references/rails_helper.rb, skills/rspec-request-spec/references/spec_helper.rb at .agents/skills/rspec-request-spec/references/spec_helper.rb, skills/rspec-request-spec/references/rubocop.yml at .agents/skills/rspec-request-spec/references/rubocop.yml. The "Cursor" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/rails-rspec/cursor.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Rails request specs with RSpec and FactoryBot in Gemini CLI?
From your project root, put AGENTS.md, GEMINI.md, skills/rspec-request-spec/SKILL.md at .agents/skills/rspec-request-spec/SKILL.md, skills/rspec-request-spec/references/projects_controller.rb at .agents/skills/rspec-request-spec/references/projects_controller.rb, skills/rspec-request-spec/references/project.rb at .agents/skills/rspec-request-spec/references/project.rb, skills/rspec-request-spec/references/projects_factory.rb at .agents/skills/rspec-request-spec/references/projects_factory.rb, skills/rspec-request-spec/references/projects_spec.rb at .agents/skills/rspec-request-spec/references/projects_spec.rb, skills/rspec-request-spec/references/rails_helper.rb at .agents/skills/rspec-request-spec/references/rails_helper.rb, skills/rspec-request-spec/references/spec_helper.rb at .agents/skills/rspec-request-spec/references/spec_helper.rb, skills/rspec-request-spec/references/rubocop.yml at .agents/skills/rspec-request-spec/references/rubocop.yml. The "Gemini CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/rails-rspec/gemini-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Rails request specs with RSpec and FactoryBot in Antigravity CLI?
From your project root, put AGENTS.md, skills/rspec-request-spec/SKILL.md at .agents/skills/rspec-request-spec/SKILL.md, skills/rspec-request-spec/references/projects_controller.rb at .agents/skills/rspec-request-spec/references/projects_controller.rb, skills/rspec-request-spec/references/project.rb at .agents/skills/rspec-request-spec/references/project.rb, skills/rspec-request-spec/references/projects_factory.rb at .agents/skills/rspec-request-spec/references/projects_factory.rb, skills/rspec-request-spec/references/projects_spec.rb at .agents/skills/rspec-request-spec/references/projects_spec.rb, skills/rspec-request-spec/references/rails_helper.rb at .agents/skills/rspec-request-spec/references/rails_helper.rb, skills/rspec-request-spec/references/spec_helper.rb at .agents/skills/rspec-request-spec/references/spec_helper.rb, skills/rspec-request-spec/references/rubocop.yml at .agents/skills/rspec-request-spec/references/rubocop.yml. The "Antigravity CLI" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/rails-rspec/antigravity-cli.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
How do I install Rails request specs with RSpec and FactoryBot in GitHub Copilot?
From your project root, put AGENTS.md, skills/rspec-request-spec/SKILL.md at .agents/skills/rspec-request-spec/SKILL.md, skills/rspec-request-spec/references/projects_controller.rb at .agents/skills/rspec-request-spec/references/projects_controller.rb, skills/rspec-request-spec/references/project.rb at .agents/skills/rspec-request-spec/references/project.rb, skills/rspec-request-spec/references/projects_factory.rb at .agents/skills/rspec-request-spec/references/projects_factory.rb, skills/rspec-request-spec/references/projects_spec.rb at .agents/skills/rspec-request-spec/references/projects_spec.rb, skills/rspec-request-spec/references/rails_helper.rb at .agents/skills/rspec-request-spec/references/rails_helper.rb, skills/rspec-request-spec/references/spec_helper.rb at .agents/skills/rspec-request-spec/references/spec_helper.rb, skills/rspec-request-spec/references/rubocop.yml at .agents/skills/rspec-request-spec/references/rubocop.yml. The "GitHub Copilot" tab on this page has the curl commands, or download https://loadout.jnw-it.com/download/rails-rspec/copilot.zip, which is already laid out. Do not overwrite an existing AGENTS.md or CLAUDE.md; merge it.
Has Rails request specs with RSpec and FactoryBot been tested?
It passed the Level 1 automated install checks on 2026-10-17: the files parse, install to each agent's documented paths, and pass the safety scan. No AI agent has run it yet, so no agent pass or fail is claimed.
More for Claude Code, Codex, Cursor, Gemini CLI, Antigravity CLI and GitHub Copilot.