aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_controller/metal/streaming.rb
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2011-04-18 08:52:29 +0200
committerJosé Valim <jose.valim@gmail.com>2011-04-18 08:55:41 +0200
commit389d15ef139e50696b274f2d61dd309ba2632877 (patch)
tree333341059cbf9227979873345c0cb09338ec45ca /actionpack/lib/action_controller/metal/streaming.rb
parent7a152ab0127877eea6f2cef8ff6d1975a3fc16d4 (diff)
downloadrails-389d15ef139e50696b274f2d61dd309ba2632877.tar.gz
rails-389d15ef139e50696b274f2d61dd309ba2632877.tar.bz2
rails-389d15ef139e50696b274f2d61dd309ba2632877.zip
Body... wanna *stream* my body? Body... such a thrill my body!
Added stream as class level method to make it explicit when to stream. Render also accepts :stream as option.
Diffstat (limited to 'actionpack/lib/action_controller/metal/streaming.rb')
-rw-r--r--actionpack/lib/action_controller/metal/streaming.rb57
1 files changed, 57 insertions, 0 deletions
diff --git a/actionpack/lib/action_controller/metal/streaming.rb b/actionpack/lib/action_controller/metal/streaming.rb
new file mode 100644
index 0000000000..adb3e94134
--- /dev/null
+++ b/actionpack/lib/action_controller/metal/streaming.rb
@@ -0,0 +1,57 @@
+require 'active_support/core_ext/file/path'
+require 'rack/chunked'
+
+module ActionController #:nodoc:
+ # Methods for sending streaming templates back to the client.
+ module Streaming
+ extend ActiveSupport::Concern
+
+ include AbstractController::Rendering
+ attr_internal :stream
+
+ module ClassMethods
+ # Render streaming templates. It accepts :only, :except, :if and :unless as options
+ # to specify when to stream, as in ActionController filters.
+ def stream(options={})
+ if defined?(Fiber)
+ before_filter :_stream_filter, options
+ else
+ raise "You cannot use streaming if Fiber is not available."
+ end
+ end
+ end
+
+ protected
+
+ # Mark following render calls as streaming.
+ def _stream_filter #:nodoc:
+ self.stream = true
+ end
+
+ # Consider the stream option when normalazing options.
+ def _normalize_options(options) #:nodoc:
+ super
+ options[:stream] = self.stream unless options.key?(:stream)
+ end
+
+ # Set proper cache control and transfer encoding when streaming
+ def _process_options(options) #:nodoc:
+ super
+ if options[:stream]
+ headers["Cache-Control"] ||= "no-cache"
+ headers["Transfer-Encoding"] = "chunked"
+ headers.delete("Content-Length")
+ end
+ end
+
+ # Call render_to_body if we are streaming instead of usual +render+.
+ def _render_template(options) #:nodoc:
+ if options.delete(:stream)
+ Rack::Chunked::Body.new view_context.render_body(options)
+ else
+ super
+ end
+ end
+ end
+end
+ \ No newline at end of file