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


91

У мене проблема з redirect_to :back. Так, це реферали.

Я часто отримую виняток

(ActionController :: RedirectBackError) "У запиті на цю дію не встановлено HTTP_REFERER, тому redirect_to: back не вдалося викликати успішно. Якщо це тест, обов’язково вкажіть request.env [\" HTTP_REFERER \ "]."

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


У мене така сама помилка в дії оновлення, що дивно, оскільки реферал не міг бути порожнім (оскільки запит буде з форми), але деякому користувачеві просто вдалося зробити це, що я не знаю як.
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
Я підозрюю, що зміню це, щоб замість цього використовувати рятувальник_від.
Боб Аман,

1
@BobAman IMO, який ми могли б використати, rescue_fromякби контролер мав декількаredirect_to :back
Тео Б,

не працює з рейками 5, ActionController :: RedirectBackError не визначено ... яке рішення?
Матриця

Використовуйте це замість цього: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 За відповідь на запитання та не критикуючи методи дизайну.
Abe Petrillo,

31

Основна особливість

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

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

EDIT: джерело


Посилання на джерело, будь ласка
Кріс Блум

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)

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')}

0

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


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

Якщо ви хочете використовувати sessionдеталі, зробіть це в іншій частині коду.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.