当引用器不可用时,正确地在 Ruby on Rails 中执行 redirect_to:

我有一个问题与 redirect_to :back。是的,它的推荐人。

我经常遇到例外

(ActionController: : RedirectBackError)“在对此操作的请求中没有设置 HTTP _ REFERER,因此无法成功调用 redirect _ to: back。如果这是一个测试,请确保指定 request.env [“ HTTP _ REFERER”]

我意识到这是一个不可用的推荐人的结果。例如,有没有一种方法可以在每次访问最后访问的页面时设置一个会话变量,并且当 HTTP _ REFERER 不可用时,利用这个会话变量重定向到?

77571 次浏览
def store_location
session[:return_to] = request.request_uri
end


def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end

Try that! (Thanks to the Authlogic plugin)

It is unlikely that you do have a session and don't have a referrer.

The situation that a referrer is not set isn't that uncommon and I usually rescue that expection:

def some_method
redirect_to :back
rescue ActionController::RedirectBackError
redirect_to root_path
end

If you do this often (which I think is a bad idea) you can wrap it in an other method like Maran suggests.

BTW I think that's a bad idea because this makes the userflow ambiguous. Only in the case of a login this is sensible.

UPDATE: As several people pointed out this no longer works with Rails 5. Instead, use redirect_back, this method also supports a fallback. The code then becomes:

def some_method
redirect_back fallback_location: root_path
end

Here's my little redirect_to_back method:

  def redirect_to_back(default = root_url)
if request.env["HTTP_REFERER"].present? and request.env["HTTP_REFERER"] != request.env["REQUEST_URI"]
redirect_to :back
else
redirect_to default
end
end

You can pass an optional url to go somewhere else if http_refferrer is blank.

Maybe it's late but I would like to share my method which also preserve options:

  def redirect_back_or_default(default = root_path, *options)
tag_options = {}
options.first.each { |k,v| tag_options[k] = v } unless options.empty?
redirect_to (request.referer.present? ? :back : default), tag_options
end

You can use it like:

redirect_back_or_default(some_path, :notice => 'Hello from redirect', :status => 301)

updated: Rails 5 added redirect_back method (https://github.com/rails/rails/pull/22506/), better just use:

redirect_back fallback_location: answer_path(answer), flash: { error: I18n.t('m.errors')}

For rails lower than 5.0 can still use the old way below:

similar to @troex's answer, add this to your application controller

def redirect_back_or_default(default = root_path, options = {})
redirect_to (request.referer.present? ? :back : default), options
end

then use it in your controller

redirect_back_or_default answer_path(answer), flash: { error: I18n.t('m.errors')}

Core feature

redirect_back is a core feature from Rails 5+, it is available in the ActionController::Redirecting module that is already included inApplicationController::Base.

DEPRECATION WARNING: redirect_to :back is deprecated and will be removed from Rails 5.1. Please use redirect_back(fallback_location: fallback_location) where fallback_location represents the location to use if the request has no HTTP referer information.

EDIT : source

Recently, I encountered the same issue where either I had to redirect :back or to specific page. After going to a lot of solution, I finally found this which is simple and seems to solve the issue:


if request.env["HTTP_REFERER"].present?
redirect_to :back
else
redirect_to 'specific/page'
end

If you want to use session details, do it in the else part of the code.

redirect_back_or_to (Rails 7+)

Rails 7 presents a new idiomatic way to redirect back or to the fallback location.

Quoting directly from the official Rails API docs:

redirect_back_or_to(fallback_location, allow_other_host: true, **args)

Redirects the browser to the page that issued the request (the referrer) if possible, otherwise redirects to the provided default fallback location.

The referrer information is pulled from the HTTP Referer (sic) header on the request. This is an optional header and its presence on the request is subject to browser security settings and user preferences. If the request is missing this header, the fallback_location will be used.

redirect_back_or_to({ action: "show", id: 5 })
redirect_back_or_to @post
redirect_back_or_to "http://www.rubyonrails.org"
redirect_back_or_to "/images/screenshot.jpg"
redirect_back_or_to posts_url
redirect_back_or_to proc { edit_post_url(@post) }
redirect_back_or_to '/', allow_other_host: false

It is also worth mentioning that
the Rails 5 way redirect_back(fallback_location: '/things/stuff')
has exactly the same behavior as newly introduced redirect_back_or_to('/things/stuff').

Sources: