Подтвердить что ты не робот

Devise and stored_location_for: как сохранить возвращаемое местоположение?

У меня есть страница, чей путь (например)/помещения/92, на котором я показываю ", пожалуйста, войдите в систему или зарегистрируйтесь для получения дополнительной информации", если пользователь не вошел в систему, и я хочу, чтобы вернуть эту же страницу/помещение/92 после входа пользователя в систему.

Я читал другие сообщения, и я думаю, что я понимаю, как должен работать devise stored_location_for. В теории я мог бы добавить что-то вроде этого в ApplicationController:

def stored_location_for(resource)
  if (r = session[:return_to])
    session[:return_to] = nil
    r
  else
    super
  end
end

Мой вопрос: как/где настроить сеанс [: return_to]?

Я хочу установить сеанс [: return_to] только в том случае, если пользователь нажимает [log in] или [register], но какой лучший способ сделать это?

  • Украсить ссылки с помощью JavaScript? Это может сработать, но кажется жестоким.
  • Установите его в контроллере помещения перед тем, как сделать страницу? Это не кажется правильным: что, если пользователь не нажимает на ссылки [войти] или [зарегистрироваться]? Затем у меня есть session [: return_to], установленное на некоторое нечетное значение, которое может меня опрокинуть, если пользователь входит в систему с другой страницы.
  • Добавить строку запроса ?return_to=/premises/92 к ссылкам [log in] и [register] и обнаружить это в RegistrationsController и SessionController и использовать эту информацию для настройки сеанса [: return_to]? Кажется, что это сработает, но и тяжело.

Ни один из этих запахов не прав. Какой общепринятый способ настройки состояния для stored_location_for?

4b9b3361

Ответ 1

Использовать

session["#{scope}_return_to"]

Таким образом, вы можете использовать session["user_return_to"], если ваша модель для аутентификации - это Пользователь.

Ответ 2

Я обнаружил, что вся эта притягательная перенаправляющая вещь довольно запутанна.

Где @rorra говорит, что Devise использует session["#{scope}_return_to"], он означает, что Devise default after_sign_in_path_for(resource) будет использовать эту переменную с помощью метода stored_location_for(resource).

Итак, вы должны сохранить место, которое хотите сохранить в переменной session["#{scope}_return_to"], которая обычно будет session["user_return_to"]. Для этого разместите в приложении application_controller.rb следующее:

after_action :store_location

def store_location
  # store last url - this is needed for post-login redirect to whatever the user last visited.
  if (request.fullpath != "/users/sign_in" &&
      request.fullpath != "/users/sign_up" &&
      request.fullpath != "/users/password" &&
      request.fullpath != "/users/sign_out" &&
      !request.xhr?) # don't store ajax calls
    session["user_return_to"] = request.fullpath 
  end
end

В некоторых случаях вам не нужно определять метод after_sign_in_path_for(resource), так как метод default по умолчанию сделает все переадресации для вас, и если у них нет перенаправленного URL-адреса, вы будете перенаправлены на корневой путь ресурса (обычно пользовательский корневой путь), и если этого не существует, вы будете перенаправлены на корневой путь. Если, однако, вы хотите настроить, куда отправляется пользователь, если нет URL-адреса переадресации, добавьте следующее к вашему application_contorller.rb(и измените root_path соответственно):

def after_sign_in_path_for(resource)
  stored_location_for(resource) || root_path
end

Ответ 3

Devise ищет ключ "#{resource}_return_to" в сеансе.

Здесь я цитирую API:

По умолчанию он сначала пытается найти действительный ключ #{resource}_return_to в сеанс, затем он возвращается к #{resource}_root_path, в противном случае использует root_path.

Вот ссылка на API

Ответ 4

вот лучшее, что я мог придумать. Работает отлично также с аутентификацией facebook. добавив дополнительные ограничения на добавление URL-адресов в переменную сеанса, вы можете удалить все больше и больше путей, которые не хотите, чтобы пользователь тоже возвращался (например, обратные вызовы, страницы всплеска, целевые страницы и т.д.)

#ApplicationsController

after_filter :store_location

def store_location
  session[:previous_urls] ||= []
  # store unique urls only
  session[:previous_urls].prepend request.fullpath if session[:previous_urls].first != request.fullpath && request.fullpath != "/user" && request.fullpath != "/user/login" && request.fullpath != "/" && request.fullpath != "/user/logout" && request.fullpath != "/user/join" && request.fullpath != "/user/auth/facebook/callback"
  # For Rails < 3.2
  # session[:previous_urls].unshift request.fullpath if session[:previous_urls].first != request.fullpath 
  session[:previous_urls].pop if session[:previous_urls].count > 3
end

def after_sign_in_path_for(resource) 
  @url = session[:previous_urls].reverse.first
  if @url != nil
    "http://www.google.com" + @url
  else
    root_path
  end
end

Ответ 5

Мне нравится следующее:

class ApplicationController < AC::Base
  after_filter :clear_attached_unit # UPDATED

  protected
  def clear_attached_unit
    session[:attached_unit_path] = nil unless keep_attached_unit_path?
  end

  def keep_attached_unit_path? # UPDATED
    @keep_attached_unit_path   
  end                           
end


class UnitController < ApplicationController
  before_filter :attach_unit, :only => [:show]

  protected
  def attach_unit
    session[:attached_unit_path] = request.url if request.get? && !request.xhr?
  end
end

class SessionsController < Devise::SessionsController
  before_filter :keep_attached_unit_path! # UPDATED

  protected
  def keep_attached_unit_path! # UPDATED
    @keep_attached_unit_path = true
  end

  def after_sign_in_path_for(resource_or_scope)
    if resource_or_scope.is_a?(User) && session[:attached_unit_path].present?
      session[:attached_unit_path]
    else
      super
    end
  end 
end

И извлеките это в модуль.