Ответ 1
Использовать
session["#{scope}_return_to"]
Таким образом, вы можете использовать session["user_return_to"]
, если ваша модель для аутентификации - это Пользователь.
У меня есть страница, чей путь (например)/помещения/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], но какой лучший способ сделать это?
?return_to=/premises/92
к ссылкам [log in] и [register] и обнаружить это в RegistrationsController и SessionController и использовать эту информацию для настройки сеанса [: return_to]? Кажется, что это сработает, но и тяжело.Ни один из этих запахов не прав. Какой общепринятый способ настройки состояния для stored_location_for?
Использовать
session["#{scope}_return_to"]
Таким образом, вы можете использовать session["user_return_to"]
, если ваша модель для аутентификации - это Пользователь.
Я обнаружил, что вся эта притягательная перенаправляющая вещь довольно запутанна.
Где @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
Devise
ищет ключ "#{resource}_return_to"
в сеансе.
Здесь я цитирую API:
По умолчанию он сначала пытается найти действительный ключ
#{resource}_return_to
в сеанс, затем он возвращается к#{resource}_root_path
, в противном случае используетroot_path
.
вот лучшее, что я мог придумать. Работает отлично также с аутентификацией 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
Мне нравится следующее:
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
И извлеките это в модуль.