如何在Ruby on Rails中重定向到上一页?

我有一个页面,列出了所有具有可排序标题和分页的项目。

path:
/projects?order=asc&page=3&sort=code

我选择编辑其中一个项目

path:
projects/436/edit

当我在该页面上单击Save时,它调用Projects Controller/Update方法。更新代码后,我希望重定向到单击“编辑特定项目”之前所在的路径。换句话说,我想在同一页上进行相同的排序。

我看到链接_到(:back),并认为:back可以在重定向_到(:back)中工作,但这是不可行的。

puts YAML::dump(:back)
yields the following:
:back

关于我如何让它工作有什么想法吗?这似乎是一个很容易解决的问题,但我是RoR的新手。

172846 次浏览

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)

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.

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.

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)

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

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'.

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

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.

link_to 'get me back', :back

The symbol :back is your swiss army knife.