用设计动态设置用户时区 [英] Set user time zone dynamically with devise
问题描述
我已经建立了一个可以帮助父母跟踪婴儿睡眠的rails应用程序。为了正常工作,我必须支持不同的时区。为了避免用户带来时区错误,我创建了一个JavaScript,为登录表单添加了一个隐藏的字段,包括时区偏移。这是代码
I've built a rails app that helps parents keep track of their infants’ sleep. For it to work properly I've had to support different time zones. To avoid annoying the user with time zones, I've created a little javascript that adds a hidden field to the login form, including the timezone offset. Here's the code
var timeZoneField = $("input[name='user_tz_offset']");
if (timeZoneField.length) {
var browserDate = new Date();
var timeZoneOffsetSeconds = (browserDate.getTimezoneOffset() * 60) * -1;
$(timeZoneField).val(timeZoneOffsetSeconds);
}
使用该字段的数据,我将Time.zone设置为任何城市对应与此抵消。这样的事情会产生时区
With the data from that field I set the Time.zone to whatever city corresponds with that offset. Something like this generates the timezone
user_time_zone = ActiveSupport::TimeZone.[](params[:user_tz_offset].to_i)
session[:user_time_zone] = user_time_zone
最后,我在ApplicationController中设置时区。
Finally, I set the time zone in the ApplicationController.
def set_user_time_zone
if (session[:user_id])
Time.zone = session[:user_time_zone]
else
Time.zone = config.time_zone
end
end
所有这一切都依赖于我自己写的登录功能。但是,我知道我以后需要使用更好的用户管理系统,因为我自己的代码既不完善,也不是特别安全(我首先关注其他功能)。
All this relies on the login functionality, which I wrote myself. However, I knew that I would need to use a better user management system later, as my own code is neither well done or particularly secure (I was focusing on other functionality first).
现在,我已经安装了devise,它很好地登录和注销,该网站的大多数其他功能也是如此。但我不知道如何使用设计作为我的用户管理系统来接近时区支持。
Now, I've installed devise and it works well to log in and log out, most other functions of the site work as well. But I don't know how to approach the time zone support with devise as my user management system.
一个想法是覆盖Devise中的SessionsController,为该隐藏的时区字段添加一个检查,并将其值添加到user_session。但是我觉得这样做很担心,感觉好像是个坏主意。
One idea is to override the SessionsController in Devise, add a check for that hidden time zone field and add its value to the user_session. But I feel apprehensive about doing so, it feels like a bad idea.
有没有更好的方法来添加此功能,而不强制用户在注册期间添加时区信息?
Is there a better way to add this functionality, without forcing the user to add time zone information during registration?
谢谢!
推荐答案
经过大约八个小时的尝试和错误,我已经提出了一个解决方案。也许这可能是有兴趣的人有一个类似的设置。
After about eight hours of trial and error I have come up with a solution that works for now. Perhaps this may be of interest to someone with a similar setup.
我开始添加一个列到用户表和模型中的相应属性 - session_tz_offset
。
I started by adding a column to the users table and corresponding attribute in the model – session_tz_offset
.
然后,我开始用守望者回调进行黑客攻击。对我来说有用的是将一个帮助方法放在ApplicationController中,并用以下过滤器调用:
Then I started hacking around with Warden callbacks. What worked for me was to put a helper method in the ApplicationController, and call that with a before filter like this:
before_filter :authenticate_user!, :set_session_tz_offset_for_user
helper_method :set_user_time_zone, :set_session_tz_offset_for_user
def set_session_tz_offset_for_user
Warden::Manager.after_authentication do |user, auth, opts|
if (params[:user])
user.session_tz_offset = params[:user][:session_tz_offset]
user.save
end
end
end
在登录时,after_authentication回调触发多次,为什么我不知道。不是所有这些调用都有一个params [:user]字段,如果我没有检查它,我的应用程序崩溃了一个 undefined方法[]为nil:NilClass
错误。
The after_authentication callback fires several times during login, why is unknown to me. Not all of these calls have a params[:user] field, and if I didn't check for it, my application crashed with a undefined method [] for nil:NilClass
error.
当设置 session_tz_offset
时,我的其他控制器使用另一个帮助方法,也在ApplicationController中定义,以设置 Time.zone
当前请求:
When the session_tz_offset
is set, my other controllers use another helper method, also defined in ApplicationController to set Time.zone
for the current request:
def set_user_time_zone
if (user_signed_in?)
if(user_session[:time_zone])
Time.zone = user_session[:time_zone]
else
user_session[:time_zone] =
ActiveSupport::TimeZone.[](current_user.session_tz_offset)
Time.zone = user_session[:time_zone]
end
else
Time.zone = config.time_zone
end
end
这篇关于用设计动态设置用户时区的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!