erb

erb
<h1>Products</h1>

<%= link_to "New product", new_product_path, data: { turbo_frame: "modal" }, class: "btn" %>

<table id="products">
  <tbody>

Turbo Frame modal that renders server HTML

rails hotwire turbo
by codesnips 4 tabs
erb
<h1><%= @post.title %></h1>
<p><%= @post.author_name %></p>

<%# Only sanitized rich text should be rendered as HTML %>
<div class="prose"><%= sanitize(@post.body_html, tags: %w[p a ul ol li strong em code], attributes: %w[href]) %></div>

Cross site scripting defense with output encoding and CSP

xss content-security-policy owasp
by Kai Nakamura 3 tabs
ruby
class AdminController < ApplicationController
  before_action :authenticate_admin!
  before_action :disable_turbo_cache, only: %i[dashboard moderation_queue]

  helper_method :turbo_cache_control_tag

Turbo Drive: disable caching on volatile admin pages

rails turbo hotwire
by codesnips 3 tabs
erb
<%= form_with model: @document, data: { controller: "upload" } do |form| %>
  <div class="field">
    <%= form.label :file, "Attach a document" %>
    <%= form.file_field :file,
          direct_upload: true,
          data: { upload_target: "input" } %>

Active Storage direct upload progress with Stimulus

rails hotwire stimulus
by codesnips 3 tabs
ruby
class Document < ApplicationRecord
  belongs_to :account

  enum status: { pending: 0, processing: 1, ready: 2, failed: 3 }

  after_create_commit :broadcast_badge

Broadcast a status badge update on background processing

rails hotwire turbo
by codesnips 4 tabs
javascript
import { Controller } from "@hotwired/stimulus"

export default class extends Controller {
  static targets = ["input"]
  static values = { wait: { type: Number, default: 300 }, url: String }

Stimulus: debounced search that plays nicely with Turbo

rails stimulus hotwire
by codesnips 3 tabs
erb
<nav id="main-navbar"
     data-turbo-permanent
     data-controller="navbar"
     data-navbar-menu-open-value="false"
     class="navbar">
  <div class="navbar-inner">

Keep navbar state across Turbo navigations with data-turbo-permanent

rails hotwire turbo
by codesnips 3 tabs
erb
<%= turbo_stream_from :comments %>

<section class="comments">
  <h2>Discussion</h2>

  <%= turbo_frame_tag "new_comment" do %>

Inline create form that prepends into a list with Turbo Streams

rails hotwire turbo
by codesnips 4 tabs
ruby
class CommentsController < ApplicationController
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.build(comment_params)
    @comment.author = current_user

Turbo Streams for real-time list updates

hotwire turbo turbo-streams
by Jordan Lee 2 tabs
erb
<div class="layout" data-controller="sidebar">
  <aside class="sidebar">
    <%= render "shared/sidebar", active: params[:controller] %>
  </aside>

  <main class="content-area">

Scoped navigation inside a sidebar with Turbo Frames

rails hotwire turbo
by codesnips 4 tabs
erb
<div class="orders-layout" data-controller="drawer">
  <table class="orders">
    <tbody>
      <% @orders.each do |order| %>
        <tr>
          <td><%= order.reference %></td>

Turbo Frames: inline “details drawer” without a SPA router

rails hotwire turbo
by codesnips 4 tabs
ruby
class CommentsChannel < ApplicationCable::Channel
  def subscribed
    post = find_post
    if post
      stream_for post
    else

Broadcasting New Comments to Subscribers over an ActionCable Channel

rails actioncable websockets
by codesnips 4 tabs