Skip to content
Contact us Find a job at Sping

Using Turbo Streams to Build a Realtime Lunch Attendance App

Published:

Here at Sping, we recently embarked on a project to simplify our office manager’s life – a lunch attendance tracker! This seemingly simple tool turned into a valuable learning experience when we implemented it using Ruby on Rails and Hotwire Turbo Streams.

Building a Realtime Attendance System

Our goal was to create a system where the office manager could track lunch attendance in real-time. Traditionally, this might involve a static web page that required manual refreshes to see updates. But with Turbo Streams, we could achieve a more dynamic experience.

The Input Page and Turbo Stream Updates

We started by building an input page listing all our colleagues. Each name would act as a button. Clicking a button would trigger an action that:

  1. Updates the lunch attendance record for that specific colleague for the current day in the database.
  2. Uses Turbo Streams to send a partial update to the browser. This update could be a simple message confirming attendance or a visual change highlighting the attended colleague’s name.

Code Example

Implementation details will depend on your specific project setup.

# In your controller (controllers/people_controller.rb)

def check
   person = Person.find(params[:id])
   date = params[:date].present? ? params[:date] : Time.current._to_date
   checked = person.checks.find_by(checked_at: date)
   if checked
     checked.destroy!
   else
     person.checks.create!(checked_at: date)
   end
   respond_to do |format|
     format.turbo_stream do
       render turbo_stream: [
         turbo_stream.replace(person),
       ]
     end
     format.html { redirect_to root_path }
   end
end

# In your view (views/pages/home.html.erb)
...
<div class="flex flex-wrap justify-center font-medium text-xl">
 <%= render @people %>
</div>
...

# In your view partial (views/people/_person.html.erb)

<%= turbo_frame_tag person do %>
 <%
   cls = 'btn m-2'
   cls += person.checks.select { |c| c.checked_at == Date.current }.any? ? ' btn-active' : ''
 %>
 <%= button_to person.name, check_path(person), method: :post, class: "#{cls}" %>
<% end %>

Realtime Updates with Turbo Streams

The magic happens with Turbo Streams. Since other browsers using the application establish a web socket connection, any update to the database is automatically broadcasted to all connected clients. This means that colleagues checking the attendance list will see the update reflected on their screen almost instantly, without needing to manually refresh the page.

Extending to an Overview Page

We didn’t stop there. We built a separate overview page displaying the weekly attendance for all colleagues. Similar to the input page, users could update their own attendance on this page. Once again, Turbo Streams handled the real-time updates, reflecting changes on all connected browser windows.

Turbo Streams: A Game Changer for Ruby on Rails

This project served as a valuable learning experience for us. It demonstrated the power of Turbo Streams in creating semi-dynamic web pages that would traditionally require Javascript frameworks. This opens the door to potentially using Ruby on Rails as a full-stack framework again, even for applications requiring a more interactive and real-time experience. Previously, such scenarios might have necessitated building a separate front-end web app.

Moving Forward

We’re excited about the possibilities that Turbo Streams unlocks for future development. It allows us to leverage the strengths of Ruby on Rails while still delivering a user experience that feels modern and dynamic. We’re eager to explore further use cases for Turbo Streams and see how it can streamline our development process.