How to - Rails turbo
Tags: turbo, rails, hotwire, tutorial
Published: 2022-05-10 19:24:55

##Why turbo

NO JS ?!

![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ozbnpwbn855l42red828.gif)


When your application needs to be more 'dynamic' than the simple old school 1 request 1 view, you would typically use javascript, or a complete javascript framework like React to turn the page into a Single Page Application, _however_ this is cumbersome, especially in the rails spirit of the ability to maintain the stack as one developer.

Turbo reduces the requirements for javascript in your rails application, and makes it more like a single page application ( although, this is by far not a replacement for that ) 


This a quick 'how to' run and use turbo in a rails application
How to use turbo on rails, credit goes to https://hotwired.dev/, you can also checkout https://turbo.hotwired.dev/handbook/introduction for the documentation on turbo


##Requirements

Minimum rails 6 app ( it is installed automatically on a rails 7 app ), to install on rails 6 refer to https://github.com/hotwired/turbo-rails#:~:text=Add%20the%20turbo,Turbo%20Stream%20broadcasting.

##Step by step process from scratch in a rails 7 app.
Prerequisites
`rails -v                                                                                        
Rails 7.0.2.4
`
and
`ruby -v                                                                                         
ruby 3.0.0p0`
Otherwise refer to https://guides.rubyonrails.org/getting_started.html for getting set up with rails on your machine

run `rails new turbo-example`

Make sure it works by `cd turbo-example` and running `rails s`
You should see something like `Listening on http://localhost:3000/items
`
Next, let's make a simple model 'item'

`rails g scaffold Item title:string description:text` and ` rake db:migrate`

navigate browser to `http://localhost:3000/items` or whatever url you have, and you should be able to see the very empty item list.

## Turbo_frame
go to `app/views/items/index.html.erb` and wrap the last line 'new item' to be 
```erb
<%= turbo_frame_tag "new_item" do %>
  <%= link_to "New item", new_item_path %>
<% end %>
```

now go to `app/views/items/new.html.erb` and wrap the form render like this
```erb
<%= turbo_frame_tag "new_item" do %>
  <%= render "form", item: @item %>
<% end %>
```

We now have a turbo frame on our items list in the index, you can see that the page does not reload on clicking new item, or on create. However, you have to refresh to actually see the new item.

for that we can use turbo_stream

## Turbo_stream
go to `app/views/items/index.html.erb`
and add `<%= turbo_stream_from @items %>` above the items div
so it looks like
```erb
<h1>Items</h1>

<%= turbo_stream_from @items %>

<div id="items">
  <% @items.each do |item| %>
    <%= render item %>
    <p>
      <%= link_to "Show this item", item %>
    </p>
  <% end %>
</div>


<%= turbo_frame_tag "new_item" do %>
  <%= link_to "New item", new_item_path %>
<% end %>
```

next go to `app/models/item.rb` and add `broadcasts`

This lets the model broadcast everything happening to it (create update and delete) Note that this is regardless of any authorization rights, so keep that in mind.

now go to `app/controllers/items_controller.rb#create`
and add `format.turbo_stream` to the successful save render
it should look like this
```rb
  def create
    @item = Item.new(item_params)

    respond_to do |format|
      if @item.save
        format.turbo_stream
        format.html { redirect_to item_url(@item), notice: "Item was successfully created." }
        format.json { render :show, status: :created, location: @item }
      else
        format.html { render :new, status: :unprocessable_entity }
        format.json { render json: @item.errors, status: :unprocessable_entity }
      end
    end
  end
```

lastly create `app/views/items/create.turbo_stream.erb` with the content `<%= turbo_stream.prepend "items", @item %>`


Notice the form is still the same, we can fix this by adding 
`<%= turbo_stream.replace "new_item", partial: 'items/form', locals: { item: Item.new } %>`
in the `app/views/items/create.turbo_stream.erb`

the file will look like this
```erb
<!-- Refresh preview list -->
<%= turbo_stream.prepend "items", @item %>

<!-- Reset form -->
<%= turbo_stream.replace "new_item", partial: 'items/form', locals: { item: Item.new } %>


```

You can find an example project of this exact step-by-step guide on https://github.com/nicho1991/turbo-example