rails

Keep Controllers Thin: Use Command Objects

Command objects (a.k.a. “actions”) make controllers boring. They’re easy to test, easy to instrument, and they produce a stable API for the rest of your app. This is the kind of structure that makes large Rails apps maintainable.

Guard Rails for Dangerous Admin Actions

Admin actions are production sharp edges. Require a typed confirmation string, log actor + request_id, and run the dangerous work in a background job. This reduces accidental incidents.

Morphing page refreshes with turbo_refreshes_with

When a page has lots of dynamic pieces but I still want “just refresh it” semantics, I use Turbo’s morphing refreshes. With turbo_refreshes_with method: :morph, Turbo updates the DOM by morphing rather than doing a full replace, which tends to preserv

Turbo Frames: Inline edit that swaps form <-> row

Inline editing works best when the frame boundary is small and stable (one row). Render the display state inside a frame, then link to edit inside the same frame. Submit swaps it back. This keeps controllers simple and UI snappy.

Broadcast job progress updates to a Turbo Frame

Long-running jobs are where Hotwire can feel magical: start an export, then watch progress update live. I give each job a “progress” model, render it in a turbo_frame_tag, and broadcast replacements as the job advances. The job updates percent and sta

ActionCable channel that streams Turbo updates safely

Even with model broadcasts, it’s useful to know how streams map to ActionCable channels. Turbo::StreamsChannel is essentially a channel that streams from a signed stream name. When I need custom behavior, I still follow the same scoping rules: identif

API Error Handling with Problem Details (RFC7807-ish)

APIs are easier to operate when errors are structured and consistent. Wrap errors into a problem-details style response with a stable type and request_id so support can quickly trace issues.

Safer HTML Sanitization Pipeline

User content needs defense in depth: markdown rendering + sanitization + link attribute hygiene. Keep the allowed tags list explicit and test it. Don’t trust upstream renderers to be safe by default.

ETag + last_modified for expensive Turbo Frame endpoints

Turbo Frames can trigger lots of small requests, so caching matters. For expensive frame endpoints (like an activity panel), I use stale? with an ETag that includes a cache key and the latest update timestamp. If the content hasn’t changed, Rails retu

Broadcasts refreshes for complex pages (less target wiring)

When a page has many small targets, wiring dozens of Turbo Stream operations can get noisy. Rails’ broadcasts_refreshes (Rails 7.1+) lets you take a pragmatic approach: broadcast a refresh, and Turbo morphs the page. It’s not always the right choice (

Read Replica Routing for GET-Heavy Endpoints

For apps with replicas, route read-only code paths to reading role and enforce prevent_writes. This is a strong reliability move: accidental writes on replicas become exceptions instead of silent data loss.

Safer Time-Based Deletes with “mark then sweep”

Direct deletes can be risky and slow. Mark records for deletion, then sweep in batches in a maintenance job. This gives you observability and a rollback window.