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:
- Updates the lunch attendance record for that specific colleague for the current day in the database.
- 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.