temporal-rails 0.2.1 → 0.2.2

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.
data/LICENSE CHANGED
@@ -4,7 +4,7 @@ Rails to use.
4
4
  Documentation and other useful information can be found at
5
5
  https://github.com/jejacks0n/temporal
6
6
 
7
- Copyright (c) 2011 Jeremy Jackson
7
+ Copyright (c) 2012 Jeremy Jackson
8
8
 
9
9
  Permission is hereby granted, free of charge, to any person obtaining
10
10
  a copy of this software and associated documentation files (the
@@ -5,7 +5,7 @@ module Temporal
5
5
  end
6
6
 
7
7
  def set_time_zone
8
- Time.zone = ActiveSupport::TimeZone.new(cookies[:timezone]) || Rails.application.config.time_zone
8
+ Time.zone = cookies[:timezone] ? ActiveSupport::TimeZone.new(cookies[:timezone]) : Rails.application.config.time_zone
9
9
  end
10
10
  end
11
11
  end
@@ -2,7 +2,7 @@ require 'temporal/controller_additions'
2
2
 
3
3
  module Temporal
4
4
  class Engine < ::Rails::Engine
5
- initializer "temporal.controller_additions" do
5
+ initializer "temporal.controller_additions" do
6
6
  ActiveSupport.on_load(:action_controller) do
7
7
  include Temporal::ControllerAdditions
8
8
  end
@@ -1,3 +1,3 @@
1
1
  module Temporal
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
@@ -0,0 +1,22 @@
1
+ require 'spec_helper'
2
+
3
+ describe ApplicationController, type: :controller do
4
+
5
+ before do
6
+ Rails.application.config.time_zone = 'Central Time (US & Canada)'
7
+ end
8
+
9
+ it "set the timezone to the configured default if the cookie isn't set" do
10
+ get :welcome
11
+ Time.zone.to_s.should =~ /Central Time/
12
+ response.code.should == "200"
13
+ end
14
+
15
+ it "set the timezone based on the cookie" do
16
+ @request.cookies[:timezone] = 'America/Denver'
17
+ get :welcome
18
+ Time.zone.to_s.should =~ /Denver/
19
+ response.code.should == "200"
20
+ end
21
+
22
+ end
@@ -1,6 +1,8 @@
1
1
  require File.expand_path('../boot', __FILE__)
2
2
 
3
- require 'rails/all'
3
+ require 'action_controller/railtie'
4
+ require 'sprockets/railtie'
5
+
4
6
  require 'evergreen/rails'
5
7
 
6
8
  if defined?(Bundler)
@@ -46,13 +48,13 @@ module Dummy
46
48
  # Use SQL instead of Active Record's schema dumper when creating the database.
47
49
  # This is necessary if your schema can't be completely dumped by the schema dumper,
48
50
  # like if you have constraints or database-specific column types
49
- config.active_record.schema_format = :sql
51
+ #config.active_record.schema_format = :sql
50
52
 
51
53
  # Enforce whitelist mode for mass assignment.
52
54
  # This will create an empty whitelist of attributes available for mass-assignment for all models
53
55
  # in your app. As such, your models will need to explicitly whitelist or blacklist accessible
54
56
  # parameters by using an attr_accessible or attr_protected declaration.
55
- config.active_record.whitelist_attributes = true
57
+ #config.active_record.whitelist_attributes = true
56
58
 
57
59
  # Enable the asset pipeline
58
60
  config.assets.enabled = true
@@ -23,11 +23,11 @@ Dummy::Application.configure do
23
23
  config.action_dispatch.best_standards_support = :builtin
24
24
 
25
25
  # Raise exception on mass assignment protection for Active Record models
26
- config.active_record.mass_assignment_sanitizer = :strict
26
+ #config.active_record.mass_assignment_sanitizer = :strict
27
27
 
28
28
  # Log the query plan for queries taking more than this (works
29
29
  # with SQLite, MySQL, and PostgreSQL)
30
- config.active_record.auto_explain_threshold_in_seconds = 0.5
30
+ #config.active_record.auto_explain_threshold_in_seconds = 0.5
31
31
 
32
32
  # Do not compress assets
33
33
  config.assets.compress = false
@@ -27,10 +27,10 @@ Dummy::Application.configure do
27
27
  # Tell Action Mailer not to deliver emails to the real world.
28
28
  # The :test delivery method accumulates sent emails in the
29
29
  # ActionMailer::Base.deliveries array.
30
- config.action_mailer.delivery_method = :test
30
+ #config.action_mailer.delivery_method = :test
31
31
 
32
32
  # Raise exception on mass assignment protection for Active Record models
33
- config.active_record.mass_assignment_sanitizer = :strict
33
+ #config.active_record.mass_assignment_sanitizer = :strict
34
34
 
35
35
  # Print deprecation notices to the stderr
36
36
  config.active_support.deprecation = :stderr
@@ -1,6 +1,6 @@
1
1
  Dummy::Application.routes.draw do
2
2
 
3
- match '/welcome' => 'application#welcome'
3
+ root to: 'application#welcome'
4
4
 
5
5
  # The priority is based upon order of creation:
6
6
  # first created -> highest priority.
@@ -0,0 +1,16 @@
1
+ # encoding: UTF-8
2
+ # This file is auto-generated from the current state of the database. Instead
3
+ # of editing this file, please use the migrations feature of Active Record to
4
+ # incrementally modify your database, and then regenerate this schema definition.
5
+ #
6
+ # Note that this schema.rb definition is the authoritative source for your
7
+ # database schema. If you need to create the application database on another
8
+ # system, you should be using db:schema:load, not running all the migrations
9
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
10
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
11
+ #
12
+ # It's strongly recommended to check this file into your version control system.
13
+
14
+ ActiveRecord::Schema.define(:version => 0) do
15
+
16
+ end
@@ -0,0 +1,21 @@
1
+ require 'spec_helper'
2
+
3
+ describe Temporal do
4
+
5
+ it "is a module" do
6
+ Temporal.should be_a(Module)
7
+ end
8
+
9
+ it "has a version" do
10
+ Temporal::VERSION.should be_a(String)
11
+ end
12
+
13
+ it "defines ControllerAdditions" do
14
+ Temporal::ControllerAdditions.should be_a(Module)
15
+ end
16
+
17
+ it "includes ControllerAdditions in ActionController::Base" do
18
+ ActionController::Base.new.methods.should include(:set_time_zone)
19
+ end
20
+
21
+ end
@@ -2,3 +2,75 @@ require '/assets/temporal.js'
2
2
 
3
3
  describe "Temporal", ->
4
4
 
5
+ beforeEach ->
6
+ document.cookie = 'timezone='
7
+ document.cookie = 'timezone_offset='
8
+ @timezoneStub = {name: 'foo', offset: 0} # 0 here ensure the jsonp request isn't made
9
+
10
+ describe "signature", ->
11
+
12
+ it "has a detect and reference method", ->
13
+ expect(Object.keys(Temporal).length).toBe 2
14
+ expect(Object.keys(Temporal)).toEqual ['detect', 'reference']
15
+ expect(typeof(Temporal.detect)).toBe 'function'
16
+ expect(typeof(Temporal.reference)).toBe 'function'
17
+
18
+
19
+ describe ".detect", ->
20
+
21
+ beforeEach ->
22
+ window.Temporal = Temporal.reference() if Temporal.reference
23
+ @spy = spyOn(Temporal.prototype, 'detectLocally').andReturn @timezoneStub
24
+ @callback = ->
25
+
26
+ it "instantiates an instance and passes arguments", ->
27
+ instance = Temporal.detect('username', @callback)
28
+ expect(@spy).toHaveBeenCalled()
29
+ expect(instance.username).toBe 'username'
30
+ expect(instance.callback).toBe @callback
31
+
32
+
33
+ describe "constructor", ->
34
+
35
+ it "calls #detectLocally", ->
36
+ spy = spyOn(Temporal.prototype, 'detectLocally').andReturn @timezoneStub
37
+ new Temporal()
38
+ expect(spy.callCount).toBe 1
39
+
40
+ it "calls #geoLocate if there's a username for the GeoName API", ->
41
+ spyOn(Temporal.prototype, 'detectLocally').andReturn name: 'foo', offset: 1
42
+ spy = spyOn(Temporal.prototype, 'geoLocate')
43
+ new Temporal('username')
44
+ expect(spy.callCount).toBe 1
45
+
46
+ it "doesn't call #geoLocate if there isn't a username", ->
47
+ spyOn(Temporal.prototype, 'detectLocally').andReturn name: 'foo', offset: 1
48
+ spy = spyOn(Temporal.prototype, 'geoLocate')
49
+ new Temporal()
50
+ expect(spy.callCount).toBe 0
51
+
52
+ it "calls #set", ->
53
+ spyOn(Temporal.prototype, 'detectLocally').andReturn @timezoneStub
54
+ spy = spyOn(Temporal.prototype, 'set')
55
+ new Temporal()
56
+ expect(spy.callCount).toBe 1
57
+ expect(spy).toHaveBeenCalledWith name: 'foo', offset: 0
58
+
59
+
60
+ describe "#detectLocally", ->
61
+
62
+ beforeEach ->
63
+ spyOn(Temporal.prototype, 'detect')
64
+ @temporal = new Temporal()
65
+
66
+ it "returns a quickly determined time zone", ->
67
+ spyOn(Temporal.prototype, 'januaryOffset').andReturn -420
68
+ spyOn(Temporal.prototype, 'juneOffset').andReturn -360
69
+ timezone = @temporal.detectLocally()
70
+ expect(timezone).toEqual name: 'America/Denver', offset: -7
71
+
72
+ it "handles other locations than denver", ->
73
+ spyOn(Temporal.prototype, 'januaryOffset').andReturn 120
74
+ spyOn(Temporal.prototype, 'juneOffset').andReturn 120
75
+ timezone = @temporal.detectLocally()
76
+ expect(timezone).toEqual name: 'Africa/Johannesburg', offset: 2
@@ -0,0 +1,39 @@
1
+ ENV['RAILS_ENV'] ||= 'test'
2
+ ENV['RAILS_ROOT'] = File.expand_path('../dummy', __FILE__)
3
+ require File.expand_path('../dummy/config/environment', __FILE__)
4
+
5
+ require 'rspec/rails'
6
+ require 'rspec/autorun'
7
+
8
+ # Requires supporting ruby files with custom matchers and macros, etc,
9
+ # in spec/support/ and its subdirectories.
10
+ Dir[Temporal::Engine.root.join('spec/support/**/*.rb')].each { |f| require f }
11
+
12
+ RSpec.configure do |config|
13
+ # ## Mock Framework
14
+ #
15
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
16
+ #
17
+ # config.mock_with :mocha
18
+ # config.mock_with :flexmock
19
+ # config.mock_with :rr
20
+
21
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
22
+ #config.fixture_path = "#{::Temporal::Engine.root}/spec/fixtures"
23
+
24
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
25
+ # examples within a transaction, remove the following line or assign false
26
+ # instead of true.
27
+ #config.use_transactional_fixtures = true
28
+
29
+ # If true, the base class of anonymous controllers will be inferred
30
+ # automatically. This will be the default behavior in future versions of
31
+ # rspec-rails.
32
+ config.infer_base_class_for_anonymous_controllers = false
33
+
34
+ # Run specs in random order to surface order dependencies. If you find an
35
+ # order dependency and want to debug it, you can fix the order by providing
36
+ # the seed, which is printed after each run.
37
+ # --seed 1234
38
+ config.order = "random"
39
+ end
@@ -1,41 +1,22 @@
1
- class TimeZone
1
+ # Temporal -- use detect() to detect, and reference() if you need a reference
2
+ # to the class so you can use it.
3
+ # -----------------------------------------------------------------------------
4
+ class Temporal
2
5
 
3
- constructor: (keyOrProperties) ->
4
- if typeof(keyOrProperties) == 'string'
5
- zone = TIMEZONES[keyOrProperties]
6
- @[property] = value for own property, value of zone
7
- @resolveAmbiguity()
8
- else
9
- @[property] = value for own property, value of keyOrProperties
10
-
11
- resolveAmbiguity: ->
12
- ambiguous = AMBIGIOUS_ZONES[@name]
13
- return if typeof(ambiguous) is 'undefined'
14
- for key, value of ambiguous
15
- if Temporal.dateIsDst(DST_START_DATES[value])
16
- @name = value
17
- return
6
+ jsonpCallback = "geoSuccessCallback#{parseInt(Math.random() * 10000)}"
18
7
 
8
+ @detect: (username = null, callback = null) =>
9
+ new Temporal(username, callback)
19
10
 
20
- class Temporal
11
+ constructor: (@username = null, @callback = null) ->
12
+ @detect()
21
13
 
22
- @detect: (@username = null, @callback = null) =>
23
- timezone = @quick()
24
- if timezone.offset != @get().offset
25
- navigator.geolocation.getCurrentPosition(@geoSuccess, ->) if @username and navigator.geolocation
14
+ detect: ->
15
+ timezone = @detectLocally()
16
+ @geoLocate() if @username and navigator.geolocation and timezone.offset != @get().offset
26
17
  @set(timezone)
27
18
 
28
- @geoSuccess: (position) =>
29
- window[JSONP_CALLBACK] = @parseGeoResponse
30
- script = document.createElement('script')
31
- script.setAttribute('src', "http://api.geonames.org/timezoneJSON?lat=#{position.coords.latitude}&lng=#{position.coords.longitude}&username=#{@username}&callback=#{JSONP_CALLBACK}")
32
- document.getElementsByTagName('head')[0].appendChild(script)
33
-
34
- @parseGeoResponse: (response) =>
35
- delete(window[JSONP_CALLBACK])
36
- @set(new TimeZone(name: response.timezoneId, offset: response.rawOffset)) if response.timezoneId
37
-
38
- @quick: =>
19
+ detectLocally: ->
39
20
  januaryOffset = @januaryOffset()
40
21
  juneOffset = @juneOffset()
41
22
  key = {offset: januaryOffset, dst: 0, hemisphere: HEMISPHERE_UNKNOWN}
@@ -45,35 +26,76 @@ class Temporal
45
26
  key = {offset: juneOffset, dst: 1, hemisphere: HEMISPHERE_SOUTH}
46
27
  new TimeZone("#{([key.offset, key.dst].join(','))}#{if key.hemisphere is HEMISPHERE_SOUTH then ',s' else ''}")
47
28
 
48
- @set: (timezone) ->
49
- window.timezone = timezone
29
+ geoLocate: ->
30
+ navigator.geolocation.getCurrentPosition(@geoSuccess, ->)
31
+
32
+ geoSuccess: (position) =>
33
+ window[jsonpCallback] = @parseGeoResponse
34
+ script = document.createElement('script')
35
+ script.setAttribute('src', "http://api.geonames.org/timezoneJSON?lat=#{position.coords.latitude}&lng=#{position.coords.longitude}&username=#{@username}&callback=#{jsonpCallback}")
36
+ document.getElementsByTagName('head')[0].appendChild(script)
37
+
38
+ parseGeoResponse: (response) =>
39
+ delete(window[jsonpCallback])
40
+ @set(new TimeZone(name: response.timezoneId, offset: response.rawOffset)) if response.timezoneId
41
+
42
+ set: (@timezone) ->
43
+ window.timezone = @timezone
50
44
  expiration = new Date()
51
45
  expiration.setMonth(expiration.getMonth() + 1)
52
- document.cookie = "timezone=#{timezone.name}; expires=#{expiration.toGMTString()}"
53
- document.cookie = "timezone_offset=#{timezone.offset}; expires=#{expiration.toGMTString()}"
54
- @callback?(timezone)
46
+ document.cookie = "timezone=#{@timezone.name}; expires=#{expiration.toGMTString()}"
47
+ document.cookie = "timezone_offset=#{@timezone.offset}; expires=#{expiration.toGMTString()}"
48
+ @callback?(@timezone)
55
49
 
56
- @get: ->
50
+ get: ->
57
51
  name: @getCookie('timezone')
58
- offset: parseFloat(@getCookie('timezone_offset'))
52
+ offset: parseFloat(@getCookie('timezone_offset')) || 0
59
53
 
60
- @getCookie: (name) ->
54
+ getCookie: (name) ->
61
55
  match = document.cookie.match(new RegExp("(?:^|;)\\s?#{name}=(.*?)(?:;|$)", 'i'))
62
56
  match && unescape(match[1])
63
57
 
64
- @januaryOffset: ->
58
+ januaryOffset: ->
65
59
  @dateOffset(new Date(2011, 0, 1, 0, 0, 0, 0))
66
60
 
67
- @juneOffset: ->
61
+ juneOffset: ->
68
62
  @dateOffset(new Date(2011, 5, 1, 0, 0, 0, 0))
69
63
 
70
- @dateOffset: (date) ->
64
+ dateOffset: (date) ->
71
65
  -date.getTimezoneOffset()
72
66
 
73
- @dateIsDst: (date) ->
67
+
68
+ # Timezone -- contains offset and timezone name
69
+ # -----------------------------------------------------------------------------
70
+ class TimeZone
71
+
72
+ dateIsDst = (date) ->
74
73
  (((if date.getMonth() > 5 then @juneOffset() else @januaryOffset())) - @dateOffset(date)) isnt 0
75
74
 
76
- JSONP_CALLBACK = "geoSuccessCallback#{parseInt(Math.random() * 10000)}"
75
+ resolveAmbiguity = ->
76
+ ambiguous = AMBIGIOUS_ZONES[@name]
77
+ return if typeof(ambiguous) is 'undefined'
78
+ for key, value of ambiguous
79
+ if dateIsDst(DST_START_DATES[value])
80
+ @name = value
81
+ return
82
+
83
+ constructor: (keyOrProperties) ->
84
+ if typeof(keyOrProperties) == 'string'
85
+ zone = TIMEZONES[keyOrProperties]
86
+ @[property] = value for own property, value of zone
87
+ resolveAmbiguity()
88
+ else
89
+ @[property] = value for own property, value of keyOrProperties
90
+
91
+
92
+ # Expose Temporal to the global scope
93
+ # -----------------------------------------------------------------------------
94
+ @Temporal = {detect: Temporal.detect, reference: -> Temporal}
95
+
96
+
97
+ # Data
98
+ # -----------------------------------------------------------------------------
77
99
  HEMISPHERE_SOUTH = 'SOUTH'
78
100
  HEMISPHERE_NORTH = 'NORTH'
79
101
  HEMISPHERE_UNKNOWN = 'N/A'
@@ -191,5 +213,3 @@ TIMEZONES =
191
213
  '765,1,s': {offset: 12.75, name: 'Pacific/Chatham'}
192
214
  '780,0': {offset: 13, name: 'Pacific/Tongatapu'}
193
215
  '840,0': {offset: 14, name: 'Pacific/Kiritimati'}
194
-
195
- @Temporal = {detect: Temporal.detect}
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: temporal-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.2.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-09-11 00:00:00.000000000 Z
12
+ date: 2012-10-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
@@ -107,6 +107,22 @@ dependencies:
107
107
  - - ! '>='
108
108
  - !ruby/object:Gem::Version
109
109
  version: 1.0.0
110
+ - !ruby/object:Gem::Dependency
111
+ name: rspec-rails
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
110
126
  description: Javascript timezone detection that also sets Time.zone for Rails to use
111
127
  email:
112
128
  - jejacks0n@gmail.com
@@ -122,6 +138,7 @@ files:
122
138
  - lib/temporal-rails.rb
123
139
  - vendor/assets/javascripts/temporal.js.coffee
124
140
  - LICENSE
141
+ - spec/controllers/application_controller_spec.rb
125
142
  - spec/dummy/Rakefile
126
143
  - spec/dummy/app/assets/javascripts/application.js
127
144
  - spec/dummy/app/controllers/application_controller.rb
@@ -142,10 +159,13 @@ files:
142
159
  - spec/dummy/config/initializers/wrap_parameters.rb
143
160
  - spec/dummy/config/locales/en.yml
144
161
  - spec/dummy/config/routes.rb
162
+ - spec/dummy/db/schema.rb
145
163
  - spec/dummy/public/favicon.ico
146
164
  - spec/dummy/script/rails
165
+ - spec/engine/temporal_spec.rb
147
166
  - spec/javascripts/spec_helper.js
148
167
  - spec/javascripts/temporal_spec.js.coffee
168
+ - spec/spec_helper.rb
149
169
  homepage: http://github.com/jejacks0n/temporal
150
170
  licenses:
151
171
  - MIT
@@ -161,7 +181,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
161
181
  version: '0'
162
182
  segments:
163
183
  - 0
164
- hash: 2430015501946444903
184
+ hash: -492844622740408129
165
185
  required_rubygems_version: !ruby/object:Gem::Requirement
166
186
  none: false
167
187
  requirements:
@@ -170,7 +190,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
170
190
  version: '0'
171
191
  segments:
172
192
  - 0
173
- hash: 2430015501946444903
193
+ hash: -492844622740408129
174
194
  requirements: []
175
195
  rubyforge_project:
176
196
  rubygems_version: 1.8.24
@@ -178,6 +198,7 @@ signing_key:
178
198
  specification_version: 3
179
199
  summary: ! 'Temporal: Javascript timezone detection for Rails'
180
200
  test_files:
201
+ - spec/controllers/application_controller_spec.rb
181
202
  - spec/dummy/Rakefile
182
203
  - spec/dummy/app/assets/javascripts/application.js
183
204
  - spec/dummy/app/controllers/application_controller.rb
@@ -198,7 +219,10 @@ test_files:
198
219
  - spec/dummy/config/initializers/wrap_parameters.rb
199
220
  - spec/dummy/config/locales/en.yml
200
221
  - spec/dummy/config/routes.rb
222
+ - spec/dummy/db/schema.rb
201
223
  - spec/dummy/public/favicon.ico
202
224
  - spec/dummy/script/rails
225
+ - spec/engine/temporal_spec.rb
203
226
  - spec/javascripts/spec_helper.js
204
227
  - spec/javascripts/temporal_spec.js.coffee
228
+ - spec/spec_helper.rb