Why turbo
NO JS ?!
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
<%= 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
<%= 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
<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
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
<!-- 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
Top comments (0)