This article is basically a snippet for a common pattern in web apps, and I struggle to find the right way each time I want to implement this behaviour in my rails apps with turbo enabled 😅
What we want
On a form submission, I want to redirect to a new page on success, and render errors otherwise.
Let’s take a dummy model for our example: a Post with title/description as text attributes
And our new.html.erb view:
When turbo is enabled, it does not work at all.
FYI, If you want to disable turbo you can add the
the form (which solved the issue).
Like I said in the intro, I struggle each time to have a working version of this with turbo, which consists of a dynamic display of errors and a simple redirect to my path.
Wrap your form (with errors) in a
turbo-frame tag, and add a
turbo-frame="_top" on the form:
The tricky part here is the
turbo-frame="_top": without it turbo intercept
the redirection, and does not perform a “full” reload of our page.
In the controller, on success use http status 303 (See Other), and on failure use a 422 http status (Unprocessable entity)
Turbo relies a lot on HTTP status. When the server renders a 4xx or 5xx error, it does not perform the redirection.
All you need to do is to write a
new.turbo_stream.erb which we’ll be triggered
render :new in our controller:
When you submit your form, it accepts turbo stream as response, adding a view with turbo stream format bypass entirely the html response and let us to do what we want: render the form (and the errors) on our frame.
Note: You have to put your entire ‘new’ view in a partial (or just your form) in order to be able to use a partial here.
At this point, it should be OK.