2016-08-06 12:48:35 -04:00
|
|
|
require "active_support/core_ext/string/output_safety"
|
2011-04-16 04:28:47 -04:00
|
|
|
|
|
|
|
module ActionView
|
2011-04-16 05:42:02 -04:00
|
|
|
class OutputFlow #:nodoc:
|
2011-04-16 04:28:47 -04:00
|
|
|
attr_reader :content
|
|
|
|
|
|
|
|
def initialize
|
2016-10-28 23:05:58 -04:00
|
|
|
@content = Hash.new { |h, k| h[k] = ActiveSupport::SafeBuffer.new }
|
2011-04-16 04:28:47 -04:00
|
|
|
end
|
|
|
|
|
2011-04-16 05:42:02 -04:00
|
|
|
# Called by _layout_for to read stored values.
|
2011-04-16 04:28:47 -04:00
|
|
|
def get(key)
|
|
|
|
@content[key]
|
|
|
|
end
|
|
|
|
|
2011-04-16 05:42:02 -04:00
|
|
|
# Called by each renderer object to set the layout contents.
|
2011-04-16 04:28:47 -04:00
|
|
|
def set(key, value)
|
2015-05-06 09:31:49 -04:00
|
|
|
@content[key] = ActiveSupport::SafeBuffer.new(value)
|
2011-04-16 04:28:47 -04:00
|
|
|
end
|
|
|
|
|
2011-04-16 05:42:02 -04:00
|
|
|
# Called by content_for
|
2011-04-16 04:28:47 -04:00
|
|
|
def append(key, value)
|
|
|
|
@content[key] << value
|
|
|
|
end
|
2012-01-22 08:12:26 -05:00
|
|
|
alias_method :append!, :append
|
2011-04-16 04:28:47 -04:00
|
|
|
end
|
|
|
|
|
2011-04-16 05:42:02 -04:00
|
|
|
class StreamingFlow < OutputFlow #:nodoc:
|
2011-04-16 05:22:36 -04:00
|
|
|
def initialize(view, fiber)
|
|
|
|
@view = view
|
|
|
|
@parent = nil
|
|
|
|
@child = view.output_buffer
|
2011-05-01 06:16:31 -04:00
|
|
|
@content = view.view_flow.content
|
2011-04-16 04:28:47 -04:00
|
|
|
@fiber = fiber
|
|
|
|
@root = Fiber.current.object_id
|
|
|
|
end
|
|
|
|
|
2013-06-25 14:34:51 -04:00
|
|
|
# Try to get stored content. If the content
|
2016-04-11 16:01:26 -04:00
|
|
|
# is not available and we're inside the layout fiber,
|
|
|
|
# then it will begin waiting for the given key and yield.
|
2011-04-16 04:28:47 -04:00
|
|
|
def get(key)
|
|
|
|
return super if @content.key?(key)
|
|
|
|
|
|
|
|
if inside_fiber?
|
2011-04-16 05:22:36 -04:00
|
|
|
view = @view
|
|
|
|
|
2011-04-16 04:28:47 -04:00
|
|
|
begin
|
|
|
|
@waiting_for = key
|
2011-04-16 05:22:36 -04:00
|
|
|
view.output_buffer, @parent = @child, view.output_buffer
|
2011-04-16 04:28:47 -04:00
|
|
|
Fiber.yield
|
|
|
|
ensure
|
|
|
|
@waiting_for = nil
|
2011-04-16 05:22:36 -04:00
|
|
|
view.output_buffer, @child = @parent, view.output_buffer
|
2011-04-16 04:28:47 -04:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
super
|
|
|
|
end
|
|
|
|
|
2011-04-16 05:42:02 -04:00
|
|
|
# Appends the contents for the given key. This is called
|
2016-04-11 16:01:26 -04:00
|
|
|
# by providing and resuming back to the fiber,
|
|
|
|
# if that's the key it's waiting for.
|
2011-04-16 05:34:07 -04:00
|
|
|
def append!(key, value)
|
2011-04-16 04:28:47 -04:00
|
|
|
super
|
|
|
|
@fiber.resume if @waiting_for == key
|
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2016-08-06 13:55:02 -04:00
|
|
|
def inside_fiber?
|
|
|
|
Fiber.current.object_id != @root
|
|
|
|
end
|
2011-04-16 04:28:47 -04:00
|
|
|
end
|
2013-06-25 14:34:51 -04:00
|
|
|
end
|