Skip to content

docs: tutorial accuracy sweep — chapters 1-6 - #2395

Merged
bpamiri merged 1 commit into
developfrom
peter/tutorial-doc-sweep
May 1, 2026
Merged

bpamiri merged 1 commit into
developfrom
peter/tutorial-doc-sweep

Conversation

@bpamiri

@bpamiri bpamiri commented May 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

Bundles 9 fixes from the 2026-04-30 fresh-VM tutorial bake into a single doc-sweep PR (one CI run, one review pass). Each chapter is a focused edit; nothing touches code or tests.

Findings addressed

# Chapter Fix
6 6b Name app/events/onapplicationstart.cfm explicitly as the strategy-registration site; explain why config/app.cfm is wrong
7 6 caution Recommend <meta name=\"csrf-token\"> scrape uniformly across all forms
8 6 caution Replace --data-urlencode recipe with a known-working raw --data form
10 2 Update Expected migration output to match current snapshot wording, with a "format may drift" note
11 4 Drop manual <label> wrappers; use helpers' label=\"...\" arg (no more nested <label> elements)
13 3 Phrase scaffold-resources behavior as conditional ("only if no resources line exists")
14 3 Update stale findByKey(params.key) claim — generator uses params.post like the tutorial
15 1 Drop non-existent Controller.cfc / Model.cfc from file tree; add real rewrite.config
16 1 Add "First start downloads ~74 MB" Aside before the boot step

Findings deliberately NOT in this PR

# Why
9 Verified t.timestamps() adds deletedAt (vendor/wheels/migrator/TableDefinition.cfc:372-376) and softDeleteProperty=\"deletedAt\" (vendor/wheels/events/init/orm.cfm:27). Chapter 5's callout matches current code; runner's snapshot-1660 observation predates the behavior.
12 Aligning docs to the generator's uglier emitted shape (force='false', id='true' triplet) is value-negative — either source can drift again.
17 Silent brew tap exits 0; adding a "no output expected" note is noise.
19 Chapter 6 Compare table markdown source is well-formed GFM. If rendered output is broken, it's a build/CSS issue (separate task).

Companion PRs

Test plan

  • Snapshot CI green (visual regression catches Astro layout drift)
  • Chapter 1 file tree matches reality on a fresh `wheels new`
  • Chapter 4 form renders with single `` per field (no nesting in DevTools)
  • Chapter 6b registration code in `app/events/onapplicationstart.cfm` activates after `wheels stop && wheels start`

🤖 Generated with Claude Code

Bundles 9 fixes uncovered by the 2026-04-30 fresh-VM tutorial bake.
Each chapter is a focused edit; the bundle ships one PR / one CI run
since they all live under web/sites/guides/.

Chapter 1 (Hello, Wheels):
- Drop `Controller.cfc` and `Model.cfc` from the "What got created"
  file tree — `wheels new` doesn't emit those base classes; the tree
  was aspirational. Add `rewrite.config` at the repo root, which IS
  emitted but wasn't listed. Finding #15.
- Add a "First start downloads ~74 MB" Aside before the welcome-page
  step so a 30-second wait isn't a surprise. Finding #16.

Chapter 2 (Your First Model):
- Replace the made-up `Migration complete.` Expected output with the
  shape the runner actually emits today (`Migrating from 0 up to <ts>`
  + `Created table posts`), and note that the wording can drift across
  snapshots so readers verify on the `Created table` line. Finding #10.
- Update the `t.timestamps()` description to mention all three columns
  it adds (`createdAt`, `updatedAt`, `deletedAt`) and link forward to
  Part 5's soft-delete callout. Previously claimed only two columns.

Chapter 3 (CRUD Scaffold):
- Rephrase the scaffold caution: it does NOT unconditionally append
  `.resources("posts")` to routes; it only appends when no resources
  line for the model exists. Chapter 2 already adds one, so the file
  is left alone. Finding #13.
- Update the "generator emits findByKey(params.key) everywhere" claim
  — actually it uses `params.post` (route model binding) on key-scoped
  actions; only positional helpers fall back to `findByKey`. Finding #14.

Chapter 4 (Validations + Turbo Frames):
- Drop the manual `<label>` wrappers around helpers in `_form.cfm` and
  use the helpers' own `label="..."` argument instead. The previous
  shape produced nested `<label>` elements — exactly what chapter 3's
  caution about object-bound helpers warned against. Finding #11.

Chapter 6 (Authentication, Part 6b):
- Name `app/events/onapplicationstart.cfm` explicitly as the place to
  register the session strategy, and explain why `config/app.cfm` is
  the wrong place (`Application.cfc` this-scope, DI container not yet
  initialized). The previous "or equivalent on-init block" hedge cost
  the runner real time. Finding #6.
- Recommend scraping `<meta name="csrf-token">` uniformly for curl
  smoke tests instead of mixing meta-tag-vs-form-input rules. Some
  forms (login raw inputs, comments, basecoat-rewritten views) don't
  always include the hidden input. Finding #7.
- Replace the `--data-urlencode` recipe with a known-working raw
  `--data` form that pre-encodes brackets and `@`. The previous "use
  the `=` separator" advice was incomplete — Lucee's form parser
  treats any bracketed key as a nested-struct path regardless of
  encoding form. Finding #8.

Findings deliberately not addressed in this PR:
- #9 (soft-delete callout) — verified against current code: `t.timestamps()`
  emits all three columns including `deletedAt`, and `softDeleteProperty`
  defaults to `deletedAt`. Chapter 5's callout matches reality. The
  runner's snapshot-1660 observation likely predates the current behavior.
- #12 (cosmetic migration drift) — aligning the docs to the generator's
  uglier emitted shape is value-negative; either source can drift again
  in a future release.
- #17 (silent `brew tap`) — `exit 0` with no output is brew convention;
  adding a "no output expected" note is noise.
- #19 (chapter 6 Compare table renders as wall) — markdown source is
  well-formed GFM; if the rendered output is broken it's a build/CSS
  issue not a source issue. Investigate in a follow-up if reproducible.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@bpamiri
bpamiri merged commit 83dbdc9 into develop May 1, 2026
10 checks passed
@bpamiri
bpamiri deleted the peter/tutorial-doc-sweep branch May 1, 2026 12:04
bpamiri added a commit that referenced this pull request May 1, 2026
…eadless brew install (#2398)

Three follow-ups from the 2026-05-01 fresh-VM tutorial run that survived the
recent doc sweeps (#2395, #2396).

F8 — chapter 6's "known-working signup smoke test" regex assumed
`name="csrf-token" content="..."` attribute order, but Wheels'
`vendor/wheels/view/miscellaneous.cfc:404` `$tag` helper sorts attributes
alphabetically for deterministic test output, so the actual emit is
`content="..." name="csrf-token"`. The old regex returned an empty TOKEN
and POST silently failed with `Wheels.InvalidAuthenticityToken`. New regex
matches the actual order, plus an explanatory note so future readers know
to check attribute order if the scrape ever returns empty.

F7 — chapter 2 said "feel free to keep the generator's timestamp instead"
of renaming to `20260419120000`. That sounds permissive but is actually a
footgun: chapters 5/6 hardcode timestamps `20260419130000`,
`20260419140000`, `20260419150000` for comments / users / add_user_to_posts.
If the posts migration sorts after them (e.g. May 2026 from a current-day
generator), the dev DB still works because migrations apply incrementally
as files are added — but the test DB in chapter 7 runs them all from
scratch in timestamp order, hits `add_user_to_posts` before `posts` exists,
and bails. Now the rename is mandatory with a callout explaining the
dependency chain.

F1 — the install page only documented the interactive Homebrew installer.
That installer's `sudo -n true` precheck always fails in a non-interactive
context (CI, agents, packer, provisioning scripts), even with
`NONINTERACTIVE=1` set. Added a "Headless / non-interactive installs"
caveat with three concrete options (user-prefix `git clone`, pre-baked
image, Ansible's homebrew module) and a recommendation for the common
agent/CI VM case.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
bpamiri added a commit that referenced this pull request May 2, 2026
…F11, F13, F18) (#2411)

Bundles seven small fixes from the 2026-05-01 fresh-VM tutorial run that
weren't urgent enough to ship as separate PRs. Each chapter is a focused
edit; the bundle ships one PR / one CI run.

start-here/installing (F4 partial):
  - Hoist `brew install openjdk@21` from inline prose into a code block
    inside the Java prereq Aside. The Aside placement is fine (Java is a
    prerequisite, not a Wheels-specific step), but a copy-paste-friendly
    code block makes it scannable for users skimming for commands. Did
    NOT promote Java to step 1 of the macOS tab — that would push the
    Wheels-specific steps to 2/3/4 for marginal benefit.

02-first-model (F6, F11 setup):
  - Tweak the "intentionally slim" lead-in so users learn upfront that
    the generator ships with `validatesPresenceOf` rules they'll drop
    here and revisit in Part 4. The earlier wording suggested the
    generator omits validations entirely, which then read as a
    contradiction when the next paragraph says to remove them.
  - Add a tip introducing `wheels generate migration` (and the `g`
    alias) right where users see the first auto-generated migration.
    Chapter 5 mentions the shortcut parenthetically; this gives readers
    a forward-link to it instead of seeing it for the first time inline.

03-crud-scaffold (F7):
  - Fix the inaccurate "same shape as this tutorial's" claim about the
    scaffold's emitted controller. The scaffold uses a `findRecord`
    filter + `variables.record` reference; this tutorial uses route
    model binding's `params.post`. Both are valid; the chapter now says
    so explicitly instead of pretending they're identical.

05-comments-streams (F10, F11 follow-through):
  - Restore `allowBlank=true` on the `validatesLengthOf(property="title")`
    line. Chapter 4 explained at length why `allowBlank=true` is needed
    to avoid double-firing alongside `validatesPresenceOf`; chapter 5
    silently dropped it from the same Post.cfc snippet, regressing
    chapter 4's behavior on a verbatim paste.
  - Update the `wheels g migration` parenthetical to reference its
    introduction in chapter 2 instead of presenting it as new.

06-authentication (F13):
  - Add a working `buttonTo` snippet for logout in the "Test 6a manually"
    section. The chapter referenced `/logout` abstractly but never
    showed a known-good way to hit it from a view (DELETE routes need a
    form, not a link). Now there's a one-line `buttonTo` that uses the
    named route + method=delete, with a short note that the same shape
    is what chapter 3's Delete buttons use.

cli/lucli/Module.cfc + 07-testing-deploying (F18):
  - `wheels browser setup` now ends with both invocation forms named
    explicitly: `wheels test --filter=browser` (canonical, matches the
    docs) and `wheels browser test` (alias). Previously the CLI
    suggested only the alias, while the docs used only the canonical
    form, so users saw two different commands without knowing they were
    equivalent. Chapter 7 already uses the canonical form; no chapter
    edit needed.

Findings deliberately NOT addressed:
  - F8 (params.post works without binding=true): Verified against
    Dispatch.cfc:469-475 — binding is OFF by default at both
    per-resource and global level. The chapter's claim is correct;
    the user's report observation likely came from an environment
    where the Posts.cfc had already been replaced with the chapter's
    snippet, OR an environmental quirk unrelated to scaffold output.
  - F5 (generated migration cosmetic differences): Same triage as PR
    #2395's deliberate skip of the same finding under its prior number
    — aligning docs to the generator's emitted shape (`force='false'`
    triplet) is value-negative since either source can drift again.

F4 partial, F6, F7, F10, F11, F13, F18 from the 2026-05-01 fresh-VM
tutorial run.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant