Processing link and button clicks with and without Turbo
How Rails handles link and button clicks with and without Turbo.
I’ve been playing around with Hotwire for the past couple days. For those who don’t know what Hotwire is, it’s a “new” addition to the Ruby on Rails ecosystem that bring Single Page Application capabilities to your Ruby on Rails application. It achieves this through 4 distinct parts namely; Turbo streams, Turbo Frames and Turbo drive. Behavior for your already existing HTML may be added by another component of Hotwire named Stimulus JS.
For my first Hotwire application, i built the classic Rails blog application, only this time with Hotwire as a way of getting my hands dirty. Below is what the final application looks like:
In the application above, each post has 3 buttons: a show button, an update button plus a delete button. At the top of the page, we have a “New Post” button which when clicked renders a “create post” form on the index page. This form has a “Create New Post” button which submits the form to create a new post. We also have an “Update post” button which is rendered as part of the “edit post” form. As of Rails 7, clicks on “links” and “buttons” to submit forms in Rails applications are processed as TURBO STREAM requests instead of HTML requests unless specified otherwise. What this means is that, when we click on the “Create New Post” button, the “Update Post” and “delete” buttons for a given post, these requests will be processed as turbo_stream requests instead of HTML. This is because they involve submitting a “form” plus making related changes to the database which may involve deleting, creating or updating a post. In contrary, links and buttons to show a post, render the “new post” form or “edit post” form are processed as HTML.
All this Turbo functionality is included by default when we create a new rails app. We’ll take a look at the server logs for each of the aforementioned actions to see how the clicks on the various buttons are processed. First and foremost, creating a new post. When you click the “New Post” button, a form is rendered on the index page.
The “get” request for the form is processed as HTML instead of as "turbo_stream”. This is because clicking on the “New Post” button doesn’t submit a form but rather only “gets” the “new post” form(_form.html.erb) and displays it on the index page. Therefore when we look at the server logs to see how the request for the “new post” form was processed, we see the lines:
The above shows that the request was processed as HTML and not “turbo_stream”.
Now let’s try creating a new post and see the difference. Remember this will involve clicking on a button named “Create New Post” which submits a form and thus makes changes to the database.
By creating a new post, we notice a change in the server logs. The ‘post” request associated with submitting the form and creating a new post is processed as a “turbo_stream” instead of an HTML request.
Notice the line “Processing by PostsController#create as TURBO_STREAM”.
This observation forms the basis of the rule when dealing with links or buttons as of Rails 7 applications, “When a link/button that submits a form and thus makes changes to the database is clicked, the request for the associated action is processed as a TURBO STREAM unless turbo is disabled for that particular form, whereby in that case, the request will be processed as HTML”.
We’ll test out this rule to see if it applies for other CRUD actions. First, the update action. When we click on the “Update” button, we expect the “get” request for the “edit” form to be processed as HTML and the click on the “Update Post” button which submits the form associated with editing a post and saving the update to the database, to be processed as TURBO STREAM.
Rendering the edit form:
Server logs for rendering the edit form:
We see that the “get” request for the “edit post” form is processed as HTML which is expected.
Updating the actual post:
Updating Post server logs:
Here we see that the “Patch” request is processed as a TURBO_STREAM instead of HTML which is expected.
For our show action, we’ll expect the “get” request to be processed as HTML instead of TURBO_STREAM as it doesn’t involve submitting a form.
Show action server logs:
Lastly, for the destroy action, we expect the “delete” request to be processed as a turbo_stream. You’ll also notice that all “get” requests are processed as HTML by default with the other types of requests processed as TURBO STREAMS. This is because, in traditional rails applications, requests other than “get” tend to result into redirects and thus full page reloads thus causing the application to be slow. Turbo does away with this by allowing changes to be made only to the parts of the page that changed instead of reloading the entire page.
Destroy action server logs:
And now that we’ve seen how our rule applies to all necessary CRUD actions that is, creating, updating and deleting a post, we pose a very crucial question.
Why opt for TURBO STREAMS instead of HTML for creating, updating and deleting a post?
Turbo streams, a part of Hotwire, is a way of adding Single Page Application capabilities to traditional Rails applications. Turbo achieves this by doing away with full-page reloads which may cause the application to be slow in cases of heavy traffic or multiple database queries. By processing requests to create, update and delete a post as turbo streams, only the parts of the page that changed are updated instead of the entire page. Overall, this change results into a smooth user experience and makes the application faster as a whole.
Now a question for the reader:
Let’s say i have a redirect_to method as part of the create, update and destroy actions of the Posts Controller. Will this redirect be processed as HTML or TURBO STREAM.
Find out the answer in the next edition of ThumbsUp Rails.
And that marks the end of this blog post. If you’ve reached this far, congragulations for following along. And, incase of any suggestions, you can always reach me via DM here on Substack or zhephyn on Twitter/X.
Also, to receive future posts directly to your inbox, consider subscribing to the publication by clicking the button below.