skip to content

When adopting Standard Ruby on an existing codebase, what does standardrb --generate-todo produce, and how do standard:disable comments work?

level: middleimportance: should knowfreq 30%

answer

  1. run standardrb --fix first
  2. .standard_todo.yml lists file to cops
  3. read automatically, with a warning
  4. standard:disable, enable and todo
  5. rubocop: prefix also accepted

basics

~20 s

standardrb --generate-todo writes .standard_todo.yml, mapping each file that has offenses to the cops it violates; Standard then ignores those, warns about them, and still checks everything else. # standard:disable Cop comments silence specific lines like RuboCop's own directives.

solid answer

~40 s

The adoption path is: `standardrb --fix` to clear what can be corrected safely, then `standardrb --generate-todo`. That writes **`.standard_todo.yml`**, an `ignore:` list where each entry maps a file to the cops it currently violates. Standard loads the file automatically on later runs, so those file-and-cop pairs are skipped while every other rule, and every new file, is still checked. Each run prints a warning listing the files still being ignored, and once none remain it congratulates you and suggests deleting the file. For single places, Standard reads directive comments: `# standard:disable Style/GlobalVars` at the end of a line, or `# standard:disable` ... `# standard:enable` around a block, plus `standard:todo`; the `rubocop:` prefix works too. Only `disable`, `enable` and `todo` are recognised under Standard, and `all` silences every cop.

code

yaml · 10 lines
yaml
# .standard_todo.yml (generated)
# Auto generated files with errors to ignore.
# Remove from this list as you refactor files.
---
ignore:
- app/models/invoice.rb:
  - Style/GlobalVars
  - Lint/UselessAssignment
- lib/tasks/import.rake:
  - Style/StringLiterals

go deeper

for a junior

Recall the order: standardrb --fix first, then --generate-todo, and the end-of-line standard:disable comment.

for a middle

Explain that the todo file maps files to specific cops, is loaded automatically with a warning, and still fails new offenses and new files.

for a senior

Plan the migration: safe fixes, a generated todo, directives only for permanent exceptions, and a steady cadence of removing todo entries.

for a principal

Track the todo file as migration debt with an owner, and decide when a stalled list means Standard is the wrong fit for the codebase.

## The problem Switching an existing codebase to Standard usually reports thousands of offenses on the first run. Standard's answer is to fix what can be fixed mechanically, record the rest, and keep the gate strict for everything else. ## Step 1: fix what is safe `standardrb --fix` applies every safe correction. Most formatting offenses disappear here, which keeps the todo list short and meaningful. ## Step 2: `--generate-todo` `standardrb --generate-todo` runs the full check and writes **`.standard_todo.yml`** in the current directory: - the file starts with the comments `Auto generated files with errors to ignore.` and `Remove from this list as you refactor files.`; - its single key is `ignore:`, with one entry per file that has offenses; - each entry maps the file path to the **list of cops** it currently violates, so only those cops are skipped for that file. When generating, Standard deliberately does **not** load an existing todo file, so the new one lists every current offense rather than inheriting old entries. ## Step 3: living with the todo file On every later run Standard looks for `.standard_todo.yml` the same way it finds `.standard.yml`, upward from the working directory, and merges its `ignore` entries with the project's own. The effects: 1. **Existing offenses** in listed files, for the listed cops, are not reported. 2. **New offenses** of other cops in those files, and **any** offense in unlisted or new files, fail the run as usual. 3. Every run prints `WARNING: this project is being migrated to standard gradually via .standard_todo.yml and is ignoring these files:` with the list. 4. When the list is empty and no offenses remain, Standard prints a congratulation and suggests deleting the file. To pay the debt down, delete an entry, run `standardrb --fix`, fix the rest by hand, and commit. The `--todo FILE` option points Standard at a differently named todo file. ## Directive comments For an individual exception Standard reads the same kind of comments RuboCop does, with its own prefix: | Comment | Scope | |---|---| | `code # standard:disable Style/GlobalVars` | that line | | `# standard:disable Cop` ... `# standard:enable Cop` | the lines between | | `# standard:disable all` | every cop, on that line or region | | `# standard:todo Cop` | same as disable, marking debt | Standard patches RuboCop's directive parser to accept either `standard:` or `rubocop:` as the prefix, and only the three modes `disable`, `enable` and `todo`. Directive forms that newer RuboCop versions add, such as `disable-next`, are not recognised under Standard; Standard 1.56 also runs RuboCop 1.88, which predates them. ## A migration timeline 1. **Day one:** add the gem, run `standardrb --fix`, review and commit the safe fixes on their own. 2. **Same day:** run `standardrb --generate-todo`, commit `.standard_todo.yml`, and add `standardrb` to CI. From now on new code is held to every rule. 3. **Each week:** pick a few entries, delete them, fix those files (starting with `standardrb --fix`), and commit. 4. **When the list is empty:** Standard prints its congratulation; delete the file. Regenerating the todo file halfway through is possible, but it also records any offenses introduced since, so it should be a reviewed decision rather than a routine step. ## Choosing between them - **A whole backlog:** `--generate-todo`, then shrink the file over time. - **A deliberate, permanent exception in one place:** a `standard:disable` comment next to it, ideally with a short explanation. - **Generated or vendored code:** an `ignore` entry in `.standard.yml`, not the todo file, since it is not debt.

  • After generating .standard_todo.yml, a developer adds a new file with offenses. Does the build still fail?
    Yes. The todo file lists only the files, and for each only the cops, that had offenses when it was generated. A new file is not in the list, so every rule applies to it and its offenses fail the run. That is what lets a team adopt Standard without letting new code slip.
  • Why does standardrb --generate-todo not read the existing .standard_todo.yml?
    If it did, files already ignored would produce no offenses and would drop out of the regenerated list, so the new file would lose entries that are still needed. Skipping the old file makes generation list every current offense.

saying these in an interview costs you the question

  • --generate-todo fixes the offenses it lists.
  • Files in .standard_todo.yml are skipped by every cop, so new problems there go unnoticed.
  • Standard only recognises standard: directives, not rubocop: ones.
  • # standard:disable-next works under Standard 1.56.
  • The todo file must be referenced from .standard.yml before Standard reads it.