location-service-client 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.
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
@@ -0,0 +1,9 @@
1
+ source 'https://rubygems.org'
2
+ gem 'rspec'
3
+ gem 'activerecord'
4
+ gem 'config'
5
+ gem 'json'
6
+ gem 'rest-client'
7
+ gem 'activesupport'
8
+ gem 'tzinfo'
9
+
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
@@ -0,0 +1,8 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ Bundler::GemHelper.install_tasks
8
+
@@ -0,0 +1,4 @@
1
+ require File.dirname(__FILE__) + '/location'
2
+ module LocationServiceClient
3
+ autoload :Version, 'version'
4
+ end
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,7 @@
1
+ module LocationServiceClient
2
+ VERSION = "0.1.0".freeze
3
+
4
+ def self.version
5
+ VERSION
6
+ end
7
+ end
@@ -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