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


186

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

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 

关于如何使它起作用的任何想法。看来这个问题很容易解决,但是我对RoR还是陌生的。

Answers:


323

在您的编辑操作中,将请求的URL存储在会话哈希中,该哈希可用于多个请求:

session[:return_to] ||= request.referer

保存成功后,然后在更新操作中重定向到它:

redirect_to session.delete(:return_to)

68
我建议redirect_to session.delete(:return_to)在更新操作中。这将清除会话中的值,因为不再需要它。
stigi 2012年

19
没有打开几个选项卡会混淆此逻辑吗?
jones

12
你不能redirect_to request.referer吗?
Elle Mundy 2014年

1
@DanMundy不行,request.referer.referer如果可能的话,应该起作用。@Jaime Bellmyer为什么||=
x-yuri

@jones是的。如果切换到另一个模型编辑,也会引起混乱。我也对为什么|| =感兴趣
Mauro

99

为什么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)

请注意,redirect_to(:back)Rails 5中已不推荐使用。可以使用

redirect_back(fallback_location: 'something')相反(请参见http://blog.bigbinary.com/2016/02/29/rails-5-improves-redirect_to_back-with-redirect-back.html


12
redirect_to :back对我来说也不能很好地工作,例如您访问/posts/new,这被设置为下一个请求的引荐来源,因此在成功提交表单后,它将再次显示该表单,即/posts/new。但是,它可以很好地用于其他目的。
克里斯(Kris)

也就是说,OP希望重定向回两次。我敢打赌他可以redirect_to projects_path
x-yuri 2015年

是的 redirect_back在Rails 5中效果
不佳

@strizzwald“工作不正常”是什么意思?有什么细节吗?
Pascal

@pascalbetz,我的意思是,如果HTTP_REFERER未设置,您可能会得到ActionController::RedirectBackError,在这种情况下,您必须从此异常中解脱出来。据我了解,使用redirect_back不需要任何异常处理,因为您必须提供fallback_location。也许“做得不好”不是正确的表达方式。
strizzwald

45

我喜欢Jaime的方法,但有一个例外,它对我来说每次重新存储引用都更好:

def edit
    session[:return_to] = request.referer
...

原因是,如果您编辑多个对象,则将始终使用Jaime的方法将您重定向到存储在会话中的第一个URL。例如,假设我有对象Apple和Orange。我编辑Apple,session[:return_to]并设置为该操作的引用。当我使用相同的代码去编辑Oranges时,session[:return_to]不会被设置,因为它已经定义。因此,当我更新Orange时,将被发送到先前Apple#edit操作的引用者。


是的,但是如果您意外存储了相同的网址,您能建议怎么办吗?你在苹果,你来自苹果。您想要以前的位置
Uko

33

这就是我们在应用程序中做到的方式

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会话参数中,因此所有表单,即使多次POST也可以使用:return_to


3
request.request_uri不再可用,所以我建议request.fullpath改用
anka 2012年

@anka更新。感谢您的评论
MBO

2
是的,这很好。我只建议通常不使用andorin if语句。使用&&||代替。详细信息在这里
阿喀琉斯(Achilles)2015年

19

在Rails 5中,按照Rails指南中的说明,您可以使用:

redirect_back(fallback_location: root_path)

“后退”位置是从HTTP_REFERER标头中拉出的,浏览器不保证可以设置此位置。因此,您应该提供一个“ fallback_location”。


此功能出现在导轨5中
。– Chambeur

@pSkarl我如何传递一个notice与对象redirect_back的语句,以告诉用户出现了问题带有闪光灯的消息?
alexventuraio

2
好吧,我可以通过以下方法解决此问题:redirect_back(fallback_location: root_path, notice: "Something went wrong!")。希望它可以有所帮助。
alexventuraio

18

request.referer 由Rack设置,并设置如下:

def referer
  @env['HTTP_REFERER'] || '/'
end

只需执行a redirect_to request.referer,它将始终重定向到真实的引荐页或root_path('/')。当将在直接导航情况下失败的测试通过到控制器抛出redirect_to:back的特定页面时,这是必不可少的


不知道你在看,但在机架源的文件,这是怎么referer被定义为2011年03月28,那就是它是如何定义的今天。也就是说,|| '/'它不是定义的一部分。
maček

1

对于那些感兴趣的人,这是我的实现,它扩展了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
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.