user_time_zones 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|