# Ruby on Rails 7: Hotwire lae Turbo samrap Aepplikheishan Riaethaim > Khumue sombun khong Hotwire lae Turbo nai Rails 7. Sang aepplikheishan riaethaim doi mai tong khian JavaScript duai Turbo Drive, Frames lae Streams. - Published: 2026-01-11 - Updated: 2026-04-07 - Author: SharpSkill - Tags: ruby on rails, hotwire, turbo, turbo frames, turbo streams - Reading time: 12 min --- Rails 7 pathiwat kan phatthana web doi kanruam Hotwire pen khakamnot. Stack ni thamhai samartriang sang aepplikheishan thi mi khwam riaethaim sung doi mai tong khian khot JavaScript thi kahamnot eng mae sak brrthad nueng. Turbo Drive, Turbo Frames lae Turbo Streams thaenthi withikan SPA daengdoem duai pratchya "HTML phan sai". > **Thammai tueng Hotwire?** > > Hotwire lot khwam sapson khong frontend yang mak. Mai champen tong chai React rue Vue samrap inthoerefet thi mi kan toptoep: soewoe song HTML thi phrom chai lae Turbo chatkan kap kapnhat DOM doi atonmat. ## Khaojai Sathapattayakam Hotwire Hotwire prakop duai sam thekhnoloyi thi soem kan pen thanglueak tham ngan ruam kan phue mop prasopkan phuchai thi rapruen doi mai mi khwam sapson thi thammada khong framework JavaScript. **Turbo Drive** reng khwam reo nai kan naewithang doi kan rap klik linkhae lae kan song baep. Thaen thi cha lotphaena thang mot, cha mi phiang nueaha khong `` thuk thaenthi, doi rak sa boribot khong JavaScript lae CSS wai. **Turbo Frames** baeng phaena pen suan thi pen itsara. Tae la frame samat kapnhat idyaek, thamhai samat mi kan toptoep bep jaomung doi mai kra thop suan thi luea khong phaena. **Turbo Streams** het hai samat kapnhat raiaethaim phan WebSocket rue pen kan toptoep HTTP request. Paet kan kra tham CRUD mi hai samrap kan chatkan DOM baep prakat. ```ruby # Gemfile # Installing Turbo Rails (included by default in Rails 7+) gem 'turbo-rails' ``` Samrap porachek thi mi yu laew, kan tittang tong kan phiang kham sang diaw. ```bash # installation.sh # Installing Turbo in an existing Rails project rails turbo:install # Verify the JavaScript import is present cat app/javascript/application.js # Should contain: import "@hotwired/turbo-rails" ``` ## Kan Kamnot Kha Roemton Turbo Drive Turbo Drive thuek poet chai pen kha khamnot nai Rails 7. Kan naewithang thang mot cha pen "turbo" doi atonmat doi mai tong mi kan kamnot kha phoem. Phruettikam samat prap taeng dai thang atthribut data. ```erb <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %>
<%= yield %> ``` Turbo Drive samat pit kan chai bon link rue baep thi chapho mue champen. ```erb <%= link_to "Dashboard", dashboard_path %> <%= link_to "Download PDF", export_path, data: { turbo: false } %> <%= form_with model: @document, data: { turbo: false } do |f| %> <%= f.file_field :attachment %> <%= f.submit "Upload" %> <% end %> <%= link_to "Delete", item_path(@item), data: { turbo_method: :delete, turbo_confirm: "Are you sure?" } %> ``` > **Khaet Turbo Drive** > > Turbo Drive khaet phaena thi yiam laew. Atthribut `data-turbo-track="reload"` bon asset bangkhap kan lot mai thang mot tha fai CSS/JS mi kan plianplaeng. ## Turbo Frames samrap Kapnhat Baep Jaomung Turbo Frames kahamnot son khong phaena thi kapnhat pen itsara. Tae la frame mi tuarabubang thi mi ekkalak lae toptoep phiang kap khamtop thi mi frame thi trongkan. ```erb

Messages

<%= render @messages %>
<%= link_to "Load more", messages_path(page: @next_page) %>
<%= render "form", message: Message.new %> ``` Khamtop chak soewoe tong mi frame thi mi tuarabubang diaw kan phue hai kan kapnhat tham ngan. ```erb

<%= message.content %>

<%= link_to "Edit", edit_message_path(message) %> <%= button_to "Delete", message_path(message), method: :delete %>
``` ### Lazy Loading kap Turbo Frames Frame samat lot nueaha baep asinkronat doi chai atthribut `src`. Nueaha roemton cha saadaeng nai rawang kan lot. ```erb

Dashboard

Loading statistics...

Loading notifications...

<%= render "activity/placeholder" %> ``` Khonthrolen toptoep kap view thi mi phiang frame thi rong kho. ```ruby # app/controllers/dashboard_controller.rb class DashboardController < ApplicationController def stats @user_count = User.count @message_count = Message.count @active_today = User.where("last_seen_at > ?", 24.hours.ago).count # Partial rendering for the frame render partial: "dashboard/stats" end end ``` ```erb

<%= @user_count %>

Users

<%= @message_count %>

Messages

<%= @active_today %>

Active today

``` ## Turbo Streams samrap Kapnhat Raiaethaim Turbo Streams sanoe paet kan kra tham samrap kan chatkan DOM: `append`, `prepend`, `replace`, `update`, `remove`, `before`, `after` lae `morph`. Kan kra tham lehla ni samat thuek riak phan khamtop HTTP rue WebSocket. ```ruby # app/controllers/messages_controller.rb class MessagesController < ApplicationController def create @message = current_user.messages.build(message_params) respond_to do |format| if @message.save # Turbo Stream response to add the message format.turbo_stream do render turbo_stream: [ turbo_stream.prepend("messages", @message), turbo_stream.update("message_count", partial: "messages/count"), turbo_stream.replace("new_message", partial: "messages/form", locals: { message: Message.new }) ] end format.html { redirect_to messages_path, notice: "Message created" } else format.turbo_stream do render turbo_stream: turbo_stream.replace( "new_message", partial: "messages/form", locals: { message: @message } ) end format.html { render :new, status: :unprocessable_entity } end end end def destroy @message = Message.find(params[:id]) @message.destroy respond_to do |format| # Removal with animation format.turbo_stream { render turbo_stream: turbo_stream.remove(@message) } format.html { redirect_to messages_path, notice: "Message deleted" } end end end ``` ### Thaemplet Turbo Stream Chapho Samrap khamtop thi sapson kwanan, thaemplet `.turbo_stream.erb` sanoe khwam yuedhyun makkwa. ```erb <%= turbo_stream.prepend "messages" do %> <%= render @message %> <% end %> <%= turbo_stream.update "message_count" do %> <%= Message.count %> messages <% end %> <%= turbo_stream.replace "new_message" do %> <%= render "form", message: Message.new %> <% end %> <%= turbo_stream.prepend "flash_messages" do %>
Message sent successfully!
<% end %> ``` > **Rup Baep Khamtop** > > Khamtop Turbo Stream tong mi content-type `text/vnd.turbo-stream.html`. Rails chatkan singni doi atonmat kap `respond_to` lae rup baep `turbo_stream`. ## Broadcasting Raiaethaim kap Action Cable Turbo Streams doden dai di thi sut kap kan broadcasting WebSocket. Phuchai dai rap kapnhat thanthi doi mai tong polling. ```ruby # app/models/message.rb class Message < ApplicationRecord belongs_to :room belongs_to :author, class_name: "User" # Automatic broadcast after creation after_create_commit do broadcast_append_to( room, target: "messages", partial: "messages/message", locals: { message: self } ) end # Broadcast after update after_update_commit do broadcast_replace_to( room, target: dom_id(self), partial: "messages/message", locals: { message: self } ) end # Broadcast after deletion after_destroy_commit do broadcast_remove_to(room, target: dom_id(self)) end end ``` View samak rap stream thi trongkan duai helper `turbo_stream_from`. ```erb

<%= @room.name %>

<%= turbo_stream_from @room %>
<%= render @room.messages.order(created_at: :asc) %>
<%= form_with model: [@room, Message.new], id: "new_message" do |f| %> <%= f.text_area :content, placeholder: "Your message..." %> <%= f.submit "Send" %> <% end %> ``` ### Broadcasting Baep Asinkronat samrap Kan Tham Ngan Nak Phue likliang kan blok request, broadcasting samat tham dai nai baenglang. ```ruby # app/models/report.rb class Report < ApplicationRecord belongs_to :user after_create_commit :generate_async private def generate_async GenerateReportJob.perform_later(self) end end ``` ```ruby # app/jobs/generate_report_job.rb class GenerateReportJob < ApplicationJob queue_as :default def perform(report) # Simulating a long operation report.update!(status: "processing") # Notify user of start report.broadcast_replace_to( report.user, :reports, target: dom_id(report), partial: "reports/report" ) # Generate the report result = ReportGenerator.new(report).generate report.update!(content: result, status: "completed") # Notify user of completion report.broadcast_replace_to( report.user, :reports, target: dom_id(report), partial: "reports/report" ) end end ``` ## Ruepbaep Kanchai Ngan Khansungsamrap Turbo ### Kan Kaekhai Baep Inline Ruepbaeb thi phop boi kiao kap kan thaenthi nueaha thi khong mi kan plianplaeng duai baep kaekhai inline. ```erb
<%= task.content %>
<%= link_to "Edit", edit_task_path(task) %> <%= button_to "Delete", task_path(task), method: :delete, data: { turbo_confirm: "Delete this task?" } %>
``` ```erb <%= form_with model: @task do |f| %> <%= f.text_field :content, autofocus: true %>
<%= f.submit "Save" %> <%= link_to "Cancel", task_path(@task) %>
<% end %>
``` ### Naewithang Nok Frame Lak Doi kahamnot, link nai frame cha yu nai frame nan. Atthribut `data-turbo-frame` anuyat hai jaomung pai frame uen rue thang phaena. ```erb ``` ```erb
<%= yield %>
``` > **Kan Daebaek Turbo** > > Nai sapha waetlaom kan phatthana, poet JavaScript console lae phim `Turbo.setProgressBarDelay(0)` phue hen thaeang khwam khaonah thanthi. `Turbo.session.drive = false` pit Turbo Drive chuakhrao. ## Kan Chatkan Khophitphlat lae Sathana Kamlang Lot UX thi di tong kan kan chatkan sathana kamlang lot lae khophitphlat khruekhai. ```erb <%= form_with model: @model, data: { controller: "form-loading", action: "turbo:submit-start->form-loading#disable turbo:submit-end->form-loading#enable" } do |f| %> <%= yield f %> <% end %> ``` ```javascript // app/javascript/controllers/form_loading_controller.js import { Controller } from "@hotwired/stimulus" export default class extends Controller { static targets = ["submit", "text", "spinner"] disable() { this.submitTarget.disabled = true this.textTarget.classList.add("hidden") this.spinnerTarget.classList.remove("hidden") } enable() { this.submitTarget.disabled = false this.textTarget.classList.remove("hidden") this.spinnerTarget.classList.add("hidden") } } ``` ### Kan Chatkan Khophitphlat Soewoe ```ruby # app/controllers/application_controller.rb class ApplicationController < ActionController::Base rescue_from ActiveRecord::RecordNotFound do |exception| respond_to do |format| format.turbo_stream do render turbo_stream: turbo_stream.replace( "main_content", partial: "shared/not_found" ) end format.html { render "errors/not_found", status: :not_found } end end end ``` ## Kan Prapprung Prasiththiphap Lai thekhnik raprong aepplikheishan Turbo thi mi prasiththiphap. ```ruby # app/controllers/messages_controller.rb class MessagesController < ApplicationController # Avoid N+1 queries with eager loading def index @messages = Message.includes(:author, :room) .order(created_at: :desc) .page(params[:page]) end # Fragment caching for static elements def show @message = Message.find(params[:id]) fresh_when @message end end ``` ```erb <% cache message do %>
<%= message.content %> By <%= message.author.name %>
<% end %> ``` ## Srupphon Hotwire lae Turbo plianplaeng kan phatthana Rails doi kan loet khwam sapson khong framework JavaScript daengdoem. Turbo Drive reng khwam reo kan naewithang, Turbo Frames anuyat kan kapnhat baep jaomung, lae Turbo Streams sanoe khwam samat raiaethaim thi trongklang. ### Raikantruatsop samrap Roem Ton kap Hotwire - Chai Rails 7+ samrap kan ruam Hotwire thi mi ma hai - Khaojai sam ongprakop: Drive, Frames lae Streams - Rabu son khong phaena thi dai rap phon prayot chak Turbo Frames - Chai `respond_to` kap `format.turbo_stream` nai khonthrolen - Nammaj broadcasting samrap ficoer raiaethaim - Ruam kap Stimulus samrap kan toptoep JavaScript thi ngai Withikan "HTML phan sai" ni anuyat hai sang aepplikheishan thi than samai lae mi kan toptoep khana thi rak sa khwam ngai lae phon phlit thi thamhai Ruby on Rails mi phalang makkhana. Phonlap: khot thi tong dulae noi long, prasiththiphap thi yiam yot lae prasopkan nak phatthana thi di thi sut. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/th/blog/ruby-on-rails/ruby-on-rails-7-hotwire-turbo