Browse files

Remove autosweep_flash and set_authenticity_token settings.

These are now on if and only if progressively rendering.
  • Loading branch information...
1 parent 88aad92 commit 32677893a4e1da2ceb15929996ee5650ba7fc4e2 @oggy committed Apr 4, 2011
Showing with 220 additions and 54 deletions.
  1. +26 −53 lib/template_streaming.rb
  2. +8 −1 spec/support/progressive_rendering_test.rb
  3. +186 −0 spec/template_streaming_spec.rb
View
79 lib/template_streaming.rb
@@ -5,44 +5,15 @@ def configure(config)
send "#{key}=", value
end
end
-
- #
- # If true, always reference the flash before returning from the
- # action when rendering progressively.
- #
- # This is required for the flash to work with progressive
- # rendering, but unlike standard Rails behavior, will cause the
- # flash to be swept even if it's never referenced in the
- # views. This usually isn't an issue, as flash messages are
- # typically rendered in the layout, causing a reference anyway.
- #
- # Default: true.
- #
- attr_accessor :autosweep_flash
-
- #
- # If true, always set the authenticity token before returning from
- # the action when rendering progressively.
- #
- # This is required for the authenticity token to work with
- # progressive rendering, but unlike standard Rails behavior, will
- # cause the token to be set (and thus the session updated) even if
- # it's never referenced in views.
- #
- # Default: true.
- #
- attr_accessor :set_authenticity_token
end
- self.autosweep_flash = true
- self.set_authenticity_token = true
-
module Controller
def self.included(base)
base.class_eval do
extend ClassMethods
alias_method_chain :render, :template_streaming
alias_method_chain :render_to_string, :template_streaming
+ alias_method_chain :flash, :template_streaming
helper_method :flush, :push
include ActiveSupport::Callbacks
@@ -85,21 +56,24 @@ def render_with_template_streaming(*args, &block)
end
response.body = @streaming_body
response.prepare!
- flash if TemplateStreaming.autosweep_flash
- form_authenticity_token if TemplateStreaming.set_authenticity_token
- run_callbacks :when_streaming_template
+ form_authenticity_token # generate now
- # Normally, @_flash is removed after #perform_action, which
- # means calling #flash in the view would cause a new
- # FlashHash to be constructed. On top of that, the flash is
- # swept on construction, which results in sweeping the flash
- # twice, obliterating its contents.
+ # Normally, the flash is swept on first reference. This
+ # means we need to ensure it's referenced before the session
+ # is persisted. In the case of the cookie store, that's when
+ # the headers are sent, so we force a reference now.
#
- # So, we preserve the flash here under a different ivar, and
- # override the #flash helper to return it.
- if defined?(@_flash)
- @template_streaming_flash = @_flash
- end
+ # But alas, that's not all. @_flash is removed after
+ # #perform_action, which means calling #flash in the view
+ # would cause the flash to be referenced again, sweeping the
+ # flash a second time. To prevent this, we preserve the
+ # flash in a separate ivar, and patch #flash to return this
+ # if we're rendering progressively.
+ #
+ flash # ensure sweep
+ @template_streaming_flash = @_flash
+
+ run_callbacks :when_streaming_template
else
render_without_template_streaming(*args, &block)
end
@@ -213,6 +187,15 @@ def flush_thin
connection = request.env['template_streaming.thin_connection'] and
EventMachineFlush.flush(connection)
end
+
+ def flash_with_template_streaming # :nodoc:
+ if defined?(@template_streaming_flash)
+ # Flash has been swept - don't use the standard #flash or it'll sweep again.
+ @template_streaming_flash
+ else
+ flash_without_template_streaming
+ end
+ end
end
# Only prepare once.
@@ -241,7 +224,6 @@ module View
def self.included(base)
base.alias_method_chain :render, :template_streaming
base.alias_method_chain :_render_with_layout, :template_streaming
- base.alias_method_chain :flash, :template_streaming
end
def render_with_template_streaming(*args, &block)
@@ -311,15 +293,6 @@ def with_render_proc_for_layout(options)
@_proc_for_layout = original_proc_for_layout
end
end
-
- def flash_with_template_streaming # :nodoc:
- if render_progressively?
- # Flash has been swept - don't use the standard #flash or it'll sweep again.
- controller.instance_eval { @template_streaming_flash }
- else
- flash_without_template_streaming
- end
- end
end
class StreamingBody
View
9 spec/support/progressive_rendering_test.rb
@@ -1,13 +1,14 @@
module ProgressiveRenderingTest
VIEW_PATH = "#{ROOT}/spec/tmp/views"
+ COOKIE_SECRET = 'x'*30
def self.included(base)
base.before { setup_progressive_rendering_test }
base.after { teardown_progressive_rendering_test }
end
def setup_progressive_rendering_test
- ActionController::Base.session = {:key => "_", :secret => "x"*30}
+ ActionController::Base.session = {:key => "session", :secret => COOKIE_SECRET}
ActionController::Routing::Routes.clear!
ActionController::Routing::Routes.add_route('/', :controller => 'test', :action => 'action')
@@ -66,6 +67,12 @@ def run(env_overrides={})
attr_reader :status, :headers, :body, :data
+ def session
+ cookie_value = headers['Set-Cookie'].scan(/^session=([^;]*)/).first.first
+ verifier = ActiveSupport::MessageVerifier.new(COOKIE_SECRET, 'SHA1')
+ verifier.verify(CGI.unescape(cookie_value))
+ end
+
def default_env
{
'REQUEST_METHOD' => 'GET',
View
186 spec/template_streaming_spec.rb
@@ -585,4 +585,190 @@
data.order.should == [:action, :rendering]
end
end
+
+ describe "#flash" do
+ describe "when rendering progressively" do
+ it "should behave correctly when referenced in the controller" do
+ values = []
+ view ""
+ action do
+ flash[:key] = "value" if params[:set]
+ values << flash[:key]
+ render :progressive => true
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ values.should == ['value', 'value', nil]
+ end
+
+ it "should behave correctly when only referenced in the view" do
+ view "(<%= flash[:key] %>)"
+ action do
+ flash[:key] = "value" if params[:set]
+ render :progressive => true
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+ received.should == chunks('(value)', :end => true)
+
+ run('HTTP_COOKIE' => session_cookie)
+ received.should == chunks('(value)', :end => true)
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ received.should == chunks('()', :end => true)
+ end
+ end
+
+ describe "when not rendering progressively" do
+ it "should behave correctly when referenced in the controller" do
+ values = []
+ view ""
+ action do
+ flash[:key] = "value" if params[:set]
+ values << flash[:key]
+ render :progressive => false
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ values.should == ['value', 'value', nil]
+ end
+ end
+
+ it "should behave correctly when only referenced in the view" do
+ view "(<%= flash[:key] %>)"
+ action do
+ flash[:key] = "value" if params[:set]
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+ received.should == '(value)'
+
+ run('HTTP_COOKIE' => session_cookie)
+ received.should == '(value)'
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ received.should == '()'
+ end
+ end
+
+ describe "#flash.now" do
+ describe "when rendering progressively" do
+ it "should behave correctly when referenced in the controller" do
+ values = []
+ view ""
+ action do
+ flash.now[:key] = "value" if params[:set]
+ values << flash[:key]
+ render :progressive => true
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ values.should == ['value', nil]
+ end
+
+ it "should behave correctly when only referenced in the view" do
+ view "(<%= flash[:key] %>)"
+ action do
+ flash.now[:key] = "value" if params[:set]
+ render :progressive => true
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+ received.should == chunks('(value)', :end => true)
+
+ run('HTTP_COOKIE' => session_cookie)
+ received.should == chunks('()', :end => true)
+ end
+ end
+
+ describe "when not rendering progressively" do
+ it "should behave correctly when referenced in the controller" do
+ values = []
+ view ""
+ action do
+ flash.now[:key] = "value" if params[:set]
+ values << flash[:key]
+ render :progressive => false
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+
+ run('HTTP_COOKIE' => session_cookie)
+ values.should == ['value', nil]
+ end
+ end
+
+ it "should behave correctly when only referenced in the view" do
+ view "(<%= flash[:key] %>)"
+ action do
+ flash.now[:key] = "value" if params[:set]
+ end
+ run('QUERY_STRING' => 'set=1')
+ session_cookie = headers['Set-Cookie'].scan(/^(session=[^;]*)/).first.first
+ received.should == '(value)'
+
+ run('HTTP_COOKIE' => session_cookie)
+ received.should == '()'
+ end
+ end
+
+ describe "#form_authenticity_token" do
+ describe "when rendering progressively" do
+ it "should match what is in the session when referenced in the controller" do
+ view ''
+ value = nil
+ action do
+ value = form_authenticity_token
+ render :progressive => true
+ end
+ run
+ session[:_csrf_token].should == value
+ end
+
+ it "should match what is in the session when only referenced in the view" do
+ view "<%= form_authenticity_token %>"
+ action do
+ render :progressive => true
+ end
+ run
+ received.should == chunks(session[:_csrf_token], :end => true)
+ end
+ end
+
+ describe "when not rendering progressively" do
+ it "should match what is in the session when referenced in the controller" do
+ view ''
+ value = nil
+ action do
+ value = form_authenticity_token
+ render :progressive => false
+ end
+ run
+ session[:_csrf_token].should == value
+ end
+
+ it "should match what is in the session when only referenced in the view" do
+ view "<%= form_authenticity_token %>"
+ action do
+ render :progressive => false
+ end
+ run
+ received.should == session[:_csrf_token]
+ end
+ end
+ end
end

0 comments on commit 3267789

Please sign in to comment.