我有一个页面的路径是(例如)/ premises / 92我正在显示“请[登录]或[注册]以获取更多信息”如果用户没有登录,我想要设计用户登录后返回相同/ premises / 92页面。
我已阅读其他帖子,我想我明白设计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],但最好的方法是什么?
?return_to=/premises/92
查询字符串,并在RegistrationsController和SessionsController中检测并使用该信息设置会话[:return_to]?这似乎有用,但也很苛刻。这些都闻不对劲。什么是为stored_location_for设置状态的普遍接受的技术?
答案 0 :(得分:25)
设计使用
session["#{scope}_return_to"]
如果您的身份验证模型是User,那么您可以使用session["user_return_to"]
。
答案 1 :(得分:8)
我发现整个设计重定向的东西很混乱。
@rorra表示Devise使用session["#{scope}_return_to"]
,他表示Devise默认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)
方法,因为设计的默认方法将为您执行所有重定向,如果它们没有可用的重定向URL,您将被重定向到资源根路径(通常是用户)根路径)如果不存在,您将被重定向到根路径。但是,如果没有可用的重定向网址,您希望自定义用户的发送位置,请将以下内容添加到您的application_contorller.rb(并相应地更改root_path
):
def after_sign_in_path_for(resource)
stored_location_for(resource) || root_path
end
答案 2 :(得分:6)
Devise
在会话中查找密钥"#{resource}_return_to"
。
我在这里引用API:
默认情况下,它首先尝试在中找到有效的
#{resource}_return_to
密钥 会话,然后它回退到#{resource}_root_path
,否则它 使用root_path
。
答案 3 :(得分:4)
这是我能想到的最好的。与facebook身份验证完美配合。通过在会话变量的前缀中添加更多限制,您可以删除越来越多的用户也不希望用户返回的路径(例如回调,启动页面,登录页面等)
#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
答案 4 :(得分:1)
我喜欢这个:
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
并将其提取到模块。