This directory contains a Ruby on Rails application. The instructions below all pertain to operations within this directory.
Ignore if you are not codex:
- All
bin/railscommands (and alsobin/rspec) should be run outside the sandbox. - All
bin/railscommands (inculdingbin/rspec) need to be prefixed withrbenv exec ruby.
- Rails app lives in
app/(controllers,models,views,services,jobs) with helpers inapp/helpersand Stimulus controllers inapp/javascript. - Shared POROs belong in
services/orlib/to keep controllers thin. - Tests are in
spec/(RSpec) andspec/javascript(Vitest); assets/builds sit inapp/assetsandapp/assets/builds. - Configuration lives in
config/, migrations indb/, and dev scripts inbin/andMakefile.
When developing on the Rails app, ensure you are always in the app subdirectory.
- Initialize: Follow the setup instructions (in the top-level README.md).
- Run app: Run
bin/rails serverfor the Rails server, or runbin/devto start all services necessary for local development. - Database commands: Run
bin/rails db:migrateto update the schema after creating a migration. - Run tests: Run
bin/rspecto run all tests. Pass filenames as arguments tobin/rspecto run only those tests. - Frontend/unit JS uses Vitest (
npm test) withhappy-dom/jsdom; mock network calls and keep components small.
- Ruby: RuboCop (rails-omakase + project overrides) enforces 2-space indents and Rails defaults. Run
make lintor./bin/rubocopbefore pushing. - Controllers: Prefer using
before_actioncallbacks for guard redirects instead of inline redirects inside actions. - JS/TS: Prettier (
tabWidth: 2, double quotes, no semicolons,printWidth: 100) vianpm run formatornpm run format:precommit. - Tests follow
_spec.rb/.test.ts; favor descriptive, imperative example names. Use snake_case for Ruby, camelCase for JS, kebab-case for Stimulus files. Preferletfor object setup,beforeblocks for shared session/context setup, andTimecopfor time freezing in controller specs (usingaroundblocks). - ERB/HTML: Put each HTML tag on its own line (opening tag, contents, closing tag) for readability and avoid
usa-proseclasses unless required by design. - Layout and spacing: Prefer USWDS / project utility classes in ERB for one-off layout and spacing (e.g.,
display-flex,flex-justify-center,margin-top-*,padding-*). Add SCSS when the same rules repeat across elements, when a named class carries semantic meaning (states, variants), or when styling is too complex or token-heavy to express cleanly as utilities.
- Add coverage for new endpoints, logic, and service objects; exercise eligibility and payroll edge cases.
- Prefer writing controller tests over request specs.
- For Rails view and ViewComponent specs, prefer Capybara matchers against
user-visible output (
have_text,have_selector,have_no_text). In ViewComponent specs, preferrendered = render_inline(...)and assert against that node. Userendered.css(...)or Nokogiri only when the assertion is about DOM structure or attributes, such asdata-labelor specific table cell positions, rather than visible text. - Avoid brittle structural selectors, such as deep
nth-childchains or:last-child, when a user-visible assertion can verify the same behavior. - Make sure to update our Capybara/Selenium end-to-end tests. They are in
spec/e2e. When running these tests, you have to prefix the command withE2E_RUN_TESTS=1. - In end-to-end specs, use
verify_pageafter each navigation to assert page headers/titles as you move through flows. - For faster local iteration, create an
.rspec-local(gitignored) with--fail-fast=3or similar overrides. - Profile factory and SQL cost with
FACTORY_PROF=flamegraph bin/rspec spec/some_dirorEVENT_PROF=sql.active_record bin/rspec spec/some_dir(test-prof).
- We use standard Rails i18n with a few process customizations.
- Put all strings in the
config/locales/en.yml. - When adding a new English string, add it to only the English file (
en.yml). Do not add translations to thees.ymlfile unless asked. - Prefer relative I18n keys in views and partials (for example
t(".title")) instead of repeated absolute key paths.
- Follow history: brief sentence-case subject with issue/PR reference when available (e.g.,
Add timeout page title). - If you're following a ticket (e.g. "FFS-1234"), then put it as a prefix (e.g.,
FFS-1234: Add timeout page title). - Commits can include a brief (2-3 sentence) summary of the solution/context.
- Call out migrations, feature flags, and operational impacts (queues, env vars); link to Jira/GitHub issues and note rollout/monitoring.
- Before committing, run the
pre-commitcommand (outside the sandbox) to run all linters. If the command fails, it probably fixed a couple styling errors, so add those files and re-run it.
- Never commit secrets; Override values in
.envto.env.localwhen modifying environment variables. - Run Rails commands locally by default; do not use Docker unless explicitly instructed.