Reputation: 6149
I have a page that lists all of the projects that has sortable headers and pagination.
path:
/projects?order=asc&page=3&sort=code
I choose to edit one of the projects
path:
projects/436/edit
When I click save on that page, it calls the projects controller / update method. After I update the code I want to redirect to the path that I was on before I clicked edit a specific project. In other words, I want to be on the same page with the same sorting.
I saw link_to(:back) and thought that :back may work in redirect_to(:back), but that's a no go.
puts YAML::dump(:back)
yields the following:
:back
How can I get this to work?
Upvotes: 198
Views: 178976
Reputation: 1176
Another way is to store the (search-) params in a cookie.
This way my customers love: You do a search for a index page. And doesnt matter where you are clicking around in your app, you always can return to the last query until you modify it.
Upvotes: 0
Reputation: 1176
The most accepted answer by @Jaime Bellmyer is the best, with one exception:
If you:
show
action like is default for Rails Scaffold and a link from edit
to show
, so that you want to go from index to show and then return to the original index path, lets say, together with search paramsYou would need some more code, in my example inside the application_controller
:
def set_return_to_path(skip_when_includes = nil)
return unless request.referrer #=> because of request-tests
unless skip_when_includes && request.referer.include?(skip_when_includes)
session[:return_to] = request.referer
end
end
inside the action:
def edit
set_return_to_path(edit_article_path(@article))
end
So, within the show
action you skip this when coming from the edit
action and reverse.
AND you must use session[:return_to]
instead of session.delete(:return_to)
on relevant places for avoiding a redirect-to-nil-error.
Upvotes: 0
Reputation: 6217
link_to 'get me back', :back
The symbol :back
is your swiss army knife.
Upvotes: 3
Reputation: 125
I wonder if this will work
def edit
if request.referer != request.original_url
@return_here = request.referer
end
end
and use @return_here as a hidden value in the submit form.
of course reloading will kill this so just go back to a default fall back as needed.
Upvotes: 0
Reputation: 8656
Why does redirect_to(:back)
not work for you, why is it a no go?
redirect_to(:back)
works like a charm for me. It's just a short cut for
redirect_to(request.env['HTTP_REFERER'])
http://apidock.com/rails/ActionController/Base/redirect_to (pre Rails 3) or http://apidock.com/rails/ActionController/Redirecting/redirect_to (Rails 3)
Please note that redirect_to(:back)
is being deprecated in Rails 5. You can use
redirect_back(fallback_location: 'something')
instead (see http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html)
Upvotes: 106
Reputation: 577
For those who are interested, here is my implementation extending MBO's original answer (written against rails 4.2.4, ruby 2.1.5).
class ApplicationController < ActionController::Base
after_filter :set_return_to_location
REDIRECT_CONTROLLER_BLACKLIST = %w(
sessions
user_sessions
...
etc.
)
...
def set_return_to_location
return unless request.get?
return unless request.format.html?
return unless %w(show index edit).include?(params[:action])
return if REDIRECT_CONTROLLER_BLACKLIST.include?(controller_name)
session[:return_to] = request.fullpath
end
def redirect_back_or_default(default_path = root_path)
redirect_to(
session[:return_to].present? && session[:return_to] != request.fullpath ?
session[:return_to] : default_path
)
end
end
Upvotes: 1
Reputation: 354
In rails 5, as per the instructions in Rails Guides, you can use:
redirect_back(fallback_location: root_path)
The 'back' location is pulled from the HTTP_REFERER header which is not guaranteed to be set by the browser. Thats why you should provide a 'fallback_location'.
Upvotes: 26
Reputation: 23317
In your edit action, store the requesting url in the session hash, which is available across multiple requests:
session[:return_to] ||= request.referer
Then redirect to it in your update action, after a successful save:
redirect_to session.delete(:return_to)
Upvotes: 342
Reputation: 31025
This is how we do it in our application
def store_location
session[:return_to] = request.fullpath if request.get? and controller_name != "user_sessions" and controller_name != "sessions"
end
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
end
This way you only store last GET request in :return_to
session param, so all forms, even when multiple time POSTed would work with :return_to
.
Upvotes: 35
Reputation: 19181
I like Jaime's method with one exception, it worked better for me to re-store the referer every time:
def edit
session[:return_to] = request.referer
...
The reason is that if you edit multiple objects, you will always be redirected back to the first URL you stored in the session with Jaime's method. For example, let's say I have objects Apple and Orange. I edit Apple and session[:return_to]
gets set to the referer of that action. When I go to edit Oranges using the same code, session[:return_to]
will not get set because it is already defined. So when I update the Orange, I will get sent to the referer of the previous Apple#edit action.
Upvotes: 46
Reputation: 181
request.referer
is set by Rack and is set as follows:
def referer
@env['HTTP_REFERER'] || '/'
end
Just do a redirect_to request.referer
and it will always redirect to the true referring page, or the root_path ('/'). This is essential when passing tests that fail in cases of direct-nav to a particular page in which the controller throws a redirect_to :back
Upvotes: 18