Turbo8 in rails7

使用turbo8快速开发单页面效果的网页应用

Turbo 8 简化了实时更新 Rails 应用程序的开发。通过最大限度地减少手动编码 Turbo 帧和 Turbo 流响应的需要,它比以前的版本实现了巨大的飞跃。这一进步简化了 Rails 应用程序的创建和维护,使您的工作效率更高。 如果您不熟悉 Turbo,它是 Ruby on Rails 应用程序广泛使用的一个库,用于部分更新页面,使它们感觉像单页 JavaScript 应用程序。它类似于 HTMX、StimulusReflex、Phoenix LiveView 和 Laravel LiveWire 等框架。

自从本年十月份的rails world上提出turbo8的概念后,它使得turbo更上了一层,达到只更新页面的部分而不刷新整个页面, 虽然之前的turbo_frame 和stream_actions 也能做到同样的效果, 但是它要写很多的代码和理解,例如下面的一个例子,

# model/note.rb
class Note < ApplicationRecord
  belongs_to :user, class_name: "User"
  validates :name, presence: true
  has_many :note_types,  dependent: :destroy
  has_many :note_items, through: :note_types

  scope :ordered, -> { order(id: :desc) }

  broadcasts_to ->(note) { [ note.user, 'notes'] }, inserts_by: :prepend
end

在note model 里使用broadcasts_to 通知note的更新。

# app/controllers/note_controller.rb
  def create
    @note = current_user.notes.create!(note_params)
    respond_to do |format|
      if @note.save
        format.html { redirect_to notes_path, notice: '笔记添加成功' }
        format.turbo_stream { flash.now[:notice] = '笔记添加成功' }
      else
        format.html { render :new, status: :unprocessable_entity }
      end
    end
  end

  def update
    if @note.update(note_params)
      respond_to do |format|
        format.html { redirect_to  notes_path, notice: '笔记修改成功' }
        format.turbo_stream
      end
    else
      render :edit, status: :unprocessable_entity
    end
  end

在这里用format.turbo_stream

#app/views/notes/index.html.erb
<%= turbo_stream_from current_user, "notes" %>
<div class="container bg-white dark:bg-gray-900">
  <h1 class="text-center">学习笔记</h1>
</div>
<div class="relative overflow-x-auto">
    <h2 class="mb-4  text-xl font-bold text-gray-900 dark:text-white"></h2>
    <button
         type="button"
         class="inline-flex justify-end items-center px-5 py-2.5 mt-4 sm:mt-6 text-sm font-medium text-center text-white bg-primary-700 rounded-lg focus:ring-4 focus:ring-primary-200 dark:focus:ring-primary-900 hover:bg-primary-800"
        >
         <%= link_to "添加笔记", new_note_path, data: { turbo_frame: dom_id(Note.new) } %>
    </button>
    <% if @notes.empty? %>
      <%= render "notes/empty_state" %>
    <% else %>
       <%= turbo_frame_tag Note.new %>
        <%= turbo_frame_tag "notes" do %>
          <%= render @notes %>
        <% end %>

        <% if @pagy.count > @pagy.items %>
          <div class="">
            <%== pagy_nav(@pagy) %>
          </div>
        <% end %>
    <% end %>

</div>

这里使用 turbo_frame_tag 标记新增和notes列表当新增的时候跳转到new.html.erb发现那里面也有 turbo_frame_tag 同样的id就使用turbo_frame的功能达到值更新部分页面的效果