Skip to content

Instantly share code, notes, and snippets.

@coolprobn
Created November 6, 2025 07:25
Show Gist options
  • Select an option

  • Save coolprobn/8bc33f8bfda9c119cdb4cdb32a6037df to your computer and use it in GitHub Desktop.

Select an option

Save coolprobn/8bc33f8bfda9c119cdb4cdb32a6037df to your computer and use it in GitHub Desktop.
Show live progress in Rails with Turbo Stream and Background Job
<!--app/views/progress_demo/_progress_bar.html.erb-->
<%
# Determine color based on progress
color_class = case progress
when 0..30
"bg-error"
when 31..70
"bg-warning"
when 71..99
"bg-info"
else
"bg-success"
end
%>
<%= turbo_frame_tag "progress_bar" do %>
<div class="w-full">
<div class="flex justify-between items-center mb-2">
<span class="text-sm font-medium">Progress</span>
<span class="text-sm font-medium"><%= progress %>%</span>
</div>
<div class="w-full bg-base-300 rounded-full h-4 overflow-hidden">
<div
class="h-4 rounded-full transition-all duration-300 <%= color_class %>"
style="width: <%= progress %>%"
></div>
</div>
<% if progress == 100 %>
<p class="text-sm text-success mt-2 font-medium">✓ Task completed!</p>
<% end %>
</div>
<% end%>
# app/controllers/progress_demo_controller.rb
class ProgressDemoController < ApplicationController
def show
@job_id = SecureRandom.uuid
end
def start
ProgressJob.perform_later(params[:job_id])
head :ok
end
end
# app/jobs/progress_job.rb
class ProgressJob < ApplicationJob
def perform(job_id)
total_steps = 100
total_steps.times do |current_step|
progress = current_step + 1
percentage = (progress.to_f / total_steps * 100).round
Turbo::StreamsChannel.broadcast_replace_to(
"progress_#{job_id}",
target: "progress_bar",
partial: "progress_demo/progress_bar",
locals: {
progress: percentage
}
)
sleep 0.1 # Simulate work
end
end
end
# config/routes.rb
Rails.application.routes.draw do
# Progress demo for Turbo Streams example
get "/progress_demo", to: "progress_demo#show", as: :progress_demo
post "/progress_demo/start/:job_id", to: "progress_demo#start", as: :progress_demo_start
end
<!--app/views/progress_demo/show.html.erb-->
<%= turbo_stream_from "progress_#{@job_id}" %>
<div class="max-w-2xl mx-auto mt-8">
<h1 class="text-3xl font-bold mb-6">Live Progress Demo</h1>
<div class="bg-base-200 rounded-lg p-6 shadow-lg">
<div class="mb-4">
<h2 class="text-xl font-semibold mb-2">Task Progress</h2>
<p class="text-sm text-base-content/70">Click the button below to start a simulated task with live progress updates.</p>
</div>
<%= render partial: "progress_demo/progress_bar", locals: { progress: 0 } %>
<div class="mt-6">
<%= button_to "Start Task",
progress_demo_start_path(job_id: @job_id),
method: :post,
class: "btn btn-primary" %>
</div>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment