Как перенаправить на предыдущую страницу в Ruby On Rails?

У меня есть страница, в которой перечислены все проекты, у которых есть сортируемые заголовки и разбиение на страницы.

path:
/projects?order=asc&page=3&sort=code

Я хочу изменить один из проектов

path:
projects/436/edit

Когда я нажимаю "Сохранить" на этой странице, он вызывает метод контроллера/обновления проектов. После того, как я обновляю код, я хочу перенаправить на тот путь, который был включен до того, как я щелкнул, отредактировав конкретный проект. Другими словами, я хочу быть на одной странице с той же сортировкой.

Я видел link_to (: назад) и думал, что: back может работать в redirect_to (: back), но это не идет.

puts YAML::dump(:back) 
yields the following:
:back 

Любые идеи о том, как я могу заставить это работать. Это похоже на проблему, которую легко решить, но я новичок в RoR.

Ответ 1

В вашем действии редактирования сохраните запрашивающий URL-адрес в хэше сеанса, который доступен для нескольких запросов:

session[:return_to] ||= request.referer

Затем перенаправляйте его в действие обновления после успешного сохранения:

redirect_to session.delete(:return_to)

Ответ 2

Почему redirect_to(:back) не работает для вас, почему это не так?

redirect_to(:back) работает как прелесть для меня. Это просто короткое сокращение для redirect_to(request.env['HTTP_REFERER'])

http://apidock.com/rails/ActionController/Base/redirect_to (pre 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)

Ответ 3

Мне нравится метод Хайме, за одним исключением, мне лучше было пересобирать реферирования каждый раз:

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

Причина в том, что если вы редактируете несколько объектов, вы всегда будете перенаправлены обратно на первый URL, который вы сохранили в сеансе, с помощью метода Хайме. Например, допустим, у меня есть объекты Apple и Orange. Я редактирую Apple, а session[:return_to] устанавливается в референт этого действия. Когда я перехожу к редактированию апельсинов с использованием того же кода, session[:return_to] не будет установлен, потому что он уже определен. Поэтому, когда я обновляю Orange, меня отправят референту предыдущего действия Apple # edit.

Ответ 4

Так мы делаем это в нашем приложении

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.

Ответ 5

request.referer устанавливается Rack и устанавливается следующим образом:

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

Просто выполните redirect_to request.referer, и он всегда будет перенаправлен на настоящую страницу ссылок или корневой путь ('/'). Это важно при передаче тестов, которые не выполняются при непосредственном наступлении на конкретную страницу, на которой контроллер выдает redirect_to: back

Ответ 6

В рельсах 5, в соответствии с инструкциями в Rails Guides, вы можете использовать:

redirect_back(fallback_location: root_path)

Местоположение "назад" вытаскивается из заголовка HTTP_REFERER, который не гарантируется установкой браузером. Вот почему вы должны предоставить "fallback_location".

Ответ 7

Для тех, кого это интересует, вот моя реализация, расширяющая исходный ответ MBO (написанный против рельсов 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