Belajar Ruby on Rails - Views & Action View
Episode 7 of 27

Belajar Ruby on Rails - Views & Action View

Membedah Action View: template ERB, partials yang bisa dipakai ulang, helpers untuk merapikan tampilan, layouts sebagai kerangka halaman, dan Hotwire (Turbo Frames & Turbo Streams) untuk UI interaktif tanpa build JS berat

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Setelah di episode 5 dan 6 kalian menguasai sisi data (Active Record & migrations), episode 7 berpindah ke lapisan paling dekat dengan pengguna: views dan Action View. Di sinilah data dari controller diubah menjadi HTML yang benar-benar dilihat user.

Mengapa views penting dikuasai dalam? Karena pengguna tidak pernah melihat model atau controller — yang mereka lihat adalah view. Dan di era Rails 8, view bukan sekadar HTML statis: dengan Hotwire (Turbo + Stimulus), kalian bisa membangun UI interaktif tanpa menulis satu baris JavaScript bundling. Episode ini membekali kalian fondasi template yang menjadi dasar semua episode UI berikutnya.

ERB: Template Rails

Views Rails ditulis dalam ERB (Embedded Ruby) — HTML dengan potongan Ruby di dalam <% %>:

HTMLapp/views/posts/index.html.erb
<h1>Daftar Post</h1>
 
<% @posts.each do |post| %>
  <article>
    <h2><%= link_to post.title, post %></h2>
    <p><%= truncate(post.body, length: 120) %></p>
    <small>Oleh <%= post.user.name %> · <%= time_ago_in_words(post.created_at) %></small>
  </article>
<% end %>

Dua jenis tag utama:

  • <% %> — menjalankan Ruby tanpa output (loop, if).
  • <%= %> — menjalankan Ruby dan menampilkan hasilnya.

Escape otomatis adalah fitur keamanan terpenting ERB: semua output <%= %> di-escape HTML secara default, sehingga serangan XSS lewat post.body otomatis diblokir (dibahas penuh di episode 18).

Partials: Potongan yang Dipakai Ulang

Kode view yang berulang dipindah ke partial — file dimulai dengan underscore:

HTMLapp/views/posts/_post.html.erb
<article>
  <h2><%= link_to post.title, post %></h2>
  <p><%= truncate(post.body, length: 120) %></p>
  <small>Oleh <%= post.user.name %></small>
</article>

Lalu dirender dari view lain:

HTMLRender partial dengan koleksi
<%= render partial: "post", collection: @posts, as: :post %>

Partial menangani loop sendiri: <%= render @posts %> otomatis me-render _post.html.erb untuk tiap elemen. Partial memakai variabel lokal (post) bukan instance variable — lebih aman dan lebih reusable.

Helpers: Merapikan Logika Tampilan

Helper adalah method Ruby yang membantu view. Bawaan Rails sudah banyak: link_to, truncate, time_ago_in_words, number_to_currency, pluralize. Helper custom ditulis di app/helpers/:

Rubyapp/helpers/posts_helper.rb
module PostsHelper
  def status_badge(post)
    if post.published?
      content_tag(:span, "Published", class: "badge badge-success")
    else
      content_tag(:span, "Draft", class: "badge badge-muted")
    end
  end
end

Dipakai di view: <%= status_badge(post) %>. Prinsipnya: logika tampilan di helper, data di model. Jika logika menyangkut aturan bisnis, letakkan di model, bukan helper.

Layouts: Kerangka Semua Halaman

Layout adalah template pembungkus seluruh halaman. Defaultnya app/views/layouts/application.html.erb:

HTMLapp/views/layouts/application.html.erb
<!DOCTYPE html>
<html>
  <head>
    <title>Blog</title>
    <%= csrf_meta_tags %>
    <%= csp_meta_tag %>
    <%= stylesheet_link_tag "application", "data-turbo-track": "reload" %>
  </head>
  <body>
    <%= render "layouts/navbar" %>
    <main class="container">
      <% flash.each do |type, msg| %>
        <%= content_tag :div, msg, class: "flash #{type}" %>
      <% end %>
      <%= yield %>
    </main>
  </body>
</html>

<%= yield %> adalah titik tempat template action disuntikkan. Flash dari episode 4 dirender di sini agar tampil di semua halaman. Layout khusus (misal layouts/admin) bisa dipilih via layout method di controller.

Hotwire: Turbo Frames & Turbo Streams

Rails 8 memakai Hotwire — Turbo + Stimulus — sebagai cara default membangun interaktivitas tanpa menulis JavaScript framework. Prinsipnya: server mengirim HTML, Turbo menukar bagian halaman secara asinkron.

Turbo Frames

Turbo Frame membatasi area halaman yang di-update:

HTMLTurbo Frame untuk form komentar
<turbo-frame id="comments">
  <% @post.comments.each do |comment| %>
    <p><%= comment.body %></p>
  <% end %>
</turbo-frame>

Ketika request berasal dari dalam frame (misal submit form komentar), Turbo hanya mengganti isi frame itu — bukan seluruh halaman. Hasilnya terasa seperti SPA tanpa JavaScript manual.

Turbo Streams

Turbo Streams adalah format respons untuk update realtime — dikirim sebagai text/vnd.turbo-stream.html:

RubyController dengan Turbo Stream
def create
  @comment = @post.comments.new(comment_params)
 
  if @comment.save
    respond_to do |format|
      format.turbo_stream { render turbo_stream: turbo_stream.append("comments", @comment) }
      format.html { redirect_to @post }
    end
  end
end

turbo_stream.append("comments", @comment) menyuruh Turbo menambahkan _comment.html.erb ke akhir elemen dengan id comments — tanpa reload. Di episode 14, Turbo Streams dikombinasikan dengan Action Cable untuk realtime penuh.

Note

Stimulus (bagian Hotwire) dipakai untuk perilaku JavaScript kecil yang scoped — misal toggle tampil/sembunyi atau fetch sederhana. Stimulus bukan pengganti Turbo: Turbo menangani update HTML, Stimulus menangani interaksi spesifik. Kombinasinya membuat banyak UI tanpa React/Vue.

Common Pitfalls

  • Instance variable dipakai tanpa nil-guard@post bisa nil; gunakan helper atau pastikan controller selalu mengaturnya. Lebih rapi: terima data lewat partial lokal.
  • Helper berisi query database — misal current_user.posts.count di dalam helper. Ini merusak pemisahan concern dan bisa memicu N+1. Query di model/controller, helper hanya menampilkan.
  • Menaruh logika kondisional panjang di view — pindahkan ke partial + helper, atau gunakan render dengan pilihan partial.
  • Lupa data-turbo-track: "reload" — asset stale; sambungan CSS/JS tak ter-update saat reload.
  • Menulis JS besar-besaran untuk interaktivitas sederhana — mulai dari Turbo Frames dulu; JS hanya untuk yang benar-benar perlu.

Penutup

Episode 7 membekali kalian Action View: ERB dengan escaping otomatis, partial untuk kode reusable, helpers untuk merapikan logika tampilan, layouts sebagai kerangka halaman, dan Hotwire — Turbo Frames untuk update terbatas serta Turbo Streams untuk update asinkron tanpa reload.

Inti yang harus dibawa pulang:

  • ERB: <% %> tanpa output, <%= %> dengan output; escaping otomatis anti-XSS.
  • Partials (_post.html.erb) dipakai ulang via render @posts.
  • Helpers menampung logika tampilan; model menampung logika bisnis.
  • Layout membungkus semua halaman; <%= yield %> adalah titik injeksi.
  • Hotwire: Turbo Frames untuk area terbatas, Turbo Streams untuk update realtime.

Di episode 8 selanjutnya kita akan membedah forms & strong parametersform_with, nested forms, dan file upload, plus permit/require dan perlindungan mass assignment. Sampai jumpa di episode 8!

Belajar Ruby on Rails - Views & Action View | Belajar Ruby on Rails