user_time_zones 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +25 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/CHANGELOG.md +6 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +21 -0
- data/README.md +158 -0
- data/Rakefile +6 -0
- data/app/assets/javascripts/user_time_zones.js +35 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/generators/user_time_zones/helpers.rb +61 -0
- data/lib/generators/user_time_zones/install/install_generator.rb +92 -0
- data/lib/generators/user_time_zones/install/templates/db/migrate/add_time_zone_to_users.rb +5 -0
- data/lib/user_time_zones/controller.rb +17 -0
- data/lib/user_time_zones/helper.rb +26 -0
- data/lib/user_time_zones/user.rb +27 -0
- data/lib/user_time_zones/version.rb +3 -0
- data/lib/user_time_zones.rb +10 -0
- data/user_time_zones.gemspec +38 -0
- metadata +187 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 01f8f2108c682b94569e141475a14e2caa1b8a2a
|
4
|
+
data.tar.gz: 94e4f6edaec4484699e3fff8669836d04ba986d0
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 469266a364b0b1d944028abadc9bf3d232e1a8c625147a511491848307b3b2b08d5ad1460bd839ccbfcac3574d8914a4edf2d380fd95472ff5d35226072affa5
|
7
|
+
data.tar.gz: bb016157dc0327316976e29c8bc5adfdc4ad0d9c0072f3c11dae6e9ae97ad56ddda4c40af269559d455f3a5740e818264c865490dce04ecf1d677bca3df9463e
|
data/.gitignore
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
/.bundle/
|
2
|
+
/.yardoc
|
3
|
+
/Gemfile.lock
|
4
|
+
/_yardoc/
|
5
|
+
/coverage/
|
6
|
+
/doc/
|
7
|
+
/pkg/
|
8
|
+
/spec/reports/
|
9
|
+
/tmp/
|
10
|
+
|
11
|
+
log/*.log
|
12
|
+
|
13
|
+
/spec/dummy/db/*.sqlite3
|
14
|
+
/spec/dummy/db/*.sqlite3-journal
|
15
|
+
/spec/dummy/log/*.log
|
16
|
+
/spec/dummy/tmp/
|
17
|
+
/spec/dummy/log/test.log
|
18
|
+
/spec/dummy/log/development.log
|
19
|
+
/.idea
|
20
|
+
|
21
|
+
user_time_zones-*.gem
|
22
|
+
*.gemfile.lock
|
23
|
+
|
24
|
+
# rspec failure tracking
|
25
|
+
.rspec_status
|
data/.rspec
ADDED
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,74 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
In the interest of fostering an open and welcoming environment, we as
|
6
|
+
contributors and maintainers pledge to making participation in our project and
|
7
|
+
our community a harassment-free experience for everyone, regardless of age, body
|
8
|
+
size, disability, ethnicity, gender identity and expression, level of experience,
|
9
|
+
nationality, personal appearance, race, religion, or sexual identity and
|
10
|
+
orientation.
|
11
|
+
|
12
|
+
## Our Standards
|
13
|
+
|
14
|
+
Examples of behavior that contributes to creating a positive environment
|
15
|
+
include:
|
16
|
+
|
17
|
+
* Using welcoming and inclusive language
|
18
|
+
* Being respectful of differing viewpoints and experiences
|
19
|
+
* Gracefully accepting constructive criticism
|
20
|
+
* Focusing on what is best for the community
|
21
|
+
* Showing empathy towards other community members
|
22
|
+
|
23
|
+
Examples of unacceptable behavior by participants include:
|
24
|
+
|
25
|
+
* The use of sexualized language or imagery and unwelcome sexual attention or
|
26
|
+
advances
|
27
|
+
* Trolling, insulting/derogatory comments, and personal or political attacks
|
28
|
+
* Public or private harassment
|
29
|
+
* Publishing others' private information, such as a physical or electronic
|
30
|
+
address, without explicit permission
|
31
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
32
|
+
professional setting
|
33
|
+
|
34
|
+
## Our Responsibilities
|
35
|
+
|
36
|
+
Project maintainers are responsible for clarifying the standards of acceptable
|
37
|
+
behavior and are expected to take appropriate and fair corrective action in
|
38
|
+
response to any instances of unacceptable behavior.
|
39
|
+
|
40
|
+
Project maintainers have the right and responsibility to remove, edit, or
|
41
|
+
reject comments, commits, code, wiki edits, issues, and other contributions
|
42
|
+
that are not aligned to this Code of Conduct, or to ban temporarily or
|
43
|
+
permanently any contributor for other behaviors that they deem inappropriate,
|
44
|
+
threatening, offensive, or harmful.
|
45
|
+
|
46
|
+
## Scope
|
47
|
+
|
48
|
+
This Code of Conduct applies both within project spaces and in public spaces
|
49
|
+
when an individual is representing the project or its community. Examples of
|
50
|
+
representing a project or community include using an official project e-mail
|
51
|
+
address, posting via an official social media account, or acting as an appointed
|
52
|
+
representative at an online or offline event. Representation of a project may be
|
53
|
+
further defined and clarified by project maintainers.
|
54
|
+
|
55
|
+
## Enforcement
|
56
|
+
|
57
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
58
|
+
reported by contacting the project team at tomichj@gmail.com. All
|
59
|
+
complaints will be reviewed and investigated and will result in a response that
|
60
|
+
is deemed necessary and appropriate to the circumstances. The project team is
|
61
|
+
obligated to maintain confidentiality with regard to the reporter of an incident.
|
62
|
+
Further details of specific enforcement policies may be posted separately.
|
63
|
+
|
64
|
+
Project maintainers who do not follow or enforce the Code of Conduct in good
|
65
|
+
faith may face temporary or permanent repercussions as determined by other
|
66
|
+
members of the project's leadership.
|
67
|
+
|
68
|
+
## Attribution
|
69
|
+
|
70
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
71
|
+
available at [http://contributor-covenant.org/version/1/4][version]
|
72
|
+
|
73
|
+
[homepage]: http://contributor-covenant.org
|
74
|
+
[version]: http://contributor-covenant.org/version/1/4/
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2017 Justin Tomich
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,158 @@
|
|
1
|
+
# UserTimeZones
|
2
|
+
|
3
|
+
UserTimeZones provides an easyway to work with multiple user time zones.
|
4
|
+
|
5
|
+
UserTimeZones is intended to be small, simple, and well-tested. A large percentage of applications will require
|
6
|
+
support for per-user time zones which this gem can assist with. The solution is simple; you could implement it
|
7
|
+
yourself, but this library will let you implement the solution the same way, every time, without having
|
8
|
+
to expend excess effort.
|
9
|
+
|
10
|
+
## Requirements
|
11
|
+
|
12
|
+
* Ruby on Rails 5
|
13
|
+
* a user model (`User` by default, but any class name is supported)
|
14
|
+
* a `current_user` helper
|
15
|
+
|
16
|
+
## Install
|
17
|
+
|
18
|
+
To get started, add the UserTimeZones gem to your `Gemfile` and run `bundle install` to install it:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem 'user_time_zones'
|
22
|
+
```
|
23
|
+
|
24
|
+
Run the install generator:
|
25
|
+
```sh
|
26
|
+
rails generate user_time_zones:install
|
27
|
+
```
|
28
|
+
|
29
|
+
Apply the migration the generator created:
|
30
|
+
```sh
|
31
|
+
rails db:migrate
|
32
|
+
```
|
33
|
+
|
34
|
+
The install generator will:
|
35
|
+
* Create a migration that adds a `time_zone` column to your user table.
|
36
|
+
* Insert `include UserTimeZones::User` into your `User` model.
|
37
|
+
* Insert `include UserTimeZones::Controller` into your `ApplicationController`.
|
38
|
+
|
39
|
+
You may optionally include the javascript to guess a new user's timezone in your `application.js`:
|
40
|
+
```javascript
|
41
|
+
//= require user_time_zones
|
42
|
+
```
|
43
|
+
|
44
|
+
|
45
|
+
##### Different user model?
|
46
|
+
|
47
|
+
To specify an alternate user model (something other than `User`), use the --model flag. For example, if your user model
|
48
|
+
is named `Profile`:
|
49
|
+
|
50
|
+
```sh
|
51
|
+
rails generate user_time_zones:install --model Profile
|
52
|
+
```
|
53
|
+
|
54
|
+
|
55
|
+
## Use
|
56
|
+
|
57
|
+
UserTimeZones has two use cases:
|
58
|
+
* calculate the user's time zone when creating a user account
|
59
|
+
* apply the user's time zone for the duration of a controller action
|
60
|
+
|
61
|
+
### Calculate the time zone offset for new users
|
62
|
+
|
63
|
+
Include the UserTimeZones javascript in your `application.js` and use the form helper `guess_tz_offset_field` to
|
64
|
+
generate a hidden field, `:time_zone_offset`. The included javascript will set `:time_zone_offset` to the user's
|
65
|
+
time zone offset.
|
66
|
+
|
67
|
+
A `guess_tz_offset_field_tag` helper is also included.
|
68
|
+
|
69
|
+
Example form for a new user that includes the `time_zone_offset`:
|
70
|
+
```erbruby
|
71
|
+
<%= form_for @user, method: :post do |f| %>
|
72
|
+
<%= f.guess_tz_offset_field %>
|
73
|
+
<%= f.text_field :first_name %>
|
74
|
+
# ...
|
75
|
+
<% end %>
|
76
|
+
```
|
77
|
+
|
78
|
+
The javascript will calculate the time zone offset, e.g. -9, and set it as a value for the `time_zone_offset` field.
|
79
|
+
The javascript looks for any element with the attribute `data-behavior="guess-time-zone-offset"`.
|
80
|
+
|
81
|
+
Your user controller will need to permit attribute `:time_zone_offset`.
|
82
|
+
|
83
|
+
|
84
|
+
##### Why guess the time zone?
|
85
|
+
|
86
|
+
You could ask your new user to pick their time zone from a drop-down during sign-up. That works. But reducing
|
87
|
+
the complexity of sign-up almost always increases user conversion rate. By determining the user's time zone
|
88
|
+
offset and making a guess at their timezone, that's one less thing you have to require from your user at sign up.
|
89
|
+
|
90
|
+
You can allow the user to edit their time zone later on, in user#edit or elsewhere.
|
91
|
+
|
92
|
+
|
93
|
+
### Applying the user's time zone
|
94
|
+
|
95
|
+
For each action a user takes, UserTimeZones will set the time zone to a user's `:time_zone` .
|
96
|
+
This is done in `ApplcationController` with an `around_action` that calls `Time.use_zone`.
|
97
|
+
|
98
|
+
|
99
|
+
### The User model and time zones
|
100
|
+
|
101
|
+
UserTimeZones gives the user a new attribute, `time_zone`, and new methods `time_zone_offset` and `time_zone_offset=`.
|
102
|
+
The `time_zone` user attribute is the name of a `ActiveSupport::TimeZone`. The offset methods are the offset of
|
103
|
+
the time zone from `UTC`, in hours.
|
104
|
+
|
105
|
+
Example:
|
106
|
+
```ruby
|
107
|
+
>> user.time_zone_offset = -8
|
108
|
+
=> -8
|
109
|
+
>> user.time_zone
|
110
|
+
=> "Pacific Time (US & Canada)"
|
111
|
+
>> user.time_zone = "Alaska"
|
112
|
+
=> "Alaska"
|
113
|
+
>> user.time_zone_offset
|
114
|
+
=> -9
|
115
|
+
```
|
116
|
+
|
117
|
+
|
118
|
+
### A summary of do’s and don'ts with time zones
|
119
|
+
|
120
|
+
Some methods are a lot more time zone friendly than others.
|
121
|
+
|
122
|
+
DON’T USE
|
123
|
+
* Time.now
|
124
|
+
* Date.today
|
125
|
+
* Date.today.to_time
|
126
|
+
* Time.parse("2015-07-04 17:05:37")
|
127
|
+
* Time.strptime(string, "%Y-%m-%dT%H:%M:%S%z")
|
128
|
+
|
129
|
+
DO USE
|
130
|
+
* Time.current
|
131
|
+
* 2.hours.ago
|
132
|
+
* Time.zone.today
|
133
|
+
* Date.current
|
134
|
+
* 1.day.from_now
|
135
|
+
* Time.zone.parse("2015-07-04 17:05:37")
|
136
|
+
* Time.strptime(string, "%Y-%m-%dT%H:%M:%S%z").in_time_zone
|
137
|
+
|
138
|
+
See https://robots.thoughtbot.com/its-about-time-zones for more information.
|
139
|
+
|
140
|
+
See Basecamp's [local_time](https://github.com/basecamp/local_time) library for easy, time zone sensitive,
|
141
|
+
cache friendly client-side local time.
|
142
|
+
|
143
|
+
|
144
|
+
## Contributing
|
145
|
+
|
146
|
+
[Bug reports] and [pull requests] are welcome on GitHub at https://github.com/tomichj/user_time_zones.
|
147
|
+
This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to
|
148
|
+
adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
149
|
+
|
150
|
+
You can contact me directly via twitter at [@JustinTomich](https://twitter.com/justintomich).
|
151
|
+
|
152
|
+
[Bug reports]: https://github.com/tomichj/authenticate/issues
|
153
|
+
[pull requests]: https://github.com/tomichj/user_time_zones/pulls
|
154
|
+
|
155
|
+
## License
|
156
|
+
|
157
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
158
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
// Mutator, watches for an element with [data-behavior~=guess-time-zone-offset].
|
2
|
+
// Sets best guess at timezone to that element.
|
3
|
+
var MutationObserver, observe, observer, guessTimeZoneOffset, selector;
|
4
|
+
|
5
|
+
MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
|
6
|
+
observer = void 0;
|
7
|
+
selector = "[data-behavior~=guess-time-zone-offset]";
|
8
|
+
|
9
|
+
guessTimeZoneOffset = function(field) {
|
10
|
+
if (field) {
|
11
|
+
field.value = -(new Date().getTimezoneOffset() / 60);
|
12
|
+
}
|
13
|
+
};
|
14
|
+
|
15
|
+
observe = function() {
|
16
|
+
if (!observer) {
|
17
|
+
observer = new MutationObserver(check);
|
18
|
+
observer.observe(window.document.documentElement, {childList: true, subtree: true});
|
19
|
+
}
|
20
|
+
check();
|
21
|
+
};
|
22
|
+
|
23
|
+
check = function() {
|
24
|
+
var element, elements;
|
25
|
+
elements = window.document.querySelectorAll(selector);
|
26
|
+
for (var i = 0; i < elements.length; i++) {
|
27
|
+
element = elements[i];
|
28
|
+
if (!element.ready) {
|
29
|
+
element.ready = true;
|
30
|
+
guessTimeZoneOffset.call(element, element);
|
31
|
+
}
|
32
|
+
}
|
33
|
+
};
|
34
|
+
|
35
|
+
(function() { return observe(); })();
|
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "user_time_zones"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start(__FILE__)
|
data/bin/setup
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module UserTimeZone
|
2
|
+
module Generators
|
3
|
+
module Helpers
|
4
|
+
private
|
5
|
+
|
6
|
+
# Either return the model passed in a classified form or return the default "User".
|
7
|
+
def model_class_name
|
8
|
+
options[:model] ? options[:model].classify : 'User'
|
9
|
+
end
|
10
|
+
|
11
|
+
def model_path
|
12
|
+
@model_path ||= File.join('app', 'models', "#{file_path}.rb")
|
13
|
+
end
|
14
|
+
|
15
|
+
def file_path
|
16
|
+
model_name.underscore
|
17
|
+
end
|
18
|
+
|
19
|
+
def namespace
|
20
|
+
Rails::Generators.namespace if Rails::Generators.respond_to?(:namespace)
|
21
|
+
end
|
22
|
+
|
23
|
+
def namespaced?
|
24
|
+
!namespace.nil?
|
25
|
+
end
|
26
|
+
|
27
|
+
def model_name
|
28
|
+
if namespaced?
|
29
|
+
[namespace.to_s] + [model_class_name]
|
30
|
+
else
|
31
|
+
[model_class_name]
|
32
|
+
end.join('::')
|
33
|
+
end
|
34
|
+
|
35
|
+
def table_name
|
36
|
+
@table_name ||= begin
|
37
|
+
base = plural_name
|
38
|
+
(class_path + [base]).join('_')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def class_path
|
43
|
+
@class_path
|
44
|
+
end
|
45
|
+
|
46
|
+
def singular_name
|
47
|
+
@file_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def plural_name
|
51
|
+
singular_name.pluralize
|
52
|
+
end
|
53
|
+
|
54
|
+
def assign_names!(name) #:nodoc:
|
55
|
+
@class_path = name.include?('/') ? name.split('/') : name.split('::')
|
56
|
+
@class_path.map!(&:underscore)
|
57
|
+
@file_name = @class_path.pop
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
require 'rails/generators/base'
|
2
|
+
require 'rails/generators/active_record'
|
3
|
+
require 'generators/user_time_zones/helpers'
|
4
|
+
|
5
|
+
module UserTimeZones
|
6
|
+
module Generators
|
7
|
+
class InstallGenerator < Rails::Generators::Base
|
8
|
+
include Rails::Generators::Migration
|
9
|
+
include UserTimeZone::Generators::Helpers
|
10
|
+
|
11
|
+
source_root File.expand_path('../templates', __FILE__)
|
12
|
+
class_option :model,
|
13
|
+
optional: true,
|
14
|
+
type: :string,
|
15
|
+
banner: 'model',
|
16
|
+
desc: "Specify the model class name if you will use anything other than 'User'"
|
17
|
+
|
18
|
+
def initialize(*)
|
19
|
+
super
|
20
|
+
assign_names!(model_class_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def verify
|
24
|
+
if options[:model] && !File.exist?(model_path)
|
25
|
+
puts "Exiting: the model class you specified, #{options[:model]}, is not found."
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy_migration_files
|
31
|
+
copy_migration 'add_time_zone_to_users.rb'
|
32
|
+
end
|
33
|
+
|
34
|
+
def inject_into_user_model
|
35
|
+
if File.exist? model_path
|
36
|
+
inject_into_class(model_path, model_class_name, " include UserTimeZones::User\n\n")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def inject_into_application_controller
|
41
|
+
inject_into_class(
|
42
|
+
'app/controllers/application_controller.rb',
|
43
|
+
ApplicationController,
|
44
|
+
" include UserTimeZones::Controller\n\n"
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def copy_migration(migration_name, config = {})
|
53
|
+
# puts "migration_version: #{migration_version}"
|
54
|
+
unless migration_exists?(migration_name)
|
55
|
+
migration_template(
|
56
|
+
"db/migrate/#{migration_name}",
|
57
|
+
"db/migrate/#{migration_name}",
|
58
|
+
config.merge(migration_version: migration_version)
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# If Rails 5, then include the migration version. Rails 4, no version.
|
64
|
+
def migration_version
|
65
|
+
if Rails.version >= '5.0.0'
|
66
|
+
"[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
# for generating a timestamp when using `create_migration`
|
71
|
+
def self.next_migration_number(dir)
|
72
|
+
ActiveRecord::Generators::Base.next_migration_number(dir)
|
73
|
+
end
|
74
|
+
|
75
|
+
def migration_exists?(name)
|
76
|
+
existing_migrations.include?(name)
|
77
|
+
end
|
78
|
+
|
79
|
+
def existing_migrations
|
80
|
+
@existing_migrations ||= Dir.glob('db/migrate/*.rb').map do |file|
|
81
|
+
migration_name_without_timestamp(file)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def migration_name_without_timestamp(file)
|
86
|
+
file.sub(%r{^.*(db/migrate/)(?:\d+_)?}, '')
|
87
|
+
end
|
88
|
+
|
89
|
+
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module UserTimeZones
|
2
|
+
module Controller
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
around_action :user_time_zone, if: :current_user
|
7
|
+
end
|
8
|
+
|
9
|
+
protected
|
10
|
+
|
11
|
+
# Use this time zone for the duration of this controller action
|
12
|
+
def user_time_zone(&block)
|
13
|
+
Time.use_zone(current_user.time_zone, &block) unless current_user.time_zone.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActionView
|
2
|
+
module Helpers
|
3
|
+
|
4
|
+
module FormHelper
|
5
|
+
def guess_tz_offset_field(object_name, options = {})
|
6
|
+
method = :time_zone_offset
|
7
|
+
options['data-behavior'] = 'guess-time-zone-offset'
|
8
|
+
hidden_field(object_name, method, options)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
module FormTagHelper
|
13
|
+
def guess_tz_offset_field_tag(name = 'user[time_zone_offset]', value = nil, options = {})
|
14
|
+
options['data-behavior'] = 'guess-time-zone-offset'
|
15
|
+
hidden_field_tag(name, value, options)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class ActionView::Helpers::FormBuilder #:nodoc:
|
23
|
+
def guess_tz_offset_field(options = {})
|
24
|
+
@template.guess_tz_offset_field(@object_name, objectify_options(options))
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'active_support/time'
|
2
|
+
|
3
|
+
module UserTimeZones
|
4
|
+
module User
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
validates_inclusion_of :time_zone, in: ActiveSupport::TimeZone.all.map{ |tz| tz.name }
|
9
|
+
end
|
10
|
+
|
11
|
+
#
|
12
|
+
# Take time zone expressed as an offset.
|
13
|
+
# Only really used
|
14
|
+
#
|
15
|
+
def time_zone_offset=(time_zone_offset)
|
16
|
+
offset = "#{time_zone_offset}".to_i
|
17
|
+
self.time_zone = ActiveSupport::TimeZone[offset].name
|
18
|
+
end
|
19
|
+
|
20
|
+
def time_zone_offset
|
21
|
+
return nil if time_zone.nil?
|
22
|
+
tz ||= Time.find_zone! time_zone
|
23
|
+
tz.utc_offset / 3600 unless (tz.nil? || tz.utc_offset.nil?)
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
$LOAD_PATH.push File.expand_path('../lib', __FILE__)
|
2
|
+
|
3
|
+
require 'user_time_zones/version'
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = 'user_time_zones'
|
7
|
+
spec.version = UserTimeZones::VERSION
|
8
|
+
spec.authors = ['Justin Tomich']
|
9
|
+
spec.email = ['justin@tomich.org']
|
10
|
+
spec.homepage = 'http://github.com/tomichj/user_time_zones'
|
11
|
+
spec.summary = 'Provide time zone support for User models in Rails applications'
|
12
|
+
spec.description = 'Provide time zone support for User models in Rails applications'
|
13
|
+
spec.license = 'MIT'
|
14
|
+
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.test_files = `git ls-files -- {spec}/*`.split("\n")
|
20
|
+
|
21
|
+
spec.require_paths = ['lib']
|
22
|
+
|
23
|
+
spec.extra_rdoc_files = %w(LICENSE.txt README.md CHANGELOG.md)
|
24
|
+
spec.rdoc_options = ['--charset=UTF-8']
|
25
|
+
|
26
|
+
# probably reduce to railtie or ...
|
27
|
+
spec.add_dependency 'rails', '>= 5.0', '< 5.2'
|
28
|
+
|
29
|
+
spec.add_development_dependency 'bundler', '~> 1.14'
|
30
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
31
|
+
spec.add_development_dependency 'rspec-rails', '~> 3.0'
|
32
|
+
spec.add_development_dependency 'sqlite3', '~> 1.3'
|
33
|
+
spec.add_development_dependency 'capybara'
|
34
|
+
spec.add_development_dependency 'factory_girl'
|
35
|
+
spec.add_development_dependency 'timecop'
|
36
|
+
|
37
|
+
spec.required_ruby_version = Gem::Requirement.new('>= 2.0')
|
38
|
+
end
|
metadata
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: user_time_zones
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Justin Tomich
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-06-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '5.0'
|
20
|
+
- - "<"
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '5.2'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '5.0'
|
30
|
+
- - "<"
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '5.2'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: bundler
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - "~>"
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '1.14'
|
40
|
+
type: :development
|
41
|
+
prerelease: false
|
42
|
+
version_requirements: !ruby/object:Gem::Requirement
|
43
|
+
requirements:
|
44
|
+
- - "~>"
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '1.14'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rake
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "~>"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: '10.0'
|
54
|
+
type: :development
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - "~>"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '10.0'
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rspec-rails
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '3.0'
|
68
|
+
type: :development
|
69
|
+
prerelease: false
|
70
|
+
version_requirements: !ruby/object:Gem::Requirement
|
71
|
+
requirements:
|
72
|
+
- - "~>"
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
version: '3.0'
|
75
|
+
- !ruby/object:Gem::Dependency
|
76
|
+
name: sqlite3
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
78
|
+
requirements:
|
79
|
+
- - "~>"
|
80
|
+
- !ruby/object:Gem::Version
|
81
|
+
version: '1.3'
|
82
|
+
type: :development
|
83
|
+
prerelease: false
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
85
|
+
requirements:
|
86
|
+
- - "~>"
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '1.3'
|
89
|
+
- !ruby/object:Gem::Dependency
|
90
|
+
name: capybara
|
91
|
+
requirement: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
type: :development
|
97
|
+
prerelease: false
|
98
|
+
version_requirements: !ruby/object:Gem::Requirement
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
version: '0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: factory_girl
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - ">="
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: '0'
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - ">="
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: '0'
|
117
|
+
- !ruby/object:Gem::Dependency
|
118
|
+
name: timecop
|
119
|
+
requirement: !ruby/object:Gem::Requirement
|
120
|
+
requirements:
|
121
|
+
- - ">="
|
122
|
+
- !ruby/object:Gem::Version
|
123
|
+
version: '0'
|
124
|
+
type: :development
|
125
|
+
prerelease: false
|
126
|
+
version_requirements: !ruby/object:Gem::Requirement
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
version: '0'
|
131
|
+
description: Provide time zone support for User models in Rails applications
|
132
|
+
email:
|
133
|
+
- justin@tomich.org
|
134
|
+
executables: []
|
135
|
+
extensions: []
|
136
|
+
extra_rdoc_files:
|
137
|
+
- LICENSE.txt
|
138
|
+
- README.md
|
139
|
+
- CHANGELOG.md
|
140
|
+
files:
|
141
|
+
- ".gitignore"
|
142
|
+
- ".rspec"
|
143
|
+
- ".travis.yml"
|
144
|
+
- CHANGELOG.md
|
145
|
+
- CODE_OF_CONDUCT.md
|
146
|
+
- Gemfile
|
147
|
+
- LICENSE.txt
|
148
|
+
- README.md
|
149
|
+
- Rakefile
|
150
|
+
- app/assets/javascripts/user_time_zones.js
|
151
|
+
- bin/console
|
152
|
+
- bin/setup
|
153
|
+
- lib/generators/user_time_zones/helpers.rb
|
154
|
+
- lib/generators/user_time_zones/install/install_generator.rb
|
155
|
+
- lib/generators/user_time_zones/install/templates/db/migrate/add_time_zone_to_users.rb
|
156
|
+
- lib/user_time_zones.rb
|
157
|
+
- lib/user_time_zones/controller.rb
|
158
|
+
- lib/user_time_zones/helper.rb
|
159
|
+
- lib/user_time_zones/user.rb
|
160
|
+
- lib/user_time_zones/version.rb
|
161
|
+
- user_time_zones.gemspec
|
162
|
+
homepage: http://github.com/tomichj/user_time_zones
|
163
|
+
licenses:
|
164
|
+
- MIT
|
165
|
+
metadata: {}
|
166
|
+
post_install_message:
|
167
|
+
rdoc_options:
|
168
|
+
- "--charset=UTF-8"
|
169
|
+
require_paths:
|
170
|
+
- lib
|
171
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
172
|
+
requirements:
|
173
|
+
- - ">="
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '2.0'
|
176
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
177
|
+
requirements:
|
178
|
+
- - ">="
|
179
|
+
- !ruby/object:Gem::Version
|
180
|
+
version: '0'
|
181
|
+
requirements: []
|
182
|
+
rubyforge_project:
|
183
|
+
rubygems_version: 2.5.2
|
184
|
+
signing_key:
|
185
|
+
specification_version: 4
|
186
|
+
summary: Provide time zone support for User models in Rails applications
|
187
|
+
test_files: []
|