Правильное выполнение redirect_to: обратно в Ruby on Rails, когда реферер недоступен

91

У меня проблема с redirect_to :back. Да, это рефереры.

Я часто получаю исключение

(ActionController :: RedirectBackError) «В запросе к этому действию не был установлен HTTP_REFERER, поэтому redirect_to: back не может быть успешно вызван. Если это тест, обязательно укажите request.env [\" HTTP_REFERER \ "]."

Я понимаю, что это результат недоступности реферера. Есть ли способ, например, чтобы можно было установить переменную сеанса при каждом доступе с последней посещенной страницей, и, когда HTTP_REFERER недоступен, использовать эту переменную сеанса для перенаправления?

user67050
источник
У меня такая же ошибка в действии обновления, что странно, потому что реферер не может быть пустым (поскольку запрос будет из формы), но какой-то пользователь просто сумел это сделать, а я не знаю, как это сделать.
lulalala

Ответы:

144

Это маловероятно , что вы делаете во время сеанса и не имеют реферера.

Ситуация, когда реферер не установлен, не такая уж редкость, и я обычно спасаю это ожидание:

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

Если вы делаете это часто (что я считаю плохой идеей), вы можете обернуть это другим методом, как предлагает Маран.

Кстати, я думаю, что это плохая идея, потому что это делает поток пользователя неоднозначным. Только в случае логина это разумно.

ОБНОВЛЕНИЕ : как указали несколько человек , этот метод больше не работает с Rails 5. Вместо этого используйте redirect_backэтот метод, который также поддерживает откат. Затем код становится:

def some_method
  redirect_back fallback_location: root_path
end
вред
источник
4
Я подозреваю, что я бы изменил это, чтобы вместо этого использовать rescue_from.
Боб Аман,
1
@BobAman ИМО, мы могли бы использовать, rescue_fromесли бы у контроллера было несколькоredirect_to :back
Тео Б
не работает с рельсами 5, ActionController :: RedirectBackError не определен ... какое решение?
Matrix
Используйте вместо этого:redirect_to (request.referrer || root_url)
Abhi
38

Вот мой маленький метод redirect_to_back:

  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

Вы можете передать необязательный URL-адрес, чтобы перейти в другое место, если http_refferrer пуст.

Мирко
источник
37
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

Попробуй это! (Благодаря плагину Authlogic )

Маран
источник
22
Это хорошее решение, но я бы посоветовал любому, кто его использует, помнить, что оно может «сломаться», что сильно запутает пользователя, если он или она использует несколько вкладок для просмотра вашего приложения.
Митч Линдгрен
3
+1 За ответ на вопрос, а не за критику методов дизайна.
Эйб Петрилло,
31

Основная функция

redirect_backэто основная функция из Rails 5+, она доступна в ActionController::Redirectingмодуле, который уже включен в ApplicationController::Base.

ПРЕДУПРЕЖДЕНИЕ ОБ УСТАРЕНИИ: redirect_to :backустарело и будет удалено из Rails 5.1. Пожалуйста, используйте redirect_back(fallback_location: fallback_location)where fallback_locationпредставляет местоположение, которое будет использоваться, если запрос не имеет информации о реферере HTTP.

РЕДАКТИРОВАТЬ: источник

Сирил Дюшон-Дорис
источник
Ссылка на источник, пожалуйста
Крис Блум
1
@ Chrisbloom7 Это предупреждение, которое я получил при запуске Rails 5.0.0beta3 с redirect_to :back.
Сирил Дюшон-Дорис
21

Возможно, уже поздно, но я хотел бы поделиться своим методом, который также сохраняет параметры:

  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

Вы можете использовать это как:

redirect_back_or_default(some_path, :notice => 'Hello from redirect', :status => 301)
Troex
источник
14

обновлено: в Rails 5 добавлен метод redirect_back ( https://github.com/rails/rails/pull/22506/ ), лучше просто используйте:

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

Для рельсов ниже 5.0 можно использовать старый способ, указанный ниже:

аналогично ответу @troex, добавьте это в свой контроллер приложения

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

затем используйте его в своем контроллере

redirect_back_or_default answer_path(answer), flash: { error: I18n.t('m.errors')}
longkt90
источник
0

Недавно я столкнулся с той же проблемой, когда мне приходилось перенаправлять :backили на конкретную страницу. После большого количества решений я наконец нашел это, что прост и, кажется, решает проблему:


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

Если вы хотите использовать sessionдетали, сделайте это в другой части кода.

Рахул Гоял
источник