Hotwire in Ruby on Rails

Hotwire in Ruby on Rails

What is Hotwire?

Hotwire is a term coined by the creators of Ruby on Rails to describe a set of techniques and tools that enable fast and smooth page transitions without requiring any JavaScript. It works by intercepting links and form submissions, fetching the HTML from the server, and updating only the parts of the page that changed. It also supports partial page updates via WebSocket, using a protocol called Turbo Streams.

Hotwire is not a single library or framework, but rather a collection of three libraries that work together:

·     Turbo:

The core library that handles the HTML over the wire logic. It includes Turbo Drive, which manages the page transitions; Turbo Frames, which allows updating parts of the page; and Turbo Streams, which enables real-time updates via WebSocket

·     Stimulus:

A minimal JavaScript framework that complements Turbo by adding interactivity and behavior to the HTML elements. It works by connecting data attributes to JavaScript controllers, which can react to events and manipulate the DOM.

·     StimulusReflex:

An optional extension for Stimulus that adds declarative data fetching via another protocol called StimulusReflex. It allows updating the page based on changes in the server-side state, without writing any custom JavaScript code.


Together, these libraries allow developers to create modern web applications with minimal JavaScript code, while still leveraging the power and productivity of Ruby on Rails.

How does Hotwire work?

To understand how Hotwire works, let's take a look at a simple example of a web application that uses Hotwire. The application is a blog that allows users to create posts and comment on them. The application has three main views: a home page that lists all the posts, a show page that displays a single post and its comments, and a new page that allows creating a new post.

Using Turbo Drive for page transitions:

The first feature of Hotwire that we will use is Turbo Drive, which handles the page transitions. Turbo Drive works by intercepting any link or form submission on the page and fetching the HTML from the server using Ajax. Then, it replaces only the body element of the current page with the body element of the new page, preserving the head element and any scripts or stylesheets. This way, it avoids reloading the entire page or executing any JavaScript code.

To use Turbo Drive in our application, we need to install the hotwire-rails gem, which will add Turbo and Stimulus to our application. Then, we need to add a data-turbo-track attribute to any element that we want to preserve across page transitions, such as the navigation bar or the footer. For example:

<!-- html code -->

<nav data-turbo-track="reload">

  <!-- Navigation links -->

</nav>        

This attribute tells Turbo to reload the element if its content changes on the server. Alternatively, we can use data-turbo-permanent attribute to tell Turbo to never reload the element, even if its content changes.

Now, when we click on any link or submit any form on our application, Turbo Drive will handle the transition and update only the body element of the page. This will make our application faster and smoother, as it will avoid unnecessary requests and re-rendering.

Using Turbo Frames for partial updates:

The next feature of Hotwire that we will use is Turbo Frames, which allows updating parts of the page without reloading it. Turbo Frames works by wrapping any part of the page that we want to update in a turbo-frame tag with an id attribute. For example:

<!-- html code -->

<turbo-frame id="post">

  <!-- Post content -->

</turbo-frame>        

This tag tells Turbo to treat this part of the page as an independent unit that can be updated separately from the rest of the page. Then, we can link to this part of the page using an href attribute with a fragment identifier that matches the id of the turbo-frame tag. For example:

<!-- html code -->

<a href="/posts/1#post">View post</a>        

This link tells Turbo to fetch only the part of the page with id “post” from /posts/1 and replace it with the current part of the page with id “post”. This way, we can update parts of the page without reloading it.

We can use Turbo Frames in our application to make it more dynamic and responsive. For example, we can use Turbo Frames to update the comments section of the show page without reloading the whole page. To do that, we need to wrap the comments section in a turbo-frame tag with an id attribute, such as:

<!-- html code -->

<turbo-frame id="comments">

 <!-- Comments content -->

</turbo-frame>        

Then, we need to link to this part of the page using an href attribute with a fragment identifier that matches the id of the turbo-frame tag. For example:

<!-- html code -->

<a href="/posts/1#comments">View comments</a>        

This link tells Turbo to fetch only the part of the page with id "comments" from /posts/1 and replace it with the current part of the page with id "comments". This way, we can update the comments section without reloading the whole page.

 

Using Turbo Streams for real-time updates:

The last feature of Hotwire that we will use is Turbo Streams, which enables real-time updates via WebSocket. Turbo Streams works by sending HTML fragments over WebSocket that describe how to update parts of the page. These fragments are wrapped in a turbo-stream tag with an action attribute that specifies what kind of update to perform. For example:

<!-- html code -->

<turbo-stream action="append" target="comments">

  <template>

    <!-- New comment content -->

  </template>

</turbo-stream>        

This tag tells Turbo to append the content of the template tag to the end of the element with id "comments". There are other actions available, such as replace, remove, update, or prepend.

We can use Turbo Streams in our application to make it more interactive and real-time. For example, we can use Turbo Streams to add new comments to the show page without refreshing it. To do that, we need to set up a WebSocket connection between the server and the client using Action Cable, which is a built-in feature of Ruby on Rails that allows bi-directional communication over WebSocket. Then, we need to broadcast a Turbo Stream message from the server whenever a new comment is created. For example:

# Ruby code

class CommentsController < ApplicationController

 def create

  @post = Post.find(params[:post_id])

  @comment = @post.comments.create(comment_params)

  # Broadcast a Turbo Stream message with the new comment

  broadcast_append_to "comments", partial: "comments/comment", locals: { comment: @comment }

 end

end        

This code tells Action Cable to broadcast a message with the action "append", the target "comments", and the partial "comments/comment" that renders the new comment. The broadcast_append_to method is a helper method provided by hotwire-rails gem that generates a Turbo Stream message from a partial.


On the client side, we need to subscribe to the WebSocket channel and listen for Turbo Stream messages. We can do that using a Stimulus controller that connects to Action Cable and passes any received messages to Turbo. For example:

// javascript code

import { Controller } from "@hotwired/stimulus"

import consumer from "./consumer"

export default class extends Controller {

 connect() {

  // Subscribe to the WebSocket channel

  this.subscription = consumer.subscriptions.create("Turbo::StreamsChannel", {

   // Pass any received messages to Turbo

   received: (data) => {

    Turbo.renderStreamMessage(data)

   }

  })

 }

 disconnect() {

  // Unsubscribe from the WebSocket channel

  this.subscription.unsubscribe()

 }

}        

This code tells Stimulus to create a controller that subscribes to the "Turbo::StreamsChannel" channel and passes any received messages to Turbo using the renderStreamMessage method. The connect and disconnect methods are lifecycle callbacks that are invoked when the controller is attached or detached from the DOM.

 

Now, when we create a new comment on our application, it will be automatically added to the show page without refreshing it, thanks to Turbo Streams.

 

Source:

-  https://hotwire.dev/

-  https://turbo.hotwire.dev/

-  https://stimulus.hotwire.dev/

-  https://docs.stimulusreflex.com/

-  https://guides.rubyonrails.org/action_cable_overview.html

- https://www.bootrails.com/blog/rails-7-hotwire-a-tutorial/

To view or add a comment, sign in

Others also viewed

Explore content categories