# Optimistic Forms

poetry_optimistic_form — the predicted result paints on submit as a server-authored Turbo Stream; the server corrects only on rejection (morph refresh). One vocabulary for prediction and truth, plus the 204/no-redirect server contract.

## Default

```erb
<%# The favorite toggle. The optimistic_template predicts the TOGGLED
    state as a turbo-stream; the button shows the current one. Submit and
    the label flips instantly - the server answers 204 and is never
    waited on. State rides the session, so a reload shows server truth. %>
<% favorite = session[:docs_favorite] %>
<%= poetry_optimistic_form(url: optimistic_favorite_path, method: :post, attribute_name: :favorite, value: !favorite) do |form| %>
  <%= form.optimistic_template "docs-favorite",
        safe_join([poetry_icon(name: favorite ? :"star-off" : :star, class: "size-4"),
                   favorite ? "Favorite" : "Unfavorite"], " ") %>
  <%= poetry_button(variant: :outline, type: :submit) do %>
    <span id="docs-favorite" class="inline-flex items-center gap-2">
      <%= poetry_icon(name: favorite ? :star : :"star-off", class: "size-4") %>
      <%= favorite ? "Unfavorite" : "Favorite" %>
    </span>
  <% end %>
<% end %>
```

## Reconciliation

```erb
<%# The failure path, on purpose. The prediction paints "Subscribed ✓"
    instantly; the endpoint always answers 422, so the controller appends
    a refresh stream and the morph puts authoritative truth back - watch
    the button snap home. The flash the server set survives the refresh. %>
<%= poetry_optimistic_form(url: optimistic_rejected_path, method: :post) do |form| %>
  <%= form.optimistic_template "docs-subscribe", "Subscribed ✓" %>
  <%= poetry_button(variant: :secondary, type: :submit) do %>
    <span id="docs-subscribe">Subscribe (server will reject)</span>
  <% end %>
<% end %>
```
