Rails World 2023

Hotwire Cookbook: Common Uses, Essential Patterns & Best Practices

Hotwire Cookbook: Common Uses, Essential Patterns & Best Practices

by Yaroslav Shmarov

In the video titled 'Hotwire Cookbook: Common Uses, Essential Patterns & Best Practices,' Yaroslav Shmarov, a Rails mentor, discusses effective methods for addressing common frontend challenges using Hotwire. He emphasizes a practical approach with 'recipes' to solve various UI problems, helping backend developers transition into using Hotwire seamlessly. The presentation covers several significant topics:

  • Understanding Turbo Drive: Yaroslav describes Turbo Drive as a culmination of Turbolinks and Rails UJS, providing features such as persistent elements across page transitions, confirmed submissions, and improved user interaction through methods like 'data-turbo-method'.

  • Turbo Frames: Key for lazy loading and self-contained page elements, Turbo Frames allow for efficient rendering of components like search functionalities and modals without full page reloads, minimizing server load and improving user experience.

  • Inline Editing and Chained Selects: Examples include editable lists where specific attributes can be updated seamlessly and chained select boxes that change options based on prior user selections, showcasing Hotwire's functionality in streamlining interactions.

  • Dynamic Content with Turbo Streams: The speaker explains how Turbo Streams enable real-time updates on the user interface, making it easy to handle CRUD operations without page refreshes, which is ideal for applications requiring live data updates, like chats or notifications.

  • Integrating Stimulus: Yaroslav advocates for using Stimulus to enhance Rails applications without relying heavily on JavaScript frameworks, demonstrating improvements in code cleanliness and project management functionalities.

Throughout the presentation, Yaroslav interweaves practical examples, like the persistent search element from his website and dynamic modals for error handling, to illustrate how Hotwire can elevate Rails applications. He concludes by encouraging developers to embrace Hotwire, emphasizing its potential to simplify development while maintaining a delightful user experience. In summary, this talk serves as a foundational guide for Ruby on Rails developers to effectively implement Hotwire in their applications, covering its capabilities and best practices for maintainable code and user-friendly interfaces.

Importantly, he highlights the synergy between Hotwire components, encouraging experimentation and integration into existing projects to enhance interactivity and responsiveness.

00:00:15.280 So nice to be here with you. Thank you all for coming. My name is Yaroslav, and I'm from Ukraine. You might know me from my blog or from my SuperAils YouTube channel, where I post a lot of content about Ruby on Rails, especially about Hotwire.
00:00:27.800 I originate from northern Ukraine, and I used to live just 80 kilometers away from Chernobyl. That area is now liberated, which is great. However, my family's home was burned in one of the early days of the war.
00:00:40.239 My godfather went to defend Ukraine. Despite the war, we're dealing with it. Just today, the city of Kharkiv was randomly bombed by the Russians, affecting many people, including those from the Ruby on Rails community in Ukraine, some of whom are actively fighting.
00:01:00.000 On a positive note, I recently became a father just two and a half months ago in France. Today, we're going to talk about Hotwire.
00:01:13.159 We had a nice talk by Jorge about Turbo, discussing its future. Then there was Marco, who spoke about the many tools in the Hotwire ecosystem. He brings all the tools to the table, while I'm doing the cooking—hence the title, the Hotwire Cookbook.
00:01:27.800 Last week, I was in Romania and received a beautiful cookbook. I prepared the Hotwire Cookbook presentation during my time there.
00:01:35.000 I've created a lot of videos covering different aspects of Hotwire, such as Turbo, Stimulus, and Turbo Streams. You can check out the 'Just Enough Hotwire for Rails Developers' series on my channel, which has become quite popular recently.
00:01:55.600 In this presentation, I'm going to show you a few common recipes and the simplest things you can build with different parts of Hotwire. We will cover Turbo Drive, Turbo Frames, Turbo Streams, and Stimulus.
00:02:10.959 While speaking with many people in the lobby, I found that a lot of them identified as backend developers—specifically as Rails backend developers. Many have heard of Hotwire, and some have tried it.
00:02:32.799 Could I see a show of hands from those who have not yet tried Hotwire? Hmm, okay, I’ll primarily target you with these very simple recipes to help you understand the basics.
00:02:44.159 We'll start with Turbo Drive. Although it’s been said that Turbolinks is dead, I see Turbo Drive as a combination of Turbolinks and Rails UJS.
00:03:01.159 For years, I simply kept the Turbolinks gem in my Gemfile, sometimes disabling it, along with Rails UJS. I never really understood why, but I maintained both until now, as we only need the Turbo Rails gem to handle everything.
00:03:44.160 So, what does Turbo Drive do? It has some explicit features you can utilize. For example, previously with Rails 6 and earlier versions, you were able to use 'link_to' with non-GET requests, but Rails UJS was deprecated and is no longer part of the default stack. However, now you can use 'link_to' with the data-turbo-method attribute set to delete, and Turbo will handle it.
00:04:58.840 It's suggested that if you’re not making a GET request, you should use a button instead. Additionally, in earlier versions using Rails UJS, you could prompt for confirmation using data-confirm. Now, with Turbo, you use data-turbo-confirm. Migrating from previous versions of Rails to Rails 7 is straightforward.
00:05:55.960 Furthermore, you might notice a feature called 'disable on submit.' You click submit and can’t click it again, boosting user experience. Turbo provides methods to handle this seamlessly. One of my favorite features allows persistent elements across different pages. This means that in a demo, when I click a video or audio, those elements maintain state across transitions.
00:06:36.800 Each element that should remain persistent needs to have a unique ID and include data-turbo-permanent set to true. This behaves like the 37signals podcast, where if I click play and navigate, the player continues playing because it’s using data-turbo-permanent as well.
00:07:30.200 Another usage example of data-turbo-permanent can be seen on my SuperAils website, which allows for searching. If I search and navigate to another page, the search results persist, saved only in the HTML.
00:08:18.320 Sometimes, you’ll need to disable Turbo, particularly when dealing with devices that aren’t compatible. For example, you might add data-turbo-frame to actions that could perform a redirect.
00:08:59.500 Next, let’s discuss Turbo Frames. Turbo Frames have two main features: lazy loading and self-contained page elements. Lazy loading allows for a collection of records to load as you scroll through an employee page, improving page load speed.
00:09:35.200 I’ll show you through a hustle-free interface how lazy loading works. When an element becomes visible on the page, it automatically makes a request to load its content. Using 'loading lazy' ensures items load only as needed. For example, if you click my avatar on Basecamp, a request is made only when needed, so it doesn't waste resources.
00:10:34.760 Another way lazy loading can be implemented is through the HTML details tag, which allows you to load elements upon unhiding them. With Twitter and GitHub, hovering over profiles initiates new requests without preloading all profiles, thus managing memory effectively.
00:11:17.680 Turbo Frames also support self-contained page elements, critical for tasks like searching and filtering through tables. As I type in the search field, each entry immediately updates the displayed results, further ensuring the URL is automatically refreshed with new search queries.
00:12:15.840 To accomplish this, I'm using Turbo Frame around my search elements. When I submit the form, the response updates only the designated Turbo Frame elements rather than refreshing the entire page.
00:12:46.960 After discussing search, let’s move to sorting functionalities. I implemented sortable links. Similar to search, sorting requires an update to the URL. To achieve that, I’ve added the 'data-turbo-action' attribute to the relevant Turbo Frame.
00:13:50.200 Now we can also discuss inline editing. Imagine working on a list of employees; if I want to edit a specific attribute, I click on it, which triggers a request to the edit page and updates that field directly.
00:14:48.760 Each attribute is wrapped in a separate Turbo Frame, ensuring that only that specific attribute requests and updates while leaving the rest unaltered. You can explore my GitHub for extensive examples and further material on Hotwire.
00:15:29.560 Another interesting feature is chained selects. Historically, I’ve seen companies using React just for this simple UX pattern, but with Turbo Frames, you can easily implement this without the overhead of a full framework.
00:16:17.759 For example, after selecting a country, I can then select a state, followed later by a city. All without unnecessary page reloads and with just a few components.
00:17:15.320 When it comes to modals, if I want to edit an employee's information, I click on the 'new employee' button. If any errors arise during input, they will render directly within the modal, keeping the user's flow uninterrupted.
00:18:05.319 To implement this, the link to the 'new employee' action has a data-turbo-frame attribute. Consequently, Turbo knows to display this action in the modal. Likewise, the modal is wrapped in a Turbo Frame to facilitate clear rendering.
00:18:49.280 Returning to Turbo Frames, they can feel quite complex initially. If you identify as a backend developer and want to dapple in Turbo, begin by inspecting Turbo requests through the browser's network tab.
00:19:41.960 This ensures that you employ different data attributes correctly for replacing elements. I recommend gaining a good understanding of how HTML forms work, specifically when differing submit buttons are involved.
00:20:20.079 Next, we’ll transition into Turbo Streams. For me, Turbo Streams resemble rebranded JS. Previously, with format JS response types, you’d replace an element on the page dynamically.
00:21:10.230 Now, with Turbo Streams, we use the format turbo_stream. You can perform operations such as updating, removing, or adding elements dynamically.
00:21:53.639 For example, I can easily add or update elements without a page refresh. When submitting records for employees, the list updates dynamically as you modify the details.
00:22:32.549 In practice, when an employee is deleted, a Turbo Stream action removes the relevant element from the list visually in real-time without needing a full page refresh.
00:23:29.440 To further enhance user experience, Turbo Streams can be combined with Turbo Frames for functionalities like infinite pagination. When scrolling down, more content can automatically be fetched and displayed.
00:24:40.080 Turbo Streams can also incorporate broadcasts using Action Cable to allow real-time updates between users. This is crucial for features like live chats where message updates should seamlessly reflect across different users without page refreshes.
00:25:24.960 While implementing live messages, Turbo Streams facilitate mutual updates in two instances, ensuring that both users receive consistent information drive across different messages.
00:26:11.440 Turbo Streams can also be applied to delivering notifications such as alerts, maintaining a dynamic user experience throughout various applications.
00:26:49.440 When it comes to broadcasting specific updates to users, create a channel dedicated to communicating real-time changes. This can enhance interactivity in various applications.
00:27:37.560 Now, I'm excited to transition to discussing Stimulus, which I deeply appreciate as a tool. I’ve always seen myself as a Ruby on Rails developer and avoided heavy reliance on JavaScript frameworks like React.
00:28:36.440 With Stimulus, I don't need to disable Turbo when loading JavaScript, providing a more integrated approach to development. I've effectively replaced numerous inline scripts with Stimulus, allowing for a cleaner structure.
00:29:37.520 For instance, in Basecamp’s examples, they’ve utilized live interactions elegantly. You can recreate project management functionalities in a new Rails application, such as task lists and draggable items, using libraries like SortableJS and RequestJS for database updates.
00:30:30.480 By leveraging external libraries and building your own Stimulus Controllers, you can create robust user interfaces without the encumbrances of more complicated frameworks.
00:31:01.599 Lastly, I want to encourage all of you to explore Hotwire. It creates a satisfying developer experience that aligns well with a back-end Ruby developer’s mindset. Thank you all for being here today.