From b0502edfd4e588b4969d44a888e4b71460a83e3f Mon Sep 17 00:00:00 2001 From: Kasper Timm Hansen Date: Sat, 6 Jul 2024 17:58:14 +0200 Subject: [PATCH] Add `redirect_forward_or_to`. (#8) I'm keen to explore more controller language that focuses on advance/forward or regress, in other words movements. E.g. a successful action moves you forward to another action, while an unsuccessful action makes you recede. I don't have more on that right now, but I explored something like it here: https://github.com/excid3/rails/pull/2#issuecomment-1760041620 So `redirect_forward_or_to` starts establishing that, but it's really just syntactic sugar around `redirect_to redirect_url || fallback_url`. --- lib/action_controller/stashed_redirects.rb | 14 ++++++++++---- test/action_controller/stashed_redirects_test.rb | 8 ++++++++ test/boot/action_controller.rb | 4 ++++ test/test_helper.rb | 6 +++++- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/lib/action_controller/stashed_redirects.rb b/lib/action_controller/stashed_redirects.rb index 9effc76..58d6707 100644 --- a/lib/action_controller/stashed_redirects.rb +++ b/lib/action_controller/stashed_redirects.rb @@ -83,12 +83,18 @@ def derive_stash_redirect_url_from(url) end end - # Looks up a redirect URL from `params[:redirect_url]` using - # `url_from` as the protection mechanism to ensure it's a valid internal redirect. + # Syntactic sugar for redirecting to `redirect_url` with a fallback. # - # Can be passed to `redirect_to` with a fallback: + # redirect_forward_or_to root_url # => redirect_to redirect_url || root_url + def redirect_forward_or_to(fallback_url) + redirect_to redirect_url || fallback_url + end + + # Looks up a redirect URL from `params[:redirect_url]` using + # Rails' `url_from` as the protection mechanism to ensure it's a valid internal redirect. + # See the `url_from` docs: https://api.rubyonrails.org/classes/ActionController/Redirecting.html#method-i-url_from # - # redirect_to redirect_url || users_url + # You probably want to use `redirect_forward_or_to`. def redirect_url = url_from(params[:redirect_url]) DEFAULT_URL = Object.new diff --git a/test/action_controller/stashed_redirects_test.rb b/test/action_controller/stashed_redirects_test.rb index 134c866..f7b488f 100644 --- a/test/action_controller/stashed_redirects_test.rb +++ b/test/action_controller/stashed_redirects_test.rb @@ -32,6 +32,14 @@ class ActionController::StashedRedirectsTest < ActionDispatch::IntegrationTest get new_session_url assert_response :internal_server_error end + + test "redirect_forward_or_to" do + get forward_sessions_redirects_url, params: { redirect_url: users_url } + assert_redirected_to users_url + + get forward_sessions_redirects_url + assert_redirected_to root_url + end end class ActionController::StashedRedirects::HooksTest < ActiveSupport::TestCase diff --git a/test/boot/action_controller.rb b/test/boot/action_controller.rb index 1a3b2f6..a317bcc 100644 --- a/test/boot/action_controller.rb +++ b/test/boot/action_controller.rb @@ -24,5 +24,9 @@ class RedirectsController < ApplicationController def create redirect_from_stashed :sign_in end + + def forward + redirect_forward_or_to root_url + end end end diff --git a/test/test_helper.rb b/test/test_helper.rb index b4e3852..6ce2e5a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -27,10 +27,14 @@ class ActionController::StashedRedirects::Application < Rails::Application Rails.application.routes.draw do resources :sessions namespace :sessions do - resources :redirects + resources :redirects do + get :forward, on: :collection + end end resources :users + + root to: "sessions#new" end require_relative "boot/action_controller"