我开发了一个rails应用程序,可以帮助父母跟踪婴儿的睡眠情况。为了让它正常工作,我不得不支持不同的时区。为了避免使用时区打扰用户,我创建了一个小javascript,它在登录表单中添加了一个隐藏字段,包括时区偏移量。这是代码
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设置为与该偏移相对应的任何城市。类似这样的东西会生成时区
user_time_zone = ActiveSupport::TimeZone.[](params[:user_tz_offset].to_i)
session[:user_time_zone] = user_time_zone
最后,我在ApplicationController中设置了时区。
def set_user_time_zone
if (session[:user_id])
Time.zone = session[:user_time_zone]
else
Time.zone = config.time_zone
end
end
所有这些都依赖于我自己编写的登录功能。然而,我知道以后我需要使用一个更好的用户管理系统,因为我自己的代码既做得不好,也不特别安全(我首先关注其他功能)。
现在,我已经安装了design,它可以很好地登录和注销,网站的大多数其他功能也可以。但我不知道如何使用design作为我的用户管理系统来实现时区支持。
一个想法是覆盖Devise中的SessionsController,添加对该隐藏时区字段的检查,并将其值添加到user_session中。但我对这样做感到担忧,这感觉是个坏主意。
有没有更好的方法可以添加此功能,而不必强迫用户在注册期间添加时区信息?
谢谢!
我管理一个调度软件,我们还检查浏览器的时区,但只需将其保存在数据库中,并在应用程序控制器中使用before_filter进行调用。
#Application Controller
before_filter :set_time_zone
private
def set_time_zone
if current_user
Time.zone = current_user.time_zone if current_user.time_zone
end
end
经过大约八个小时的反复试验,我提出了一个目前有效的解决方案。也许这可能会引起具有类似设置的人的兴趣。
我首先在users表中添加一列,并在模型中添加相应的属性session_tz_offset
。
然后我开始用典狱长的回拨电话到处乱搞。对我来说,有效的方法是在ApplicationController中放入一个helper方法,并用这样的before过滤器调用它:
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 method [] for nil:NilClass
错误而崩溃。
当设置session_tz_offset
时,我的其他控制器使用另一个助手方法,也在ApplicationController中定义,为当前请求设置Time.zone
:
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