我正在使用Rails + Devise进行登录和注册,但我的前端绝大多数都使用了角度路由。当有人试图在没有登录的情况下转到特定页面时,我希望在成功登录后重定向它们。通常,这将是在会话中存储路径和修改after_sign_in_path_for方法的简单问题。但是,我似乎无法找到有效获取实际路径的Rails方法。我有信心我可以通过JS做到这一点,然后将其存储为cookie(或者真的是Angular),但我更喜欢将它保存在Rails中。有没有一种方法我会遗漏给我一些实际的路径,包括/#/ what / whatever?
以下似乎应该有效:
request.original_url
基于此(http://api.rubyonrails.org/classes/ActionDispatch/Request.html)
但它没有返回主题标签或以下参数。
也许是因为这个人所说的话(AngularJS routing without the hash '#')
#是旧的浏览器短路,不会触发请求, 它允许许多js框架构建自己的客户端 重新路由。
有没有一种干净的方法来收集Rails中的完整路径,还是需要进入Angular / JS?
答案 0 :(得分:4)
我遇到了同样的问题但是使用了Backbone。问题是浏览器不会将URL的锚点部分发送到服务器,因此Rails无法处理此问题,只能处理前端的JS。
我发布了适合我的解决方法。
在登录页面中添加此javascript代码段(最有可能在app / views / sessions / new.html.haml中)
:javascript
// keeping the hash route into a cookie to retrieve it after sign in redirect
cname = 'hash_route'
cvalue = window.location.hash
// checking if the hash value is blank, don't overwrite the cookie
// this check covers the case of user giving wrong credentials in login
// then successfully login within the expiration time of the cookie
// other cases that aren't supported are relatively rare
if(cvalue.length){
var d = new Date();
d.setTime(d.getTime() + (3*60*1000)); // enough time to log in
var expires = "expires="+d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
在SessionsController #create中(或者你可以覆盖Devise方法" after_sign_in_path_for")
def create
# ------- Devise code --------
self.resource = warden.authenticate(auth_options)
set_flash_message(:notice, :signed_in) if is_navigational_format?
sign_in(resource_name, resource)
# ------- This is the code --------
# handling the case of redirecting to a link that had a hash route
location = after_sign_in_path_for(resource)
if cookies[:hash_route].present?
location+= cookies[:hash_route]
cookies.delete :hash_route
end
respond_with resource, :location => location
end
我希望这会有所帮助。
答案 1 :(得分:4)
非常感谢@bero这个美丽的答案。它运作得很好。
我将使用以下变体添加2美分:
<!-- app/views/sessions/new.html.erb: -->
<script type="text/javascript">
cname = 'hash_route'
// Added a .replace(/^#/, '') here to store '/hash_path' instead of '#/hash_path'
cvalue = window.location.hash.replace(/^#/, '');
if(cvalue.length){
var d = new Date();
d.setTime(d.getTime() + (3*60*1000)); // enough time to log in
var expires = "expires="+d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires;
}
</script>
在红宝石方面:
# application_controller.rb
def after_sign_in_path_for(resource)
if cookies[:hash_route].present?
anchor = cookies[:hash_route]
cookies.delete :hash_route
end
webpages_app_path(anchor: anchor)
end
我更喜欢将path_helper
与anchor
一起使用并覆盖after_sign_in_path_for
(您可能已经拥有),而不是自定义Devise控制器。
但整件事情都是一样的。