用设计动态设置用户时区 [英] Set user time zone dynamically with devise

查看:129
本文介绍了用设计动态设置用户时区的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经建立了一个可以帮助父母跟踪婴儿睡眠的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.zonefor 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆