Adding ability to detect timezone at UI side and get it within Rack/Rails via cookies with/o custom handler.
This gem created for usecase of loading detected TimeZone into Rails environment.
You can set cookie with TimeZone name at UI side(from Angular, React, Ember, Backbone or vanilla JS).
After that all XHR requests to your Rails/Rack backend can be identified by this Middleware.
In case when TimeZone name(s) is unsupported or key not found in cookies, middleware will fallback to defaults.
By default we are using ActiveSupport TimeZones, if AS is not installed and you haven't provided someone else, you will got empty TimeZone
hash with Warning message.
So we have no dependency on ActiveSupport
, but we'd like to use it.
Installation
Add this line to your application's Gemfile:
gem 'rack-time-zone-middleware'
And then execute:
$ bundle
Or install it yourself as:
$ gem install rack-time-zone-middleware
Logic in detail
- UI
- Use something like JsTz to determine users time-zone.
- Write time-zone name to cookie.
- AngularJS Example
- Ruby
- Use one of loading ways explained below (Usage).
- Provide cookie
key_name
with options, wich includes detected time-zone. - Provide enironment
key_name
with options, where you store its value. - Use
env['key_name']
to access saved value from your application or controller.
Usage
Sinatra/Padrino application
require 'rack/time-zone-middleware'
# Default TimeZone handler.
use Rack::TimeZoneMiddleware
# Configured TimeZone handler.
use Rack::TimeZoneMiddleware, default_tz: 'Europe/Moscow',
default_as_tz: 'Moscow',
time_zone_key: 'dummy.time_zone'
cookie_key: 'dummy.time_zone'
# Your own TimeZone handler. All options & instance methods is available through middleware parameter.
use Rack::TimeZoneMiddleware do |middleware, env|
request = ::Rack::Request.new(env)
time_zone = request&.cookies['dummy.time_zone'] || middleware.options[:default_tz]
env['dummy.time_zone'] = middleware.find_as_time_zone(time_zone)
middleware.app.call(env)
end
Rails application
# Default TimeZone handler.
config.middleware.use Rack::TimeZoneMiddleware
# Configured TimeZone handler.
config.middleware.use Rack::TimeZoneMiddleware, default_tz: 'Europe/Moscow',
default_as_tz: 'Moscow',
time_zone_key: 'dummy.time_zone'
cookie_key: 'dummy.time_zone'
# Your own TimeZone handler. All options & instance methods is available through middleware parameter.
config.middleware.use Rack::TimeZoneMiddleware do |middleware, env|
request = ::Rack::Request.new(env)
time_zone = request&.cookies['dummy.time_zone'] || middleware.options[:default_tz]
env['dummy.time_zone'] = middleware.find_as_time_zone(time_zone)
middleware.app.call(env)
end
In theory you can setup dynamic TimeZones detector(when its hash is managed from your Application, from Admin panel or something),
but in most of realizations what i saw, it is overhead.
Options
name | description |
---|---|
default_tz |
optional , TimeZone name fallback value (default: 'Europe/Moscow') |
default_as_tz |
optional , ActiveSupport::TimeZone key name fallback value (default: 'Moscow') |
cookie_key |
optional , Cookie key name (default: 'dummy.time_zone') |
time_zone_key |
optional , Environment key name (default: 'dummy.time_zone') |
time_zone_map |
optional , TimeZone Hash or lambda , like {'Moscow' => 'Europe/Moscow'} . If not provided ActiveSupport TZInfo map will be tried. |
AngularJS
TimeZone updater factory example via JsTz
web.services.factory('JsTz', ['ipCookie', function(ipCookie) {
return {
updateCookie: function() {
tz = jstz.determine();
name = tz.name();
ipCookie('dummy.time_zone', name, { path: '/', expires: 21 });
return name;
}
};
}]);
Dependencies:
Contributing
- Fork it ( https://github.com/merqlove/rack-time-zone-middleware/fork )
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create a new Pull Request
Bug reports and pull requests are welcome on GitHub at https://github.com/merqlove/rack-time-zone-middleware.
Testing
$ rake test
Development
To install this gem onto your local machine, run bundle exec rake install
. To release a new version, update the version number in version.rb
, and then run bundle exec rake release
, which will create a git tag for the version, push git commits and tags, and push the .gem
file to rubygems.org.
Copyright (c) 2016 Alexander Merkulov
MIT License