Turbo Streams for real-time list updates

Jordan Lee Jan 2026
2 tabs
class CommentsController < ApplicationController
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.build(comment_params)
    @comment.author = current_user

    if @comment.save
      respond_to do |format|
        format.turbo_stream do
          render turbo_stream: [
            turbo_stream.append("comments", partial: "comments/comment", locals: { comment: @comment }),
            turbo_stream.update("comment_count", html: "#{@post.comments.count} comments"),
            turbo_stream.replace("new_comment", partial: "comments/form", locals: { post: @post, comment: Comment.new })
          ]
        end
        format.html { redirect_to @post }
      end
    else
      render :new, status: :unprocessable_entity
    end
  end

  private

  def comment_params
    params.require(:comment).permit(:body)
  end
end
2 files · ruby, erb Explain with highlit

Turbo Streams enable surgical DOM updates from the server without writing JavaScript. After a successful form submission, instead of redirecting, I return a Turbo Stream response that appends, prepends, replaces, or removes specific elements. This is perfect for creating items in lists, updating counters, or showing flash messages. Combined with Action Cable, Turbo Streams power real-time collaborative features—when one user creates a comment, all viewers see it instantly via a broadcast. The seven stream actions (append, prepend, replace, update, remove, before, after) cover most UI update patterns. I use the turbo_stream_from helper to subscribe to broadcast channels and turbo_stream.append in controllers to generate the response.