location-service-client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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