Streaming Data With Rails 3.1 or 3.2
Posted by on February 4, 2012 in UncategorizedWe 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.
