ruby on rails, real-time applications, web development, live streaming, backend development,

Real-Time Streaming with Ruby on Rails: A Step-by-Step Guide

Sebastian Schkudlara Sebastian Schkudlara Follow May 22, 2024 · 3 mins read
Real-Time Streaming with Ruby on Rails: A Step-by-Step Guide
Share this

Real-Time Streaming with Ruby on Rails: A Step-by-Step Guide

In today’s fast-paced digital world, real-time updates are becoming increasingly essential. Whether you’re building a live chat application, a stock ticker, or any feature that benefits from instant updates, streaming responses can significantly enhance the user experience. In this article, we’ll explore how to implement streaming responses in a Ruby on Rails application.

Why Streaming?

Streaming allows your server to push updates to the client as soon as they happen, without the need for the client to continuously poll the server for new data. This results in more efficient resource usage and a smoother user experience.

Setting Up Streaming in Rails

To illustrate how to set up streaming in Rails, we’ll walk through a simplified example. We’ll create a MessagesController that handles both standard and streaming responses.

Step 1: Include ActionController::Live

First, include ActionController::Live in your controller. This module provides the necessary functionality for streaming responses.

class MessagesController < ApplicationController
  include ActionController::Live

  def create
    params = message_params
    prompt = params[:prompt]
    stream = params[:stream] == 'true'

    if stream
      handle_streaming_response(prompt)
    else
      handle_standard_response(prompt)
    end
  end

  private

  def message_params
    params.require(:message).permit(:prompt, :stream)
  end
end

Step 2: Handling Streaming Responses

In the handle_streaming_response method, we set the Content-Type header to text/event-stream and initialize an SSE (Server-Sent Events) object. We then call our service to handle the streaming.

def handle_streaming_response(prompt)
  response.headers['Content-Type'] = 'text/event-stream'
  sse = SSE.new(response.stream, retry: 300, event: 'open')

  begin
    GatewayService.new(prompt: prompt, stream: true).call do |chunk|
      sse.write(chunk, event: 'response')
    end
  rescue StandardError => e
    Rails.logger.error "Error during streaming: #{e.message}"
  ensure
    sse.close
    response.stream.close
  end
end

Step 3: Gateway Service

The GatewayService is responsible for interfacing with external APIs and streaming data back to the controller. Here’s a minimal version focused on streaming:

class GatewayService
  def initialize(options)
    @prompt = options[:prompt]
    @stream = options[:stream]
  end

  def call(&block)
    if @stream
      simulate_streaming(&block)
    else
      { message: "Standard response for #{@prompt}" }
    end
  end

  private

  def simulate_streaming
    5.times do |i|
      sleep 1
      yield "Chunk #{i + 1}: Response for #{@prompt}"
    end
  end
end

Running the Example

To test this setup, you can use a tool like curl to simulate a client request:

curl -N -H "Accept: text/event-stream" -d "message[prompt]=Hello&message[stream]=true" http://localhost:3000/messages

This will initiate a streaming connection, and you should see the streamed chunks arriving one by one.

Conclusion

Implementing streaming in a Ruby on Rails application is straightforward with the ActionController::Live module. By properly handling streaming responses, you can create applications that provide real-time updates to users, greatly enhancing the user experience. Whether you are working on a chat application, live notifications, or data feeds, streaming is a powerful tool in your Rails development toolkit.

Happy coding!

Sebastian Schkudlara
Written by Sebastian Schkudlara Follow
Hi, I am Sebastian Schkudlara, the author of Jevvellabs. I hope you enjoy my blog!