rails-core
Skill2 starsChanged 8 days agoMITView on GitHub
Use FIRST on any Ruby on Rails work — the project owner's hard-won Rails gotchas and non-negotiable rules (fixtures, migrations, Stimulus LSP, validation, gems, test suite). Read before writing or changing Rails code.
In this repository24 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- rails-activestorageSkill
- rails-apiSkill
- rails-auditSkill
- rails-clean-test-outputSkill
- rails-controllersSkill
- rails-database-performanceSkill
- rails-i18nSkill
- rails-jobsSkill
- rails-loggingSkill
- rails-mailersSkill
- rails-migrationsSkill
- rails-modelsSkill
- rails-multi-tenancySkill
- rails-performanceSkill
- rails-philosophySkill
- rails-project-setupSkill
- rails-securitySkill
- rails-stimulusSkill
- rails-styleSkill
- rails-testingSkill
- rails-turboSkill
- rails-upgradeSkill
- rails-viewcomponentsSkill
The file
We split this skill into the rules it gives an agent
6 rules. About 0 are common, 6 are distinctive, and 0 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈6
Distinctive · estimate
This author's own choices. Worth a look.
0
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 13
Do not modify existing fixtures or add new relationships to them — that silently breaks other tests.
- Distinctive: line 16
After you add or rename a Stimulus controller, the Stimulus LSP does not refresh until a restart, so it may report a controller as "not a …
- Distinctive: line 19
Always prefer server-side validation with Hotwire and Turbo over client-side JavaScript validation.
- Distinctive: line 22
When a newly-added gem or package is involved, read its actual API/docs rather than relying on memory — APIs drift between versions.
- Distinctive: line 26
Add the column as nullable.
- Distinctive: line 28
Add the constraint (NOT NULL / unique) in a follow-up migration.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Rails Core Gotchas
The entry-point skill for Rails work in this environment. These are personal, hard-won rules that override generic Rails habits. Read this first, then pull in the specific rails-toolkit:rails-* skill for the area you're touching.
The Rules
1. Fixtures — never mutate, only add
Do not modify existing fixtures or add new relationships to them — that silently breaks other tests. If no existing fixture fits what you're testing, create a new one. See [[rails-testing]] for fixture patterns and deterministic UUIDs.
2. Stimulus LSP is stale until restart
After you add or rename a Stimulus controller, the Stimulus LSP does not refresh until a restart, so it may report a controller as "not a valid Stimulus controller" even though it exists. Ignore these false errors — don't chase them. See [[rails-stimulus]].
3. Validate on the server, not in JavaScript
Always prefer server-side validation with Hotwire and Turbo over client-side JavaScript validation. Let the model be the source of truth and re-render with Turbo. See [[rails-turbo]] and [[rails-models]].
4. Read the docs for new gems
When a newly-added gem or package is involved, read its actual API/docs rather than relying on memory — APIs drift between versions.
5. Migrations on populated tables are multi-step
For tables that already have rows, never add a non-nullable or unique column in a single migration. Use the multi-step pattern:
- Add the column as nullable.
- Backfill the data.
- Add the constraint (NOT NULL / unique) in a follow-up migration.
Exception: on PostgreSQL 11+, a NOT NULL column with a constant (non-volatile)
default: is safe in one migration — it doesn't rewrite the table. A volatile default, or a
unique column, still takes the steps above.
See [[rails-migrations]] for the full zero-downtime toolkit (strong_migrations, concurrent indexes, renames, backfills, column removal). See [[rails-models]] for transactions and data-integrity patterns. For the legacy integer-primary-key foreign-key gotcha when adding a child table, see [[rails-models]].
6. Multi-database apps: db:rollback needs the namespaced task
In an app configured with multiple databases (e.g. primary / queue / cache), a bare
bin/rails db:rollback aborts with "you must run the namespaced task". Target the database
explicitly: bin/rails db:rollback:primary STEP=n (and likewise for the other migration tasks
that operate per-database). See [[rails-models]].
7. Restart the dev server after a migration — it caches the schema at boot
A running dev server reads the DB schema once at boot. After a migration that adds
columns — especially an enum-backed column — the already-running process keeps 500ing
(Undeclared attribute type for enum ... must be backed by a database column) until it is
restarted. This is not a code bug; restart after migrating.
How you restart depends on the server: Puma hot-restarts via SIGUSR2, not
touch tmp/restart.txt (that's a Passenger-only trick and does nothing under Puma). Sending
SIGUSR2 makes Puma re-exec in place keeping the same PID, so a foreman/bin/dev dev group
doesn't see a child die and tear everything down (Vite and friends keep running). Everyday app
code (models, controllers, views) auto-reloads and needs no restart — only boot-time state
does (initializers, config/*, Gemfile, env vars, new/enum-backed columns).
A drop-in bin/restart-web wrapper (adjust the pgrep pattern to your app's Puma process tag):
#!/usr/bin/env sh
# Hot-restart the running Puma dev server in place (SIGUSR2).
#
# Puma re-execs itself on SIGUSR2, keeping the same PID, so foreman does not
# see a child die and tear down the whole dev group — Vite keeps running.
# Use this to reload boot-time state: config/initializers, config/*, Gemfile,
# env vars, and new/enum-backed DB columns. Everyday app code (models,
# controllers, views) is auto-reloaded and needs no restart.
#
# Note: this is NOT `touch tmp/restart.txt` — that only works with Passenger.
set -e
pid=$(pgrep -f 'puma .* \[YourApp\]' || true) # match your app's Puma process tag
if [ -z "$pid" ]; then
echo "No running Puma dev server found (is bin/dev running?)." >&2
exit 1
fi
echo "Hot-restarting Puma (pid $pid) via SIGUSR2..."
kill -USR2 "$pid"
echo "Done. Watch the bin/dev terminal for the restart log."8. Run the FULL suite after factory/fixture changes
Factory and fixture changes have cascading effects across the entire suite. After any such change (or when optimizing/refactoring factories), run the full test suite — not just the files you touched. Use PARALLEL_WORKERS=1 when you need readable, debuggable output. See [[rails-testing]].
When to reach for the other skills
- Architecture / "should I add a service object?" → [[rails-philosophy]]
- Code aesthetics, method ordering, REST routing, enforcing style on AI output with a RuboCop hook → [[rails-style]]
- Models, validations, callbacks, scopes → [[rails-models]]
- Thin controllers, concerns → [[rails-controllers]]
- Background jobs (Solid Queue) → [[rails-jobs]]
- Turbo Frames/Streams/broadcasts → [[rails-turbo]]
- Stimulus controllers → [[rails-stimulus]]
- Caching, ETags, N+1 → [[rails-performance]]
- Schema/index/query audits → [[rails-database-performance]]
- Writing or reviewing migrations, especially on tables with production data (zero-downtime patterns, backfills, renames) → [[rails-migrations]]
- Auditing / reviewing an existing or inherited app, tech-debt health-check → [[rails-audit]]
- Auth & authorization → [[rails-security]]
- URL-based tenancy, Current → [[rails-multi-tenancy]]
- File uploads, variants → [[rails-activestorage]]
- Extracting ViewComponents → [[rails-viewcomponents]]
- New Rails 8 app setup → [[rails-project-setup]]
- Writing tests → [[rails-testing]]
- Noisy test output (warnings, stray
puts/p, deprecations) in RSpec or Minitest → [[rails-clean-test-output]] - JSON APIs or an API namespace (versioning, serialization, CORS, pagination, JSON errors) → [[rails-api]]
- Internationalization: locale files, pluralization, formatting, missing/unused keys → [[rails-i18n]]
- Logging and observability: structured request logs, tagged logging, parameter filtering, error tracking, health checks → [[rails-logging]]
- ActionMailer mailers: layouts, previews, delivery, attachments, bounces → [[rails-mailers]]
- Upgrading Rails versions (2.3 → 8.1, breaking changes, deprecations, multi-hop plans) → [[rails-upgrade]] — guard rules, then the vendored OmbuLabs/FastRuby.io upgrade skill. Reach for it whenever an upgrade is on the table; do not hand-roll the version bump.
Upgrade in place and skip rails-upgrade's dual-boot step unless the user asks for
dual-booting. The
dual-boot,rails-load-defaultsandupgrade-cleanupskills it delegates to aren't installed here, so do any such step inline rather than waiting on them.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

