Rails streaming is a great feature that allows you to optimize on server resources when dealing with large generated content. However – it might be a bit tricky to validate and test in local development.
First off – a local server that supports streaming is required. The only one I could find was trinidad which is moving to the likely defacto for JRuby/Rails projects. Trinidad uses tomcat-core as it’s servlet container and server.
Then make sure you grab the latest jruby-rack resolving most recent issues (1.1.10 at the time of writing).
This StackOverflow answer, along with this guide offer a comprehensive support as to what options work with Rails version as well as some gotchas (newrelic, caching, haml, …).
For Rails 3.2.x – It boils down to assigning an object that responds to an each method call to the response_body of a controller’s action. However – this doesn’t allow you to set a :stream =>true where it explicitly tells Rails to stream the respons. To resolve that I opted to use a render call, with a passed option hash as follows:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# Controller
def streaming_action
@objs = MyObj.where(:foo => 'bar')
render :nothing => true, :stream => true #setting the response to stream while rendering nothing
self.response_body = Streamer.new(@objs) # the object responding to 'each' call
end
#models/streamer.rb
class Streamer
attr_accssor :objs
def initialize(objs)
@objs = objs
end
# all the magic
def each
yield "Some initial output for header"
@objs.each do |obj|
yield "#{obj.attr}\n"
end
end
end |
This works with the following releases: JRuby 1.6.8 Rails 3.2.8 jruby-rack 1.1.10 trinidad 1.4.4
0 Responses
Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.