Permalink
Browse files

Add features to 'auto_redirect': the ability to specify an exclusion …

…list, and the the ability to provide a custom default value.
  • Loading branch information...
1 parent 2a86068 commit d96a1782f495c2dd99eb46707bfcb68477723bb8 @FooBarWidget committed Sep 3, 2008
@@ -96,11 +96,30 @@ def attempt_auto_redirect
end
# Try to redirect the browser by calling +attempt_auto_redirect+. If that
- # method returns false, then the browser will be redirected to +root_path+
- # instead.
- def auto_redirect
- if !attempt_auto_redirect
- redirect_to root_path
+ # method returns false, then the browser will be redirected to a the
+ # specified default location instead.
+ #
+ # Options:
+ # - +default+: The default location that this method will redirect the
+ # browser to, if +attempt_auto_redirect+ fails or if the redirection
+ # target matches +exclude+. This may be any value that +redirect_to+
+ # would accept.
+ # - +exclude+: A regular expression which specifies a path that
+ # +auto_redirect+ must *not* redirect to. If the place that the browser
+ # is supposed to be redirected to matches this regular expression, then
+ # the browser will be redirected to the default location instead.
+ def auto_redirect(options = {})
+ should_redirect_to_default = false
+ if options[:exclude]
+ info = get_redirection_information
+ should_redirect_to_default = match_exclusion_list(info,
+ options[:exclude])
+ end
+ if !should_redirect_to_default
+ should_redirect_to_default = !attempt_auto_redirect
+ end
+ if should_redirect_to_default
+ redirect_to(options[:default] || root_path)
end
end
@@ -136,6 +155,24 @@ def redirection_information_for_current_request
return ControllerRedirectionInformation.new(
controller_path, action_name, parameters, request.method)
end
+
+ def match_exclusion_list(redirection_info, exclusion_list)
+ case exclusion_list
+ when Array
+ return exclusion_list.all? do |l|
+ match_exclusion_list(redirection_info, l)
+ end
+ when Hash
+ args = exclusion_list.merge(:path_only => true)
+ return redirection_info.path == url_for(args)
+ when String
+ return redirection_info.path == exclusion_list
+ when Regexp
+ return redirection_info.path =~ exclusion_list
+ else
+ raise ArgumentError
+ end
+ end
end
end # module AutoRedirections
@@ -19,6 +19,8 @@
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
+require 'uri'
+
module AutoRedirection
class RedirectionInformation
@@ -58,6 +60,10 @@ def method
return :get
end
+ def path
+ return URI.parse(url).path
+ end
+
def marshal(encrypt = true, ascii7 = true)
super do
Marshal.dump({
@@ -82,6 +88,18 @@ def initialize(controller_path, action_name, params = {}, method = :get)
@method = method || :get
end
+ def path
+ object = Object.new
+ metaclass = class << object
+ self
+ end
+ metaclass.send(:include, ActionController::UrlWriter)
+ args = params.merge(:only_path => true,
+ :controller => controller,
+ :action => action)
+ return metaclass.url_for(args)
+ end
+
def marshal(encrypt = true, ascii7 = true)
super do
Marshal.dump({
@@ -28,6 +28,10 @@ def action_attempt_auto_redirect
end
end
+ def action_auto_redirect
+ auto_redirect(:exclude => %r{^/forbidden}, :default => '/')
+ end
+
def action_save_redirection_information
save_redirection_information
render :nothing => true
@@ -149,4 +153,13 @@ class SimpleRedirectionTest < ActionController::TestCase
assert_kind_of UrlRedirectionInformation, info
assert_equal '/foo', info.url
end
+
+
+ ##### Other tests #####
+
+ test "auto_redirect(:exclude => ...) works" do
+ @controller.request.headers["Referer"] = '/forbidden'
+ get(:action_auto_redirect)
+ assert_redirected_to '/'
+ end
end

0 comments on commit d96a178

Please sign in to comment.