The insider's guide to everything sparqcode
Header image

Streaming Data With Rails 3.1 or 3.2

Posted by Mike on February 4, 2012 in Uncategorized

We recently upgraded one of our services to use Rails 3.2. The downside I discovered pretty quickly is that rails broke support for the 3.0 way of streaming data.

The 3.0 way, simplified a bit:

self.response_body =  proc{ |response, output|
  @records.each do |record|
     output.write << CSV.generate_line(record.csv_values)
}

In >= 3.1, the proc method has been deprecated. What are we to do then? Well it's actually pretty simple if we go digging in the Rack source code.

      if body.respond_to? :to_str
        write body.to_str
      elsif body.respond_to?(:each)
        body.each { |part|
          write part.to_s
        }
      else
        raise TypeError, "stringable or iterable required"
      end

Basically, if we set response_body to something that responds to 'each' then rack will automatically send those chunks back to the browser without having to do anything special on our end. In my case I wrote a little streamer class that would take care of it.

class RecordCsvStreamer
   attr_reader :records

   def initialize(record_scope)
      @records = record_scope
   end

   def each
     records.each do |record|
        yield csv_row(record)
     end
   end

   def csv_row(record)
   # however you want to format it
   end
end

Then in my controller I do

class RecordController
  def index
    @records = Record.all

    self.response_body = new RecordCsvStreamer(@records)
  end
end

Happy streaming!

You can follow any responses to this entry through the RSS 2.0 You can leave a response, or trackback.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>