Перенаправление на указанный URL после POST в Rails

Очень часто у меня на веб-странице есть форма, которую пользователь отправляет в Pils, PUT или DELETE в Rails, где я хочу, чтобы она перенаправляла на указанный URL, если отправка прошла успешно. Я обычно делаю скрытый дополнительный параметр под названием to с пути как /users, Таким образом, если отправка формы не удалась, она просто остается в этой форме, но если это происходит успешно, браузер перенаправляется на /users,

Я хотел бы автоматически искать этот параметр и всегда перенаправлять его, если отправка формы прошла успешно в каком-либо контроллере / действии. Я положу это в ApplicationController в пределах after_action?

class ApplicationController < ActionController::Base
  after_action :redirect_if_success

  private
  def redirect_if_success
    redirect_to params[:to] if params[:to]
  end
end

Я думаю, я могу проверить объект запроса, если это было действие POST, PUT или DELETE. Как я знаю, что представление было успешным? Будет redirect_to в after_action переопределить любой redirect_toв форме контроллера?

2 ответа

Я думаю, что решение заключается в том, чтобы определить частный метод redirect_if_success в контроллере приложения, но вызвать его непосредственно в действии. например:

class ApplicationController < ActionController::Base

  private
  def redirect_if_success(default_ur)
     redirect_to params[:to] || default_url
     # or similar logic
  end
end

class UserController < ApplicationController::Base

  def create
    redirect_if_success("/users") if @user.save
  end
end

Я бы создал вспомогательный метод

def redirect_to_location
  redirect_to params[:to] && params[:to].present?
end

и я бы использовал это явно в каждом действии, я хочу это поведение.

Тем не менее, вы могли бы немного поэкспериментировать. Чтобы сохранить эту логику в after_action, вам нужно установить какое-то состояние, которое сообщит вам, нужно ли вам перенаправить или нет.

Вы могли бы сделать:

def save
  if @user.save
    @follow_redirect = true
  end
end

и проверьте флаг @follow_redirect в фильтре after_action. Не похоже на очень красивое решение, но оно будет работать.

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

Так что вы можете проверить:

если вам нужно перенаправить (действие post/put/delete) и params[:to] присутствует и если вы еще не перенаправили / перенаправили

# this is not a copy-paste code but rather to demonstrate an idea
class ApplicationController < ActionController::Base 
  after_action :redirect_to_location

  protected 

  def is_redirectable?
    %w{post put delete}.include?(request.method) && params[:to].present?
  end

  def already_redirected?
    !response.status.nil? # not sure if it would work at all 
  end

  def redirect_to_location
     redirect_to params[:to] if is_redirectable? && !already_redirected?
  end
end