aboutsummaryrefslogtreecommitdiffstats
path: root/actionpack/lib/action_view/flows.rb
diff options
context:
space:
mode:
authorJosé Valim <jose.valim@gmail.com>2011-04-16 10:28:47 +0200
committerJosé Valim <jose.valim@gmail.com>2011-04-16 10:28:47 +0200
commite30ca001efa861cc13259ca8287837174b24e679 (patch)
treeab47ef08d8c2e8773bb7fc6d6d24cda6cd32bf66 /actionpack/lib/action_view/flows.rb
parent2dd43c3f804176d114cdbfeb8a0f92a43155baee (diff)
downloadrails-e30ca001efa861cc13259ca8287837174b24e679.tar.gz
rails-e30ca001efa861cc13259ca8287837174b24e679.tar.bz2
rails-e30ca001efa861cc13259ca8287837174b24e679.zip
Yo dawg, I heard you like streaming. So I put a fiber, inside a block, inside a body, so you can stream.
Diffstat (limited to 'actionpack/lib/action_view/flows.rb')
-rw-r--r--actionpack/lib/action_view/flows.rb64
1 files changed, 64 insertions, 0 deletions
diff --git a/actionpack/lib/action_view/flows.rb b/actionpack/lib/action_view/flows.rb
new file mode 100644
index 0000000000..1ac62961d1
--- /dev/null
+++ b/actionpack/lib/action_view/flows.rb
@@ -0,0 +1,64 @@
+require 'active_support/core_ext/string/output_safety'
+
+module ActionView
+ class OutputFlow
+ attr_reader :content
+
+ def initialize
+ @content = Hash.new { |h,k| h[k] = ActiveSupport::SafeBuffer.new }
+ end
+
+ def get(key)
+ @content[key]
+ end
+
+ def set(key, value)
+ @content[key] = value
+ end
+
+ def append(key, value)
+ @content[key] << value
+ end
+ end
+
+ class StreamingFlow < OutputFlow
+ def initialize(flow, fiber)
+ @content = flow.content
+ @fiber = fiber
+ @root = Fiber.current.object_id
+ end
+
+ # Try to get an stored content. If the content
+ # is not available and we are inside the layout
+ # fiber, we set that we are waiting for the given
+ # key and yield.
+ def get(key)
+ return super if @content.key?(key)
+
+ if inside_fiber?
+ begin
+ @waiting_for = key
+ Fiber.yield
+ ensure
+ @waiting_for = nil
+ end
+ end
+
+ super
+ end
+
+ # Set the contents for the given key. This is called
+ # by provides and resumes back to the fiber if it is
+ # the key it is waiting for.
+ def set(key, value)
+ super
+ @fiber.resume if @waiting_for == key
+ end
+
+ private
+
+ def inside_fiber?
+ Fiber.current.object_id != @root
+ end
+ end
+end \ No newline at end of file