The Rails redirect_back Controller Helper
While working on one of our TextACoder projects today I came across the following line which was used by one of the developers on my team:
redirect_back(fallback_location: loan_payment_accounts_path)
It was a foreign line to me. Apparently it was introduced as part of Rails 5. After researching a bit, I came across the original pull request that first introduced the feature.
While it was briefly discussed in the pull request, I found myself wondering whether or not this function should be used in a controller. The most obvious reason to avoid it is that it’s a sort of “Rails magic”. The purist in me wants to avoid as much magic as possible so that future developers know exactly what is taking place here.
In the specific case of our controller, a user can wind up posting to the delete
action via two pages: an index page and an edit page. The bug that this line
solved was that regardless of where you came from, the user was always redirected
back to the index page. So if you were on the edit page, you’d be redirected to
the wrong place.
The alternative would have been to write something like the following:
if params[:editing]
redirect_to edit_loan_payment_accounts_path(params[:loan_id])
else
loan_payment_accounts_path
end
The plus side of this code is that you know the context through which a user can end up at this action. It’s more verbose. The downside? More lines of code, and another parameter.
However the greatest downside is that it could introduce a new potential for failure.
The method redirect_back
depends on HTTP referrer information and thus the
redirect will be incorrect should that header data wind up being unavailable.
So what circumstances will HTTP referrer data be unavailable? According to this StackOverflow post HTTP_REFERER data will be unavailable if the user:
- Entered the site URL in the browser address bar itself
- Visited the site by a browser-maintained bookmark
- Visited the site as first page in the window/tab
- Switched from an HTTPS URL to a different HTTPS URL
- Has security software installed which strips the referrer
- Is behind a proxy which strips the referrer from all requests
- Visited the site programmatically (like, curl)
In our specific circumstance cases 1 to 4 are not possible. Case 7 is ok because we have another API response which just returns a header rather than a redirect.
However we cannot definitively guarantee that the user doesn’t have security software installed or is behind a proxy. In this circumstance the user will be sent to the wrong page. So what strategy did we decide to go with?
We are going to keep the controller action short by switching the original line to:
redirect_to destroy_redirect_path
We then have a function that includes the more verbose code that I outlined earlier.
While this method exists in rails, I can’t suggest that it ever be used since it’s dependent on the unreliable HTTP_REFERER header.