erb css ruby 100 lines · 4 tabs

Post-Redirect-Get in Sinatra with Sinatra::Flash and a redirect_to Helper

Shared by codesnips Sep 2026
4 tabs
<h1>New Article</h1>

<form action="/articles" method="post">
  <div>
    <label for="title">Title</label>
    <input id="title" type="text" name="article[title]"
           value="<%= @article.title %>">
  </div>

  <div>
    <label for="body">Body</label>
    <textarea id="body" name="article[body]"><%= @article.body %></textarea>
  </div>

  <button type="submit">Publish</button>
</form>
4 files · erb, css, ruby Explain with highlit

This snippet demonstrates the Post-Redirect-Get (PRG) pattern in a classic Sinatra application, using sinatra-flash to carry one-shot messages across the redirect. PRG solves a well-known problem: if a browser renders HTML directly in the response to a POST, then a refresh or back-button re-submits the form, potentially creating duplicate records. The fix is to respond to a successful POST with a 303 See Other (or 302) redirect to a GET route, so the reloadable URL is idempotent.

The app.rb tab wires up the moving parts. enable :sessions is required because flash storage lives in the session, and register Sinatra::Flash adds the flash helper. The custom redirect_to helper centralizes the redirect convention: it accepts a path, an optional flash type and message, sets flash[type] only when a message is present, and issues a redirect using 303 by default so the follow-up request is always a GET. Keeping this in one helper means every controller action redirects consistently instead of hand-rolling flash[:success] = ...; redirect ... everywhere.

The POST /articles route shows the pattern end to end. It builds an Article, and on save it calls redirect_to '/articles', :success, '...'; on failure it re-renders the form inline with flash.now[:error], which is the important distinction — flash.now is visible only in the current request and is not persisted to the session, so it does not leak onto the next page. The GET routes then read flash[:success] once; sinatra-flash deletes the value after it is read, giving true single-use messages.

The layout.erb tab renders whatever flash keys exist by iterating flash.keys, mapping each type to a CSS class. Because the layout is shared, any action that sets a flash gets a rendered banner for free. A subtle pitfall worth noting: flash relies on a working session cookie, so set :session_secret should be configured in real deployments, and redirects must point at same-origin paths. This structure keeps forms safe against double submits while giving clean, consistent user feedback.


Related snips

Share this code

Here's the card — post it anywhere.

Post-Redirect-Get in Sinatra with Sinatra::Flash and a redirect_to Helper — share card
Link copied