# Ruby on Rails 7: Reaktif Uygulamalar icin Hotwire ve Turbo > Rails 7'de Hotwire ve Turbo icin kapsamli rehber. Turbo Drive, Frames ve Streams ile JavaScript yazmadan reaktif uygulamalar gelistirme. - 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, Hotwire'i varsayilan olarak entegre ederek web gelistirmeyi devrimlestirildi. Bu stack, tek bir satir ozel JavaScript yazmadan son derece reaktif uygulamalar olusturmayi mumkun kiliyor. Turbo Drive, Turbo Frames ve Turbo Streams, geleneksel SPA yaklasimlarini "kablo uzerinden HTML" felsefesiyle degistiriyor. > **Neden Hotwire?** > > Hotwire, frontend karmasikligini onemli olcude azaltir. Dinamik arayuzler icin React veya Vue gerekmez: sunucu kullanima hazir HTML gonderir ve Turbo, DOM guncellemelerini otomatik olarak yonetir. ## Hotwire Mimarisini Anlamak Hotwire, tipik JavaScript framework karmasikligi olmadan akici bir kullanici deneyimi sunmak icin birlikte calisan uc tamamlayici teknolojiden olusur. **Turbo Drive**, baglanti tiklamalarini ve form gonderimlerini yakalayarak gezinmeyi hizlandirir. Sayfanin tamami yeniden yuklenmek yerine, yalnizca `` icerigi degistirilir ve JavaScript ile CSS baglami korunur. **Turbo Frames**, sayfalari bagimsiz bolumlere ayirir. Her frame ayri ayri guncellenebilir, bu da sayfanin geri kalanini etkilemeden hedefli etkilesimlere olanak tanir. **Turbo Streams**, WebSocket uzerinden veya HTTP isteklerine yanit olarak gercek zamanli guncellemeler saglar. Bildirimsel DOM manipulasyonu icin sekiz CRUD eylemi mevcuttur. ```ruby # Gemfile # Installing Turbo Rails (included by default in Rails 7+) gem 'turbo-rails' ``` Mevcut projeler icin kurulum yalnizca bir komut gerektirir. ```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" ``` ## Turbo Drive Baslangic Yapilandirmasi Turbo Drive, Rails 7'de varsayilan olarak etkindir. Tum gezinme ek yapilandirma olmadan otomatik olarak "turbo" haline gelir. Davranis, data ozellikleri araciligiyla ozellestirilebilir. ```erb <%= csrf_meta_tags %> <%= csp_meta_tag %> <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %> <%= javascript_importmap_tags %>
<%= yield %> ``` Turbo Drive, gerektiginde belirli baglantilar veya formlar icin devre disi birakilabilir. ```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?" } %> ``` > **Turbo Drive Onbellegi** > > Turbo Drive ziyaret edilen sayfalari onbellegine alir. Varliklardaki `data-turbo-track="reload"` ozelligi, CSS/JS dosyalari degistiginde tam bir yeniden yuklemeyi zorlar. ## Hedefli Guncellemeler icin Turbo Frames Turbo Frames, bagimsiz olarak guncellenen sayfa bolgeleri tanimlar. Her frame benzersiz bir tanimlayiciya sahiptir ve yalnizca eslesen bir frame iceren yanitlara yanit verir. ```erb

Messages

<%= render @messages %>
<%= link_to "Load more", messages_path(page: @next_page) %>
<%= render "form", message: Message.new %> ``` Sunucu yaniti, guncellemenin calismasi icin ayni tanimlayiciya sahip bir frame icermelidir. ```erb

<%= message.content %>

<%= link_to "Edit", edit_message_path(message) %> <%= button_to "Delete", message_path(message), method: :delete %>
``` ### Turbo Frames ile Lazy Loading Frameler, `src` ozelligi kullanilarak iceriklerini asenkron olarak yukleyebilir. Yukleme sirasinda ilk icerik goruntulenir. ```erb

Dashboard

Loading statistics...

Loading notifications...

<%= render "activity/placeholder" %> ``` Denetleyici, yalnizca istenen frame'i iceren bir gorunumle yanit verir. ```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

``` ## Gercek Zamanli Guncellemeler icin Turbo Streams Turbo Streams, DOM manipulasyonu icin sekiz eylem sunar: `append`, `prepend`, `replace`, `update`, `remove`, `before`, `after` ve `morph`. Bu eylemler HTTP yaniti veya WebSocket araciligiyla tetiklenebilir. ```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 ``` ### Ozel Turbo Stream Sablonlari Daha karmasik yanitlar icin `.turbo_stream.erb` sablonu daha fazla esneklik sunar. ```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 %> ``` > **Yanit Formati** > > Turbo Stream yanitlari `text/vnd.turbo-stream.html` content-type'ina sahip olmalidir. Rails bunu `respond_to` ve `turbo_stream` formati ile otomatik olarak yonetir. ## Action Cable ile Gercek Zamanli Broadcasting Turbo Streams, WebSocket broadcasting ile gercek gucunu gosterir. Kullanicilar polling olmadan aninda guncellemeler alir. ```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 ``` Gorunum, `turbo_stream_from` helper'i ile ilgili stream'e abone olur. ```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 %> ``` ### Agir Islemler icin Asenkron Broadcasting Istekleri engellemekten kacinmak icin broadcasting arka planda gerceklestirilebilir. ```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 ``` ## Turbo ile Ileri Duzey Kaliplar ### Satir Ici Form Duzenleme Yaygin bir kalip, statik icerigi satir ici duzenleme formuyla degistirmeyi icerir. ```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 %>
``` ### Ust Frame Disinda Gezinme Varsayilan olarak, bir frame'deki baglantilar o frame icinde kalir. `data-turbo-frame` ozelligi, baska bir frame'i veya tum sayfayi hedeflemeyi saglar. ```erb ``` ```erb
<%= yield %>
``` > **Turbo Hata Ayiklama** > > Gelistirme ortaminda JavaScript konsolunu acip `Turbo.setProgressBarDelay(0)` yazarak ilerleme cubugunu hemen gorebilirsiniz. `Turbo.session.drive = false` Turbo Drive'i gecici olarak devre disi birakir. ## Hata Yonetimi ve Yukleme Durumlari Iyi bir UX, yukleme durumlarinin ve ag hatalarinin yonetilmesini gerektirir. ```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") } } ``` ### Sunucu Hatasi Yonetimi ```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 ``` ## Performans Optimizasyonu Birkac teknik, performansli Turbo uygulamalari saglar. ```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 %> ``` ## Sonuc Hotwire ve Turbo, geleneksel JavaScript frameworklerinin karmasikligini ortadan kaldirarak Rails gelistirmeyi donusturuyor. Turbo Drive gezinmeyi hizlandirir, Turbo Frames hedefli guncellemelere olanak tanir ve Turbo Streams guclu gercek zamanli yetenekler sunar. ### Hotwire ile Baslama Kontrol Listesi - Dahili Hotwire entegrasyonu icin Rails 7+ kullanmak - Uc bileseni anlamak: Drive, Frames ve Streams - Turbo Frames'ten fayda saglayacak sayfa bolgelerini belirlemek - Denetleyicilerde `respond_to` ile `format.turbo_stream` kullanmak - Gercek zamanli ozellikler icin broadcasting uygulamak - Basit JavaScript etkilesimleri icin Stimulus ile birlestirmek Bu "kablo uzerinden HTML" yaklasimi, Ruby on Rails'i bu kadar guclu kilan basitligi ve uretkenliyi koruyarak modern, reaktif uygulamalar olusturmayi mumkun kilar. Sonuc: daha az bakim gerektiren kod, mukemmel performans ve optimal bir gelistirici deneyimi. --- Source: SharpSkill (https://sharpskill.dev), tech interview preparation for your real stack. HTML version of this page: https://sharpskill.dev/tr/blog/ruby-on-rails/ruby-on-rails-7-hotwire-turbo