Call block to #redirect_to in controller context (#33735)

* Call block to #redirect_to in controller context

The documentation for ActionController::Redirecting states that a Proc
argument "will be executed in the controller's context."  However,
unless #instance_eval is used (removed in 6b3ad0ca), that statement is
false for procs defined outside of the controller instance.

This commit restores the documented behavior.

Fixes #33731.

* Move test proc into a constant in another class

Per @rafaelfranca's suggestion.

[Steven Peckins + Rafael Mendonça França]
This commit is contained in:
speckins 2018-08-27 22:36:39 -05:00 committed by Rafael França
parent 626958ce98
commit 1353610ff2
2 changed files with 17 additions and 1 deletions

View File

@ -105,7 +105,7 @@ module ActionController
when String
request.protocol + request.host_with_port + options
when Proc
_compute_redirect_to_location request, options.call
_compute_redirect_to_location request, instance_eval(&options)
else
url_for(options)
end.delete("\0\r\n")

View File

@ -5,6 +5,12 @@ require "abstract_unit"
class Workshop
extend ActiveModel::Naming
include ActiveModel::Conversion
OUT_OF_SCOPE_BLOCK = proc do
raise "Not executed in controller's context" unless RedirectController === self
request.original_url
end
attr_accessor :id
def initialize(id)
@ -119,6 +125,10 @@ class RedirectController < ActionController::Base
redirect_to proc { { action: "hello_world" } }
end
def redirect_to_out_of_scope_block
redirect_to Workshop::OUT_OF_SCOPE_BLOCK
end
def redirect_with_header_break
redirect_to "/lol\r\nwat"
end
@ -326,6 +336,12 @@ class RedirectTest < ActionController::TestCase
assert_redirected_to "http://www.rubyonrails.org/"
end
def test_redirect_to_out_of_scope_block
get :redirect_to_out_of_scope_block
assert_response :redirect
assert_redirected_to "http://test.host/redirect/redirect_to_out_of_scope_block"
end
def test_redirect_to_with_block_and_accepted_options
with_routing do |set|
set.draw do