A simple redirect to next pattern for Rails
In Rails controllers, it’s pretty common to redirect somewhere when an action is completed. Sometimes this location is unknown, and therefore straightforward. Other times I just want to redirect ‘back’ - wherever that might have been - redirect_back(fallback_location: wherenver_path)
is perfect for that.
Occasionally though, I’ll want to determine the next path from the caller - often this will be for some sort of generic or shared action, that might need to go one of several places when it’s done. For that, I like to use this simple redirect_to_next
pattern:
module RedirectToNext
extend ActiveSupport::Concern
def redirect_to_next(fallback_location:, **args)
return redirect_to fallback_location, **args unless next_path
redirect_to params[:next], **args
end
def next_path
return nil unless params[:next]&.start_with?("/")
params[:next]
end
end
# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
include RedirectToNext
# in a controller
def create
# ...
redirect_to_next(fallback_location: whatever_path, notice: "Created a thing")
end
end
This pattern essentially follows the logic of redirect_back
, but sources the redirect location from a param called next
. The param should be a path (though Rails prevents other-host redirects now by default anyway). It splats other args so that anything that can be passed to redirect_to
is forwarded.
The usage of this is nice and simple. For controllers that are POSTed to directly, I just provide the next
param with the path to send to. For new
actions, I include the next
param as a hidden field:
<%= form_with model: @widget do |f| %>
<%= hidden_field_tag :next, whatever_path %>
<%= f.label :name %>
<%= f.text_field :name %>
<%= f.submit >
<% end %>