Set user time zone using application

I created a rails app that helps parents keep track of how their children sleep. For it to work correctly, I had to maintain different time zones. To avoid annoying the user with time zones, I created a little javascript that adds a hidden field to the login form, including the time zone offset. Here is 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); } 

With the data from this field, I set Time.zone to any city that matches this offset. Something like this generates a time zone

 user_time_zone = ActiveSupport::TimeZone.[](params[:user_tz_offset].to_i) session[:user_time_zone] = user_time_zone 

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 

It all depends on the input functionality that I wrote myself. However, I knew that I would need to use a more advanced user management system later, since my own code is neither good nor safe (at first I focused on other functions).

Now I installed the program, and it works well for logging in and logging out, most of the other functions of the site work. But I don’t know how to approach time zone support using my user management system.

One idea is to override SessionController in Devise, add validation for this hidden timezone field, and add its value to user_session. But I feel wary of this, it seems like a bad idea.

Is there a better way to add this functionality without forcing the user to add time zone information during registration?

Thanks!

+4
source share
2 answers

After about eight hours of trial and error, I came up with a solution that works now. Perhaps this might be interesting for someone with a similar setup.

I started by adding a column to the users table and the corresponding attribute in the model - session_tz_offset .

Then I began to deal with Warden callbacks. What worked for me is to put a helper method in the ApplicationController and call it with a filter before the following:

 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 

The after_authentication callback fires several times during login, why I don’t know. Not all of these calls have a params [: user] field, and if I did not check it, my application crashed with an undefined method [] for nil:NilClass .

When session_tz_offset 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 
+2
source

I manage the scheduling software, and we also check the browser time zone, and then just save it in the database and call it using before_filter in the application controller.

 #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 
+2
source

Source: https://habr.com/ru/post/1445757/


All Articles