Modern Web Applications with Hotwire
Tags: ruby, rails, hotwirerails, stimulus
Published: 2021-07-12 15:46:24

# Why use Hotwire?

Rails views can sometimes be fast and work perfectly, but some other times they can cause all kinds of problems. For example, one of the most common situations is rendering a lot of partials that can make the application look slow. That could happen especially when the programmer is not careful about anti-patterns associated with Rails views.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/0eby7scw9hqpgwwxnxto.gif)
 

Also, JavaScript has been used as an alternative to dynamically update our content without having to refresh the entire browser. However, it is not a solution loved by many programmers: "Why would I want to leave my Ruby and Rails bubble of happiness?" (R, Subramaniamso, 2021).

**This is why**

Hotwire uses JavaScript libraries that provide connections to develop a more interactive and modern response system without the need to write a lot of JS code. And, the most important thing: without sacrificing any of the speed or responsiveness associated with a traditional single-page application.

## Hotwire has 3 Components

1. Turbo: It is the heart of Hotwire and it is kind of a new version of turbolinks. Also, it is used for speed and broadcasts updates and it has two elements: frames and streams.

2. Stimulus: It is used for flexibility and it is similar to JavaScript framework but for html — it does not deal with rendering HTML at all. In addition, Stimulus pairs perfectly with Turbo to provide quick fixes with minimal effort.

3. Strada: It is not released yet; it will be used for mobile hybrid applications.

Moreover, Turbo uses redis to store its data and handle websockets with action cable. This functionality is needed to autoloading the stimulus controllers without having to change anything in your controller classes to use it.


## Set-up
Add the hotwire-rails gem in your Gemfile file. This gem includes setup for Turbo and Stimulus; it also includes Redis. 

1. Run `bundle install`
2. Run `rails hotwire:install`
3. Run `yarn install`

Those steps will remove everything related to `turbolinks` from your `app/javascript/packs/application.js`.

Manually in your `app/views/layouts/application.html.erb` change the lines related to `data-turbolinks-track` to `data-turbo-track`.

**How to use Hotwire**

* Start by setting up Turbo feature frames. This provides built-in updates to parts of the page and not to the entire page.

* Add ActionCable broadcast channel preferences to your model.

```ruby
# app/models/tags.rb

class Tag < ApplicationRecord
  belongs_to :tag_type
  validates :name, presence: true, uniqueness: true

  after_create_commit { broadcast_prepend_to "tags" }
  after_update_commit { broadcast_replace_to "tags" }
  after_destroy_commit { broadcast_remove_to "tags" }
end
```

* Edit your view, add `theturbo_stream_from`, which tells Turbo where we get the updates from. It should be the same definition we used in our model for this example "tags".


```ruby
# app/views/tags/_tag.html.erb

<%= turbo_frame_tag dom_id(tag) do %>
 <i class="tiny material-icons">local_offer </i> #{tag.name} 
<% end %>
```

* Create our `turbo_frame` to mark which parts we want to update in our app.

```ruby
# app/views/tags/index.html.erb

<h5 class="center-align">Tags</h5>
<%= turbo_stream_from "tags" %>
<%= turbo_frame_tag "tags" do %>
 <%= render @tags  %>
<% end %>
<%= turbo_frame_tag "tag_form" do %>
  <%= render "form", tag: @tag   %>
<% end %>
```

# Wrapping up
The combination of Hotwire and Rails with a pinch of Stimulus for client-side interactivity, it is a powerful option for building high-performance, scalable, and easy-to-use web applications for both developers and users. Overall, you just have to consider using a design that fits this excellent solution.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ew7gbravdzkufff820q3.gif)


[See the original post on MagmaLabs Technical Blog:](http://blog.magmalabs.io/2021/07/08/hotwire-rails.html)