使用设计动态设置用户时区

我已经构建了一个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 

所有这些都依赖于我自己编写的登录function。 但是,我知道我以后需要使用更好的用户管理系统,因为我自己的代码既没有做得好或者特别安全(我首先关注其他function)。

现在,我已经安装了设计,它可以很好地登录和注销,该网站的大多数其他function也可以工作。 但我不知道如何使用设计作为我的用户管理系统来处理时区支持。

一个想法是覆盖Devise中的SessionsController,添加对该隐藏时区字段的检查并将其值添加到user_session。 但我对这样做感到担心,感觉这是一个坏主意。

是否有更好的方法来添加此function,而无需强制用户在注册期间添加时区信息?

谢谢!

我管理一个调度软件,我们还检查浏览器的时区,然后将其保存在数据库中,并在应用程序控制器中使用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 

经过大约8个小时的反复试验后,我想出了一个现在可行的解决方案。 也许这可能是具有相似设置的人感兴趣的。

我首先在users表中添加一列,并在模型中添加相应的属性 – session_tz_offset

然后我开始用Warden回调攻击。 对我有用的是在ApplicationController中放置一个辅助方法,并使用之前的filter调用它:

 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