Pre-order

Turbo Streams

Render updates to Turbo pages with Phlex components by way of Turbo Streams.

Before Phlex, Turbo Streams in Rails were a combination of view templates that …

class MessagesController < ApplicationController
  def create
    @message = Message.create!(params.require(:message).permit(:content))
    respond_to do |format|
      format.turbo_stream
      format.html { redirect_to messages_url }
    end
  end
end

Then the views would handle the actions performed by the streams:

<%# app/views/messages/create.turbo_stream.erb %>
<%= turbo_stream.append "messages", @message %>

<%= turbo_stream.replace "new_message" do %>
  <%= render partial: "new_message", locals: { room: @room } %>
<% end %>

How do we achieve the same functionality with Phlex?

Implement Turbo Streams with Phlex

🔓 Unlock content

Pre-order this course to unlock this video, source code, and content.

Pre-order video course for $379 $249

▓▓▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓ ▓▓▓▓▓▓▓▓▓ ▓▓ ▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓ ▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓ ▓ ▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓ ▓▓▓▓ ▓▓▓▓▓▓▓▓▓ ▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓▓

▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
class Component::TurboStream < ▓▓▓▓▓::▓▓▓▓
  ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ :turbo_stream

  def ▓▓▓▓▓▓▓▓▓▓▓▓▓▓
    yield self
  end

  def ▓▓▓▓▓▓(▓▓▓▓▓▓, ▓▓▓▓▓▓▓▓▓)
    ▓▓▓▓▓▓▓▓▓▓▓▓(action: "append", ▓▓▓▓▓▓:) do
      ▓▓▓▓▓▓▓▓ do
        ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓
      end
    end
  end

  def ▓▓▓▓▓▓▓(▓▓▓▓▓▓, ▓▓▓▓▓▓▓▓▓)
    ▓▓▓▓▓▓▓▓▓▓▓▓(action: "replace", ▓▓▓▓▓▓:) do
      ▓▓▓▓▓▓▓▓ do
        ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓
      end
    end
  end

  ▓ ▓▓▓
end

▓▓▓ ▓▓▓▓ ▓▓ ▓▓▓▓ ▓▓▓ ▓▓▓▓▓ ▓▓ ▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓ ▓▓▓▓▓ ▓▓▓▓ ▓ ▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓

Streaming directly from the controller

▓▓▓▓▓▓ ▓▓▓▓ ▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓ ▓▓▓▓ ▓▓▓▓▓▓▓▓▓ ▓▓ ▓ ▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓ ▓▓ ▓▓ ▓ ▓▓▓▓▓ ▓▓▓▓▓▓▓

class CommentsController < ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  ▓▓▓▓▓▓▓▓▓▓▓▓▓ { ▓▓▓▓▓▓▓▓▓ = ▓▓▓▓▓▓▓.▓▓▓ }

  def ▓▓▓▓▓
    ▓▓▓▓▓▓ ▓▓▓▓::▓▓▓▓▓▓▓▓::▓▓▓▓▓.▓▓▓(▓▓▓▓▓▓▓▓▓)
  end

  def ▓▓▓▓▓▓
    ▓▓▓▓▓▓▓▓▓▓ do |format|
      format.▓▓▓▓ { ▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ }
      format.▓▓▓▓▓▓▓▓▓▓▓▓ do
        ▓▓▓▓▓▓ do
          ▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓
          ▓▓.▓▓▓▓▓▓ "comments", ▓▓▓▓::▓▓▓▓▓▓▓▓::▓▓▓▓.▓▓▓(▓▓▓▓▓▓▓▓)

          ▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓
          ▓   ▓▓▓ ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓ ▓ ▓▓▓▓▓ ▓▓▓▓▓ ▓ ▓▓
          ▓ ▓▓ ▓▓▓ ▓▓
          ▓▓.▓▓▓▓▓▓▓ "new_comment", ▓▓▓▓::▓▓▓▓▓▓▓▓::▓▓▓▓.▓▓▓(▓▓▓▓▓▓▓▓)
        end
      end
    end
  end

  private

  def ▓▓▓▓▓▓(&)
    ▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓::▓▓▓▓▓▓▓▓▓▓▓.▓▓▓(&)
  end
end

Streaming from a view

▓▓▓▓▓ ▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓ ▓ ▓▓▓▓▓▓▓ ▓▓▓▓ ▓▓▓▓ ▓▓▓▓▓▓▓ ▓▓▓▓▓ ▓▓ ▓▓▓▓▓ ▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓ ▓▓▓▓ ▓▓ ▓ ▓▓▓▓ ▓▓▓▓▓

▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
class View::Comments::TurboStream::Create < ▓▓▓▓▓▓▓▓▓::▓▓▓▓▓▓▓▓▓▓▓
  def ▓▓▓▓▓▓▓▓▓▓(▓▓▓▓▓▓▓)
    ▓▓▓▓▓▓▓▓ = ▓▓▓▓▓▓▓
  end

  def ▓▓▓▓▓▓▓▓
    ▓▓▓▓▓▓ "comments", ▓▓▓▓::▓▓▓▓▓▓▓▓::▓▓▓▓.▓▓▓(▓▓▓▓▓▓▓▓)
    ▓▓▓▓▓▓▓ "new_comment", ▓▓▓▓::▓▓▓▓▓▓▓▓::▓▓▓▓.▓▓▓(▓▓▓▓▓▓▓▓)
  end
end

▓▓▓▓▓ ▓▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓

class CommentsController < ▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓
  ▓▓▓▓▓▓▓▓▓▓▓▓▓ { ▓▓▓▓▓▓▓▓▓ = ▓▓▓▓▓▓▓.▓▓▓ }

  def ▓▓▓▓▓
    ▓▓▓▓▓▓ ▓▓▓▓::▓▓▓▓▓▓▓▓::▓▓▓▓▓.▓▓▓(▓▓▓▓▓▓▓▓▓)
  end

  def ▓▓▓▓▓▓
    ▓▓▓▓▓▓▓▓▓▓ do |format|
      format.▓▓▓▓ { ▓▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓▓▓▓ }
      format.▓▓▓▓▓▓▓▓▓▓▓▓ { ▓▓▓▓▓▓ ▓▓▓▓::▓▓▓▓▓▓▓▓::▓▓▓▓▓▓▓▓▓▓▓::▓▓▓▓▓▓.▓▓▓(▓▓▓▓▓▓▓▓) }
    end
  end
end