tutorial rails gema ejemplos auth ruby-on-rails login devise timezone warden

ruby on rails - rails - Establecer la zona horaria del usuario de forma dinámica con el diseño



rspec rails devise (2)

Creé una aplicación de rieles que ayuda a los padres a llevar un registro del sueño de sus bebés. Para que funcione correctamente, he tenido que admitir diferentes zonas horarias. Para evitar molestar al usuario con husos horarios, he creado un pequeño javascript que agrega un campo oculto al formulario de inicio de sesión, incluido el desplazamiento de la zona horaria. Aquí está el código

var timeZoneField = $("input[name=''user_tz_offset'']"); if (timeZoneField.length) { var browserDate = new Date(); var timeZoneOffsetSeconds = (browserDate.getTimezoneOffset() * 60) * -1; $(timeZoneField).val(timeZoneOffsetSeconds); }

Con los datos de ese campo configuro Time.zone a cualquier ciudad que corresponda con ese desplazamiento. Algo así genera la zona horaria

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

Finalmente, configuré la zona horaria en ApplicationController.

def set_user_time_zone if (session[:user_id]) Time.zone = session[:user_time_zone] else Time.zone = config.time_zone end end

Todo esto depende de la funcionalidad de inicio de sesión, que yo misma escribí. Sin embargo, sabía que necesitaría utilizar un mejor sistema de administración de usuarios más adelante, ya que mi propio código no está bien hecho o es particularmente seguro (antes me enfocaba en otra funcionalidad).

Ahora, he instalado el dispositivo y funciona bien para iniciar y cerrar sesión, la mayoría de las funciones del sitio también funcionan. Pero no sé cómo acercarme al soporte de zona horaria con el diseño como mi sistema de administración de usuarios.

Una idea es anular el SessionsController en Devise, agregar un control para ese campo de zona horaria oculta y agregar su valor a user_session. Pero siento aprensión por hacerlo, parece una mala idea.

¿Hay una mejor manera de agregar esta funcionalidad sin forzar al usuario a agregar información de zona horaria durante el registro?

¡Gracias!


Administro un software de programación y también verificamos la zona horaria del navegador, pero luego solo la guardamos en la base de datos y la llamamos con un before_filter en el controlador de la aplicación.

#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


Después de aproximadamente ocho horas de prueba y error, he encontrado una solución que funciona por ahora. Quizás esto pueda ser de interés para alguien con una configuración similar.

Comencé agregando una columna a la tabla de usuarios y el atributo correspondiente en el modelo - session_tz_offset .

Luego comencé a hackear devoluciones de Warden. Lo que funcionó para mí fue poner un método auxiliar en ApplicationController, y llamarlo con un filtro anterior como este:

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

La devolución de llamada after_authentication se dispara varias veces durante el inicio de sesión, por qué me es desconocido. No todas estas llamadas tienen un campo params [: usuario], y si no lo comprobé, mi aplicación se bloqueó con un undefined method [] for nil:NilClass error undefined method [] for nil:NilClass .

Cuando se establece session_tz_offset , mis otros controladores usan otro método auxiliar, también definido en ApplicationController para establecer Time.zone para la solicitud actual:

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