rails

Handle 401 responses in Turbo by forcing a full redirect

When a session expires, Turbo can end up swapping a login page into a frame, which is confusing. A practical fix is to detect 401 responses on the client and trigger a full-page visit (Turbo.visit) to the login URL. This keeps the app consistent and a

Fast Fail for Missing Indexes (EXPLAIN sanity check)

When adding a new query path, run EXPLAIN in CI or a smoke task to catch missing indexes before production. You don’t need full query plans everywhere—just guard the hot paths.

Build Turbo Stream responses in the controller (TagBuilder)

Most of the time I prefer *.turbo_stream.erb templates, but for small one-off responses it can be nice to generate streams directly in the controller using Turbo::Streams::TagBuilder. This keeps the logic close to the action and avoids creating a temp

Rails N+1 query detection with Bullet

N+1 queries are the most common Rails performance problem—loading associations in loops causes exponential database queries. The Bullet gem detects N+1s in development and suggests fixes. It monitors queries and alerts when you should use includes, pr

Turbo Streams: inline “saved” indicator that updates on autosave

Users trust autosave when they can see it. I render a small #save_state region (“Saved just now”, “Saving…”, “Offline”) and update it via Turbo Streams. The autosave endpoint returns a stream that replaces the indicator, and optionally updates a hidde

Preview Active Storage uploads after attach using Turbo Streams

For image uploads, I like immediate previews. With Active Storage, you can render the preview server-side once the blob is attached, and use Turbo Streams to update the preview area. The form submits to an endpoint that attaches the blob and returns a

Form objects for complex form handling

Form objects encapsulate form logic separate from models. I use form objects for multi-model forms, complex validations, or forms not directly mapping to models. Form objects include ActiveModel modules for validations and callbacks. They handle param

Inline markdown preview using Turbo Frames

A markdown preview doesn’t need a client markdown parser. I render the preview server-side (same pipeline used in production), and load it into a Turbo Frame. The editor form includes a frame called preview, and a “Preview” button submits the form to

Autosave drafts with Stimulus + Turbo (lightweight)

For long text entry, autosave is a huge quality-of-life improvement. I implement it with a Stimulus controller that debounces input and submits the form to a drafts endpoint in the background. The response is a turbo stream that updates a “Saved at …”

Add/remove nested fields with Stimulus (no cocoon)

Nested fields are a common Rails pain point, and the old solution was heavy JS gems. With Stimulus, I keep it minimal: render a hidden <template> containing the fields with a placeholder index, then on “Add” clone it and swap the placeholder for

Tailwind CSS with Rails asset pipeline

Tailwind CSS provides utility-first styling that pairs perfectly with Rails component-driven architecture. I configure Tailwind to scan templates for class names and generate only the CSS being used. The standalone CLI runs during development with --w

Turbo Frames modal: load, submit, then close via stream

A modal is just a frame boundary. Load the modal content into a dedicated frame, then on submit broadcast/stream a close action plus a list update. You get “SPA modal UX” without a frontend router.