我有一个页面列出了所有具有可排序标题和分页的项目。
path:
/projects?order=asc&page=3&sort=code
我选择编辑其中一个项目
path:
projects/436/edit
当我单击该页面上的“保存”时,它会调用项目控制器/更新方法。 更新代码后,我想重定向到单击“编辑特定项目”之前所在的路径。换句话说,我想在同一页面上进行相同的排序。
我看到link_to(:back)并认为:back可能在redirect_to(:back)中工作,但这是不行的。
puts YAML::dump(:back)
yields the following:
:back
我怎样才能让它发挥作用?
在编辑操作中,将请求 URL 存储在会话哈希中,该哈希可在多个请求中使用:
session[:return_to] ||= request.referer
成功保存后,在更新操作中重定向到它:
redirect_to session.delete(:return_to)
为什么
redirect_to(:back)
对你不起作用,为什么不行?
redirect_to(:back)
对我来说就像一个魅力。这只是一个捷径
redirect_to(request.env['HTTP_REFERER'])
http://apidock.com/rails/ActionController/Base/redirect_to(Rails 3 之前)或 http://apidock.com/rails/ActionController/Redirecting/redirect_to(Rails 3)
请注意,Rails 5 中已弃用
redirect_to(:back)
。您可以使用
redirect_back(fallback_location: 'something')
(参见 http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html)
我喜欢 Jaime 的方法,但有一个例外,每次都重新存储引用者对我来说效果更好:
def edit
session[:return_to] = request.referer
...
原因是,如果您编辑多个对象,您将始终被重定向回使用 Jaime 的方法存储在会话中的第一个 URL。 例如,假设我有对象 Apple 和 Orange。我编辑 Apple 并将
session[:return_to]
设置为该操作的引用者。当我使用相同的代码编辑 Oranges 时,session[:return_to]
将不会被设置,因为它已经被定义了。 因此,当我更新 Orange 时,我将被发送到之前 Apple#edit 操作的引用者。
这就是我们在应用程序中的做法
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
这样,您只将最后一个 GET 请求存储在
:return_to
会话参数中,因此所有表单,即使多次 POSTed 也可以与 :return_to
一起使用。
在 Rails 5 中,按照 Rails Guides 中的说明,您可以使用:
redirect_back(fallback_location: root_path)
“后退”位置是从 HTTP_REFERER 标头中提取的,不保证由浏览器设置。这就是为什么您应该提供“fallback_location”。
request.referer
由Rack设置,设置如下:
def referer
@env['HTTP_REFERER'] || '/'
end
只需执行
redirect_to request.referer
,它就会始终重定向到真正的引用页面或 root_path ('/')。 当将直接导航失败的测试传递到控制器抛出redirect_to :back的特定页面时,这一点至关重要
link_to 'get me back', :back
符号
:back
是您的瑞士军刀。
对于那些感兴趣的人,这是我扩展 MBO 原始答案的实现(针对 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
我想知道这是否有效
def edit
if request.referer != request.original_url
@return_here = request.referer
end
end
并使用@return_here作为提交表单中的隐藏值。
当然,重新加载会终止此问题,因此只需根据需要返回默认回退即可。
@Jaime Bellmyer 最受接受的答案是最好的,但有一个例外:
如果您有:
show
操作是 Rails Scaffold 的默认操作,并且是从 edit
到 show
和返回您需要更多代码,在我的示例中
application_controller
: :
def set_return_to_path(exclude_string = nil)
unless request.referer.include? exclude_string
session[:return_to] = request.referer
end
end
动作内部:
def show
set_return_to_path(edit_article_path(@article))
end
因此,在
show
操作中,当来自 edit
操作并反向时,您会跳过此操作。