location-service-client 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 +10 -0
- data/.rubocop.yml +1164 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +9 -0
- data/README.md +47 -0
- data/Rakefile +8 -0
- data/lib/location-service-client.rb +4 -0
- data/lib/location.rb +100 -0
- data/lib/version.rb +7 -0
- data/location_service_client.gemspec +30 -0
- data/spec/data/locations.json +84592 -0
- data/spec/lib/location_spec.rb +46 -0
- data/spec/test_helper.rb +7 -0
- metadata +144 -0
data/CHANGELOG.md
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
0.1.0 6/24/2016
|
2
|
+
==============
|
3
|
+
|
4
|
+
Include active record validators so we can fake some aspects of ActiveRecord associations, like nested attributes and belongs_to...
|
5
|
+
|
6
|
+
0.0.7 6/6/2016
|
7
|
+
==============
|
8
|
+
|
9
|
+
Add the SAS id.
|
10
|
+
|
11
|
+
0.0.6 5/24/2016
|
12
|
+
==============
|
13
|
+
|
14
|
+
### Features
|
15
|
+
|
16
|
+
Return struct location objects instead of hashes.
|
17
|
+
|
18
|
+
Change ruby_timezone into a dynamic method on an instance instead of something we calculate for every locoation.
|
19
|
+
|
20
|
+
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# location-service-client
|
2
|
+
|
3
|
+
A gem for clients of Springshot's location service
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Add it to your gemfile.
|
8
|
+
|
9
|
+
```
|
10
|
+
gem 'location-service-client', git: 'https://8bcbcee566e5e7a5d75592940d15bc9f68b84bd9:x-oauth-basic@github.com/springshot/location-service-client.git'
|
11
|
+
```
|
12
|
+
|
13
|
+
## Configuration
|
14
|
+
|
15
|
+
Settings.location_service (c.f. the 'config' gem) will need a url for the location service
|
16
|
+
and the app token configured to access the locations end point.
|
17
|
+
|
18
|
+
```
|
19
|
+
location_service
|
20
|
+
url: ...
|
21
|
+
token: ...
|
22
|
+
```
|
23
|
+
|
24
|
+
## Documentation
|
25
|
+
|
26
|
+
The location service client just adds a dead simple Location class that presently downloads a big array of nested hashes (with indifferent access and the keys snake-cased) of all locations in the location service and some helper methods.
|
27
|
+
|
28
|
+
```
|
29
|
+
> Location.all
|
30
|
+
=> [{"id"=>449, "name"=>"Hartsfield-Jackson Atlanta International Airport", "code"=>"ATL", "kind"=>"airport", "lat"=>33.640067, "lng"=>-84.44403, "parent_location_id"=>nil, "created_at"=>"2016-04-28T21:19:02.658Z", "updated_at"=>"2016-04-28T21:19:02.658Z", "beacons"=>[], "child_locations"=>[..]},...]
|
31
|
+
```
|
32
|
+
|
33
|
+
There are some top level methods for accessing that data:
|
34
|
+
|
35
|
+
```
|
36
|
+
Location.find(id) -> find the location by its location service ID.
|
37
|
+
Location.find_by_code(code) -> return the hash of the location with the code (e.g. an airport's IATA code or a gate's qr_code).
|
38
|
+
Location.parents -> return just the roots of the trees
|
39
|
+
```
|
40
|
+
|
41
|
+
And until it needs to do more that's all it does.
|
42
|
+
|
43
|
+
|
44
|
+
## Contributing
|
45
|
+
|
46
|
+
Make sure any backwards incompatible changes come with a version bump so existing projects aren't obliterated.
|
47
|
+
|
data/Rakefile
ADDED
data/lib/location.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
require 'json'
|
2
|
+
require 'rest-client'
|
3
|
+
require 'active_support/cache'
|
4
|
+
require 'tzinfo'
|
5
|
+
require 'logger'
|
6
|
+
require 'active_record'
|
7
|
+
|
8
|
+
class Location < Struct.new(:id, :sas_id, :name, :code, :kind, :lat, :lng, :timezone, :parent_location_id, :updated_at, :created_at, :child_locations, :beacons)
|
9
|
+
include ActiveModel::Validations
|
10
|
+
|
11
|
+
def ruby_timezone
|
12
|
+
begin
|
13
|
+
TZInfo::Timezone.get(timezone) if timezone && !timezone.empty?
|
14
|
+
rescue TZInfo::InvalidTimezoneIdentifier
|
15
|
+
raise TZInfo::InvalidTimezoneIdentifier.new("'#{timezone}' is an invalid identifier")
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class << self
|
20
|
+
# For mapping the JSON camelcase data from the location service into the Location structs:
|
21
|
+
KEY_ORDER = [:id, :sasId, :name, :code, :kind, :lat, :lng, :timezone, :parentLocationId, :updatedAt, :createdAt, :childLocations, :beacons].map(&:to_s).freeze
|
22
|
+
CACHE_KEY = 'location_service_request_cache'.freeze
|
23
|
+
|
24
|
+
def find(id)
|
25
|
+
flattened.detect{|l| l.id == id }
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_by_code(code)
|
29
|
+
flattened.detect{|l| l.code == code }
|
30
|
+
end
|
31
|
+
|
32
|
+
def find_by_parent_code_and_child_name(parent_code, child_name)
|
33
|
+
airport = all.detect {|l| l.code == parent_code}
|
34
|
+
airport.try(:child_locations) && airport.child_locations.detect {|l| l.name == child_name }
|
35
|
+
end
|
36
|
+
alias_method :find_by_airport_and_gate, :find_by_parent_code_and_child_name
|
37
|
+
|
38
|
+
def find_by_codes(codes, child_locations=nil)
|
39
|
+
child_locations ||= all
|
40
|
+
codes = [codes].flatten
|
41
|
+
code = codes.shift
|
42
|
+
leaf = child_locations.detect{|l| l.code == code }
|
43
|
+
codes.empty? ? leaf : find_by_codes(codes, leaf.child_locations)
|
44
|
+
end
|
45
|
+
|
46
|
+
def children
|
47
|
+
all.map{|l| l.child_locations }.compact
|
48
|
+
end
|
49
|
+
|
50
|
+
def flattened
|
51
|
+
(all + children).flatten
|
52
|
+
end
|
53
|
+
|
54
|
+
def all
|
55
|
+
@locations ||= transform_data(request('/locations')).try(:compact) || []
|
56
|
+
end
|
57
|
+
|
58
|
+
def request(endpoint)
|
59
|
+
user_token = Thread.current[:current_user].try(:authentication_token)
|
60
|
+
url = Settings.location_service.url + "v1/" + endpoint + "?api_key=#{user_token||Settings.location_service.token}"
|
61
|
+
cache.fetch(CACHE_KEY) do
|
62
|
+
logger.debug url
|
63
|
+
JSON.parse(RestClient.get(url))
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def reset
|
68
|
+
Rails.cache.delete(CACHE_KEY)
|
69
|
+
@locations = nil
|
70
|
+
end
|
71
|
+
|
72
|
+
def transform_data(data)
|
73
|
+
if data.kind_of? Array
|
74
|
+
data.map { |v| transform_data(v) }
|
75
|
+
|
76
|
+
elsif data.kind_of? Hash
|
77
|
+
#HashWithIndifferentAccess[data.map {|k, v| [k.to_s.underscore, transform_data(v)] }]
|
78
|
+
l = Location.new(*data.values_at(*KEY_ORDER))
|
79
|
+
l.created_at = data['createdAt'] && time.at( data['createdAt']/1000 )
|
80
|
+
l.updated_at = data['updatedAt'] && time.at( data['updatedAt']/1000 )
|
81
|
+
l.child_locations = transform_data( data['childLocations'] ) || []
|
82
|
+
l
|
83
|
+
else
|
84
|
+
data
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def time
|
89
|
+
Time.zone || Time
|
90
|
+
end
|
91
|
+
def cache
|
92
|
+
defined?(Rails) ? Rails.cache : ActiveSupport::Cache::FileStore.new
|
93
|
+
end
|
94
|
+
|
95
|
+
def logger
|
96
|
+
defined?(Rails) ? Rails.logger : Logger.new(STDOUT)
|
97
|
+
end
|
98
|
+
|
99
|
+
end
|
100
|
+
end
|
data/lib/version.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
$:.push File.expand_path("../lib", __FILE__)
|
2
|
+
|
3
|
+
# Maintain your gem's version:
|
4
|
+
require "version"
|
5
|
+
#require "location_service_client/"
|
6
|
+
|
7
|
+
# Describe your gem and declare its dependencies:
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = "location-service-client"
|
10
|
+
s.version = LocationServiceClient::VERSION
|
11
|
+
s.authors = ["Josh Buermann"]
|
12
|
+
s.email = ["josh.buermann@springshot.com"]
|
13
|
+
s.homepage = "https://github.com/springshot/location_service_client"
|
14
|
+
s.summary = ""
|
15
|
+
s.description = ""
|
16
|
+
s.license = ""
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n").sort
|
19
|
+
s.test_files = `git ls-files -- spec/*`.split("\n")
|
20
|
+
|
21
|
+
s.required_ruby_version = '~> 2.0'
|
22
|
+
|
23
|
+
s.add_dependency "config"
|
24
|
+
s.add_dependency "json"
|
25
|
+
s.add_dependency "rest-client"
|
26
|
+
s.add_dependency "tzinfo"
|
27
|
+
s.add_dependency "activerecord"
|
28
|
+
|
29
|
+
s.add_development_dependency "rspec-rails", '>= 3.0'
|
30
|
+
end
|