doublemap_api 2.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: dde680b8393299472cc7dcb6a01ce62778cc5298
4
+ data.tar.gz: f1865c943dc16601c7d9b603ec9346b4cbd85aca
5
+ SHA512:
6
+ metadata.gz: 47372e2dece943ae5ada69ff5820e019d582a797c2694269ebdfb281abb772cb0c8bb6d2691d6e6a079f50398b80acdc2b2b4bfbc688fb3a79d1acee380fec27
7
+ data.tar.gz: 37ad58f6f57c6e8314172109998bbaeeefd98582dfd5fcc810f86c2e94c770c1e99146ea00178c4a7a0da73b48a2a989a3fc6a5d6c5e9362831926b305514f93
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2016 Jon Egeland
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,32 @@
1
+ require_relative 'doublemap_api/core_ext/string'
2
+
3
+ require_relative 'doublemap_api/version'
4
+ require_relative 'doublemap_api/configuration'
5
+ require_relative 'doublemap_api/connection'
6
+ require_relative 'doublemap_api/models'
7
+ require_relative 'doublemap_api/api'
8
+ require_relative 'doublemap_api/client'
9
+
10
+ module DoubleMap
11
+ class << self
12
+ # Alias for `DoubleMap::Client.new`
13
+ def new
14
+ Client.new
15
+ end
16
+
17
+ # The current client configuration
18
+ def configuration
19
+ @configuration ||= Configuration.new
20
+ end
21
+
22
+ # Allow users to set configuration options via a block. By default, the
23
+ # configuration will be validated after the block returns. This will raise
24
+ # an exception if any required configurations are not provided. This
25
+ # behavior can be skipped by passing `validate: false` as a parameter.
26
+ def configure validate: true
27
+ yield configuration
28
+ configuration.validate! if validate
29
+ configuration
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,52 @@
1
+ require 'memoist'
2
+
3
+ module DoubleMap
4
+ # A base class implementing common API operations
5
+ class API
6
+ include Connection
7
+
8
+ class << self
9
+ extend Memoist
10
+
11
+ # Include another API's functionality via a new method on this API.
12
+ # For example, `include_api :routes` would include the "Routes" API into
13
+ # the "Client" API, accessible as `Client#routes`.
14
+ def include_api name
15
+ klass = self.const_get(name.to_s.constantize)
16
+ define_method(name) do
17
+ klass.new
18
+ end
19
+ self.memoize name
20
+ end
21
+
22
+ # Require all the files given in `names` that exist in the given folder
23
+ def require_all folder, *libs
24
+ libs.each do |lib|
25
+ require_relative "#{File.join(folder, lib)}"
26
+ end
27
+ end
28
+
29
+ # Return a singleton instance of this API
30
+ def singleton
31
+ @singleton ||= self.new
32
+ end
33
+ end
34
+
35
+
36
+ # Perform a GET request over the connection to the given endpoint.
37
+ def get_request endpoint, opts={}, &block
38
+ connection.get endpoint, opts, &block
39
+ end
40
+
41
+ # Perform a POST request over the connection to the given endpoint.
42
+ def post_request endpoint, opts={}, &block
43
+ connection.post endpoint, opts, &block
44
+ end
45
+
46
+ # For APIs that extend Memoist, allow the user to call `refresh` as an
47
+ # alias for `flush_cache`.
48
+ def refresh
49
+ send(:flush_cache) if respond_to?(:flush_cache)
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,17 @@
1
+ require 'memoist'
2
+
3
+ module DoubleMap
4
+ class Client < API
5
+ extend Memoist
6
+
7
+ require_all 'client',
8
+ 'routes',
9
+ 'stops',
10
+ 'vehicles'
11
+
12
+ include_api :routes
13
+ include_api :stops
14
+ include_api :vehicles
15
+ end
16
+ end
17
+
@@ -0,0 +1,19 @@
1
+ module DoubleMap
2
+ class Client::Routes < API
3
+ extend Memoist
4
+
5
+ # Return a list of all routes on the system.
6
+ def list
7
+ get_request('/map/v2/routes').map{ |route| Route.new(route) }
8
+ end
9
+ memoize :list
10
+ alias_method :all, :list
11
+
12
+ # Return the route whose id matches the given id
13
+ def get id
14
+ list.find{ |route| route.id == id }
15
+ end
16
+ memoize :get
17
+ alias_method :find, :get
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module DoubleMap
2
+ class Client::Stops < API
3
+ extend Memoist
4
+
5
+ # Return a list of all stops on the system.
6
+ def list
7
+ get_request('/map/v2/stops').map{ |stop| Stop.new(stop) }
8
+ end
9
+ memoize :list
10
+ alias_method :all, :list
11
+
12
+ # Return the route whose id matches the given id
13
+ def get id
14
+ list.find{ |stop| stop.id == id }
15
+ end
16
+ memoize :get
17
+ alias_method :find, :get
18
+ end
19
+ end
@@ -0,0 +1,19 @@
1
+ module DoubleMap
2
+ class Client::Vehicles < API
3
+ extend Memoist
4
+
5
+ # Return a list of all vehicles currently traveling on routes.
6
+ def list
7
+ get_request('/map/v2/buses').map{ |vehicle| Vehicle.new(vehicle) }
8
+ end
9
+ memoize :list
10
+ alias_method :all, :list
11
+
12
+ # Return the vehicle whose id matches the given id
13
+ def get id
14
+ list.find{ |vehicle| vehicle.id == id }
15
+ end
16
+ memoize :get
17
+ alias_method :find, :get
18
+ end
19
+ end
@@ -0,0 +1,41 @@
1
+ module DoubleMap
2
+ class Configuration
3
+ # The version of the DoubleMap system
4
+ attr_accessor :version
5
+ # The base URL of the DoubleMap system
6
+ attr_accessor :base_uri
7
+ # The adapter to use for network communication
8
+ attr_accessor :adapter
9
+ # The output stream to which debug information should be written
10
+ attr_accessor :debug_output
11
+
12
+ # The defaults to use for any configuration options that are not provided
13
+ DEFAULT_CONFIGURATION = {
14
+ version: '3.2', # Taken from a comment on "http://bus.gocitybus.com/RouteMap/Index"
15
+ adapter: :httparty,
16
+ debug_output: false
17
+ }
18
+
19
+ # The options required when configuring a DoubleMap instance
20
+ REQUIRED_CONFIGURATION = [
21
+ :base_uri
22
+ ]
23
+
24
+ def initialize
25
+ # Apply the default set of configurations before anything else to ensure
26
+ # all options are initialized.
27
+ DEFAULT_CONFIGURATION.each do |name, value|
28
+ send("#{name}=", value)
29
+ end
30
+ end
31
+
32
+ # Ensure that all required configurations have been given a value. Returns
33
+ # true if all required configuration options have been set.
34
+ def validate!
35
+ REQUIRED_CONFIGURATION.each do |name|
36
+ raise "`#{name}` is a required configuration option, but was not given a value." if send("#{name}").nil?
37
+ end
38
+ true
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,23 @@
1
+ module DoubleMap
2
+ module Connection
3
+ extend self
4
+
5
+ # Return the connection adapter instance
6
+ def connection
7
+ @connection ||= adapter.new(DoubleMap.configuration)
8
+ end
9
+
10
+ # Return the class of the adapter to use for the connection
11
+ def adapter
12
+ @@adapters[DoubleMap.configuration.adapter]
13
+ end
14
+
15
+ # Register a new class that can be used as a connection adapter
16
+ def register_adapter name, klass
17
+ (@@adapters ||= {})[name] = klass
18
+ end
19
+ end
20
+ end
21
+
22
+ # Include the adapters that come packaged with the gem
23
+ require_relative 'connection_adapters/httparty_adapter.rb'
@@ -0,0 +1,27 @@
1
+ require 'httparty'
2
+ require 'json'
3
+
4
+ # A Connection adapter using HTTParty as the network transport
5
+ module DoubleMap
6
+ module Connection
7
+ class HTTPartyAdapter
8
+ include HTTParty
9
+
10
+ def initialize config
11
+ self.class.base_uri config.base_uri
12
+ # Write debug information to the configured output stream
13
+ self.class.debug_output config.debug_output
14
+ end
15
+
16
+ def get endpoint, opts={}, &block
17
+ self.class.get(endpoint, opts, &block).parsed_response
18
+ end
19
+
20
+ def post endpoint, opts={}, &block
21
+ self.class.post(endpoint, opts, &block).parsed_response
22
+ end
23
+ end
24
+
25
+ register_adapter :httparty, HTTPartyAdapter
26
+ end
27
+ end
@@ -0,0 +1,21 @@
1
+ class String
2
+ def underscore
3
+ self.dup.underscore!
4
+ end unless method_defined? :underscore
5
+
6
+ def underscore!
7
+ self.gsub!(/([A-Z\d]+)([A-Z][a-z])/,'\1_\2')
8
+ self.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
9
+ self.tr_s!('- ', '_')
10
+ self.downcase!
11
+ self
12
+ end unless method_defined? :underscore!
13
+
14
+ def titleize
15
+ self.tr_s('- ', '_').split('_').map(&:capitalize).join(' ')
16
+ end unless method_defined? :titleize
17
+
18
+ def constantize
19
+ self.tr_s('- ', '_').split('_').map(&:capitalize).join
20
+ end unless method_defined? :constantize
21
+ end
@@ -0,0 +1,88 @@
1
+ require 'set'
2
+
3
+ module DoubleMap
4
+ class Model
5
+ extend Forwardable
6
+
7
+ class << self
8
+ # Define a new attribute of the model.
9
+ # If `type` is given, a new instance of `type` will be created whenever
10
+ # this attribute is assigned a value. This allows creation of nested
11
+ # objects from a simple Hash.
12
+ # If `type` is given and `array` is true, the value given to this
13
+ # attribute will be interpreted as an array and a new instance of `type`
14
+ # will be created for each entry in the array
15
+ # It `type` is given, and the value given to this attribute is nil, no
16
+ # new instance of `type` will be created. Instead, the value will remain
17
+ # nil, as an instance of NilClass.
18
+ def attribute name, type: nil, array: false
19
+ attributes << [name, type]
20
+ attr_reader name
21
+ # Use a custom writer method to allow typed attributes to be
22
+ # instantiated properly.
23
+ define_method "#{name}=" do |value|
24
+ # Only do type conversion if the type is specified and the value is
25
+ # not nil.
26
+ if type and !value.nil?
27
+ # Lookup is done on DoubleMap to ensure that Model subclasses are
28
+ # searched first, falling back to other types (Numeric, Hash, etc.)
29
+ # if no Model subclass is found.
30
+ klass = DoubleMap.const_get(type.to_s.constantize)
31
+ value = array ? value.map{ |v| klass.new(v) } : klass.new(value)
32
+ end
33
+ instance_variable_set("@#{name}", value)
34
+ end
35
+ end
36
+
37
+ # The list of attributes defined on the model
38
+ def attributes
39
+ @attributes ||= Set.new
40
+ end
41
+
42
+ # The attribute of the model that can be used to uniquely identify an
43
+ # instance from any other. The primary attribute should also be set
44
+ # with `attribute <name>`.
45
+ attr_accessor :identifier
46
+ def primary_attribute name
47
+ @identifier = name
48
+ end
49
+
50
+ # Define one or more delegated methods on the model, passing them to the
51
+ # given attribute.
52
+ def delegate *names, to:
53
+ names.each do |name|
54
+ def_delegator to, name
55
+ end
56
+ end
57
+ end
58
+
59
+ # Initialize a model instance with any given attributes assigned
60
+ def initialize args={}
61
+ assign(args)
62
+ end
63
+
64
+ # Mass assign a group of attributes. Attribute names will be automatically
65
+ # be converted to snake_case for consistency.
66
+ def assign args={}
67
+ args.each do |_name, value|
68
+ public_send("#{_name.underscore}=", value)
69
+ end
70
+ end
71
+
72
+ # The value of the primary attribute on this model
73
+ def identifier
74
+ send(self.class.identifier)
75
+ end
76
+
77
+ # Assume that two Model objects are the same if their primary attributes
78
+ # have the same value
79
+ def == o
80
+ identifier == o.identifier
81
+ end
82
+ end
83
+ end
84
+
85
+ # Include all model subclasses
86
+ require_relative 'models/route'
87
+ require_relative 'models/stop'
88
+ require_relative 'models/vehicle'
@@ -0,0 +1,36 @@
1
+ module DoubleMap
2
+ class Route < Model
3
+ # The unique id used when referencing this route
4
+ attribute :id
5
+ # The full name of this route
6
+ attribute :name
7
+ # The name used to quickly identify this route
8
+ attribute :short_name
9
+ # A short summary of the purpose of this route
10
+ attribute :description
11
+ # The hexadecimal color to use when displaying this route
12
+ attribute :color
13
+ # The list of lat/lon points that this route passes through
14
+ attribute :path
15
+ # The time of day that this route becomes active
16
+ attribute :start_time
17
+ # The time of day that this route stops being active
18
+ attribute :end_time
19
+ # The url where schedule information for this route can be found
20
+ attribute :schedule_url
21
+ # Is the route currently an active route being serviced
22
+ attribute :active
23
+ alias_method :active?, :active
24
+ alias_method :is_active, :active
25
+ # NOTE: The purpose of this field is unknown, as it is almost always given
26
+ # a value of `null`.
27
+ # It's default value is a Hash, so the assumed purpose is extra information
28
+ # about the route that doesn't conform to the API schema.
29
+ attribute :fields
30
+ # The list of stop ids that this route passes through.
31
+ attribute :stops
32
+
33
+
34
+ primary_attribute :id
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module DoubleMap
2
+ class Stop < Model
3
+ # The unique id used when referencing this stop
4
+ attribute :id
5
+ # The name of this stop
6
+ attribute :name
7
+ # A short summary of the purpose of this stop
8
+ attribute :description
9
+ # The latitudinal position of this stop
10
+ attribute :lat
11
+ alias_method :latitude, :lat
12
+ # The longitudinal position of this stop
13
+ attribute :lon
14
+ alias_method :longitude, :lon
15
+ # NOTE: The purpose of this field is unknown, as it is almost always given
16
+ # a value of `null`.
17
+ attribute :buddy
18
+ # NOTE: The purpose of this field is unknown, as it is almost always given
19
+ # a value of `null`.
20
+ # It's default value is a Hash, so the assumed purpose is extra information
21
+ # about the route that doesn't conform to the API schema.
22
+ attribute :fields
23
+
24
+
25
+ primary_attribute :id
26
+ end
27
+ end
@@ -0,0 +1,32 @@
1
+ module DoubleMap
2
+ class Vehicle < Model
3
+ # The unique id used when referencing this vehicle
4
+ attribute :id
5
+ # The name given to this vehicle
6
+ attribute :name
7
+ # The latitudinal position of this vehicle
8
+ attribute :lat
9
+ alias_method :latitude, :lat
10
+ # The longitudinal position of this vehicle
11
+ attribute :lon
12
+ alias_method :longitude, :lon
13
+ # NOTE: The purpose of this field is unknown, as it is almost always given
14
+ # a value of `null`.
15
+ attribute :heading
16
+ # The route this vehicle is currently traveling
17
+ attribute :route
18
+ # The last stop that this vehicle departed from
19
+ attribute :last_stop
20
+ # NOTE: The purpose of this field is unknown, as it is almost always given
21
+ # a value of `null`.
22
+ # It's default value is a Hash, so the assumed purpose is extra information
23
+ # about the route that doesn't conform to the API schema.
24
+ attribute :fields
25
+ # The time at which this vehicle was last updated. Stored as seconds since
26
+ # the Unix epoch.
27
+ attribute :last_update
28
+
29
+
30
+ primary_attribute :id
31
+ end
32
+ end
@@ -0,0 +1,3 @@
1
+ module DoubleMap
2
+ VERSION = "2.0.0"
3
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: doublemap_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Jon Egeland
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: httparty
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '0.13'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '0.13'
27
+ - !ruby/object:Gem::Dependency
28
+ name: memoist
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '0.14'
41
+ description: A Ruby client for the DoubleMap real-time transit API. The major version
42
+ of this gem will match the version of the DoubleMap API that it is built for (e.g.,
43
+ 2.0.0 -> v2).
44
+ email: jonegeland@gmail.com
45
+ executables: []
46
+ extensions: []
47
+ extra_rdoc_files:
48
+ - LICENSE
49
+ files:
50
+ - LICENSE
51
+ - lib/doublemap_api.rb
52
+ - lib/doublemap_api/api.rb
53
+ - lib/doublemap_api/client.rb
54
+ - lib/doublemap_api/client/routes.rb
55
+ - lib/doublemap_api/client/stops.rb
56
+ - lib/doublemap_api/client/vehicles.rb
57
+ - lib/doublemap_api/configuration.rb
58
+ - lib/doublemap_api/connection.rb
59
+ - lib/doublemap_api/connection_adapters/httparty_adapter.rb
60
+ - lib/doublemap_api/core_ext/string.rb
61
+ - lib/doublemap_api/models.rb
62
+ - lib/doublemap_api/models/route.rb
63
+ - lib/doublemap_api/models/stop.rb
64
+ - lib/doublemap_api/models/vehicle.rb
65
+ - lib/doublemap_api/version.rb
66
+ homepage: http://github.com/propershark/doublemap_api
67
+ licenses:
68
+ - MIT
69
+ metadata: {}
70
+ post_install_message:
71
+ rdoc_options: []
72
+ require_paths:
73
+ - lib
74
+ required_ruby_version: !ruby/object:Gem::Requirement
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: 2.2.0
79
+ required_rubygems_version: !ruby/object:Gem::Requirement
80
+ requirements:
81
+ - - ">="
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ requirements: []
85
+ rubyforge_project:
86
+ rubygems_version: 2.4.8
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: A Ruby client for the DoubleMap real-time transit API.
90
+ test_files: []