mapbox_directions 0.1.1
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.
- checksums.yaml +7 -0
- data/.gitignore +14 -0
- data/.rspec +4 -0
- data/.travis.yml +14 -0
- data/Gemfile +6 -0
- data/Guardfile +5 -0
- data/LICENSE.txt +22 -0
- data/README.md +148 -0
- data/Rakefile +2 -0
- data/lib/mapbox_directions.rb +12 -0
- data/lib/mapbox_directions/client.rb +43 -0
- data/lib/mapbox_directions/error.rb +7 -0
- data/lib/mapbox_directions/model.rb +6 -0
- data/lib/mapbox_directions/model/location.rb +19 -0
- data/lib/mapbox_directions/model/maneuver.rb +14 -0
- data/lib/mapbox_directions/model/point.rb +17 -0
- data/lib/mapbox_directions/model/response.rb +16 -0
- data/lib/mapbox_directions/model/route.rb +24 -0
- data/lib/mapbox_directions/model/step.rb +19 -0
- data/lib/mapbox_directions/parametizer.rb +50 -0
- data/lib/mapbox_directions/response_parser.rb +69 -0
- data/lib/mapbox_directions/version.rb +3 -0
- data/mapbox_directions.gemspec +32 -0
- data/spec/acceptance/directions_spec.rb +158 -0
- data/spec/acceptance/no_routes_found_spec.rb +25 -0
- data/spec/acceptance/raising_exceptions_spec.rb +54 -0
- data/spec/fixtures/cassettes/driving_geojson_as_geometry.yml +186 -0
- data/spec/fixtures/cassettes/driving_polyline_as_geometry.yml +186 -0
- data/spec/fixtures/cassettes/no_routes_found.yml +52 -0
- data/spec/fixtures/cassettes/unauthorized.yml +144 -0
- data/spec/lib/mapbox_directions/client_spec.rb +48 -0
- data/spec/lib/mapbox_directions/model/location_spec.rb +21 -0
- data/spec/lib/mapbox_directions/model/point_spec.rb +17 -0
- data/spec/lib/mapbox_directions/model/route_spec.rb +17 -0
- data/spec/lib/mapbox_directions/parametizer_spec.rb +92 -0
- data/spec/lib/mapbox_directions/response_parser_spec.rb +140 -0
- data/spec/spec_helper.rb +18 -0
- metadata +235 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 499d139ed0106ee1428d94f915bd25e856af786b
|
4
|
+
data.tar.gz: 11282aac7616703f4be00af438f3af4303c3daac
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 46fe7a87a9d0c4040867266f8644c1095de40fc1c66dd645d403d7f97facc454902918ff142c77fc09f53c7bdf5dccf38149d9cb11975529d6423487d8630de8
|
7
|
+
data.tar.gz: b4091582b7fecb8eafe012139cf7171243d6effb776f22222ad6bc1fb694ba9993ee9390cc4393b7edb96821d95e4ee36eb6b9f8e857bffd5e71dd26dda8974e
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
script: CODECLIMATE_REPO_TOKEN=5e7eb3ca9f5744cce3649045cd4887324323c2ffc7b6b3a3be7de1bbb064ddbf bundle exec rspec
|
2
|
+
language: ruby
|
3
|
+
cache: bundler
|
4
|
+
rvm:
|
5
|
+
- 2.0.0
|
6
|
+
- 2.1.0
|
7
|
+
- 2.1.1
|
8
|
+
- 2.1.2
|
9
|
+
- 2.1.3
|
10
|
+
- 2.1.4
|
11
|
+
- 2.1.5
|
12
|
+
- 2.2.0
|
13
|
+
- 2.2.1
|
14
|
+
- 2.2.2
|
data/Gemfile
ADDED
data/Guardfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2015 yonelacort
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
# MapboxDirections
|
2
|
+
|
3
|
+
[](https://travis-ci.org/allyapp/mapbox_directions)
|
4
|
+
[](https://codeclimate.com/github/allyapp/mapbox_directions)
|
5
|
+
[](https://codeclimate.com/github/allyapp/mapbox_directions/coverage)
|
6
|
+
|
7
|
+
Ruby wrapper for the MapBox Directions Service.
|
8
|
+
|
9
|
+
Here you can find the documentation of the API interface:
|
10
|
+
https://www.mapbox.com/developers/api/directions/
|
11
|
+
|
12
|
+
## Installation
|
13
|
+
|
14
|
+
Add this line to your application's Gemfile:
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
gem 'mapbox_directions'
|
18
|
+
```
|
19
|
+
|
20
|
+
And then execute:
|
21
|
+
|
22
|
+
$ bundle
|
23
|
+
|
24
|
+
Or install it yourself as:
|
25
|
+
|
26
|
+
$ gem install mapbox_directions
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
Here's the list of supported parameters and the possible values. Note that parameters that are not optional are required:
|
31
|
+
|
32
|
+
- **access_token**: public token provided by MapBox.
|
33
|
+
- **mode**: mode of transport applied to process the routing.
|
34
|
+
Values: ``driving``, ``cycling``or``walking``.
|
35
|
+
- **origin**: origin decimal coordinates where the route starts.
|
36
|
+
Format: ``"#{lng},#{lat}"``
|
37
|
+
- **destination**: destination decimal coordinates where the route ends.
|
38
|
+
Format: ``"#{lng},#{lat}"``
|
39
|
+
- **geometry**(optional): format for route geometry.
|
40
|
+
Values ``geojson``(default), ``polyline``and ``false`` to omit geometry.
|
41
|
+
- **alternatives**(optional): whether to get more than one route as an alternative or not.
|
42
|
+
Values: ``true``(default) or ``false`` as a Boolean.
|
43
|
+
- **instructions**(optional): format for route instructions.
|
44
|
+
Values: ``text``(default) or ``html``.
|
45
|
+
|
46
|
+
|
47
|
+
```ruby
|
48
|
+
require "mapbox_directions"
|
49
|
+
|
50
|
+
parameters = {
|
51
|
+
access_token: "<your_access_token>",
|
52
|
+
mode: "driving", # %w(driving cycling walking)
|
53
|
+
origin: "-122.42,37.78", # "#{lng},#{lat}"
|
54
|
+
destination: "-77.03,38.91", # "#{lng},#{lat}"
|
55
|
+
geometry: "polyline", # %w(polyline geojson false)
|
56
|
+
alternatives: false, # true or false
|
57
|
+
instructions: "text", # %w(text html)
|
58
|
+
}
|
59
|
+
MapboxDirections.directions(parameters)
|
60
|
+
```
|
61
|
+
|
62
|
+
### Response body
|
63
|
+
|
64
|
+
```ruby
|
65
|
+
MapboxDirections.directions(parameters)
|
66
|
+
```
|
67
|
+
|
68
|
+
Will return a ``MapboxDirections::Response`` that will be composed by:
|
69
|
+
- **origin**(``MapboxDirections::Location``): Origin location of the route.
|
70
|
+
- **destination**(``MapboxDirections::Location``): Destination location of the route.
|
71
|
+
- **waypoints**
|
72
|
+
- **routes**(``MapboxDirections::Route``): Array of routes returned.
|
73
|
+
- **message**: Informative message.
|
74
|
+
- **error**: Informative error message.
|
75
|
+
|
76
|
+
``MapboxDirections::Location``:
|
77
|
+
- **name**
|
78
|
+
- **lat**
|
79
|
+
- **lng**
|
80
|
+
|
81
|
+
``MapboxDirections::Route``:
|
82
|
+
- **distance**
|
83
|
+
- **duration**
|
84
|
+
- **summary**
|
85
|
+
- **geometry**
|
86
|
+
- **steps**(``Array[MapboxDirections::Step]``)
|
87
|
+
- Methods:
|
88
|
+
- **transform_polyline_precision(precision = 1e5)**: When geometry is polyline, polyline representation format are built with precision 6 (``1e6``).
|
89
|
+
In order to get the polyline string transformed into another precision use this method passing the desired precision, which by default is 5 ``1e5``.
|
90
|
+
To know more about how polyline are built from coordinates:
|
91
|
+
https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
92
|
+
|
93
|
+
|
94
|
+
``MapboxDirections::Step``:
|
95
|
+
- **distance**
|
96
|
+
- **duration**
|
97
|
+
- **way_name**
|
98
|
+
- **direction**
|
99
|
+
- **heading**
|
100
|
+
- **maneuver**(``MapboxDirections::Maneuver``)
|
101
|
+
- Methods:
|
102
|
+
- **lat**: Latitude of the maneuver point.
|
103
|
+
- **lng**: Longitude of the maneuver point.
|
104
|
+
|
105
|
+
``MapboxDirections::Maneuver``:
|
106
|
+
- **type**
|
107
|
+
- **location**
|
108
|
+
- **instruction**
|
109
|
+
- Methods:
|
110
|
+
- **lat**: Latitude of the maneuver point.
|
111
|
+
- **lng**: Longitude of the maneuver point.
|
112
|
+
|
113
|
+
|
114
|
+
For more information about what the values of these attributes contain, please look at the [documentation](https://www.mapbox.com/developers/api/directions/).
|
115
|
+
|
116
|
+
### Exceptions
|
117
|
+
|
118
|
+
Exceptions are triggered to give immediate feedback when there's something wrong in the parameters passed that won't allow to get a successful response.
|
119
|
+
|
120
|
+
- **``MapboxDirections::MissingAccessTokenError``**: When the access token is not passed in the parameters or its value is ``nil``
|
121
|
+
|
122
|
+
|
123
|
+
- **``MapboxDirections::InvalidAccessTokenError``**: When the access token is passed in the parameters but it's invalid
|
124
|
+
|
125
|
+
- **``MapboxDirections::CoordinatesFormatError``**: When the decimal coordinates are passed bad formatted given the requirements.
|
126
|
+
|
127
|
+
|
128
|
+
- **``MapboxDirections::UnsupportedTransportModeError``**: When the mode of transport is different that the ones that the service supports.
|
129
|
+
|
130
|
+
|
131
|
+
If the exception raise is an undesired behaviour in the context where the code is being executed, they can be rescued one by one or all at once follows:
|
132
|
+
```ruby
|
133
|
+
require "mapbox_directions"
|
134
|
+
|
135
|
+
def directions(parameters)
|
136
|
+
MapboxDirections.directions(parameters)
|
137
|
+
rescue MapboxDirections::Error
|
138
|
+
# Handle exception
|
139
|
+
end
|
140
|
+
```
|
141
|
+
|
142
|
+
## Contributing
|
143
|
+
|
144
|
+
1. Fork it ( https://github.com/[my-github-username]/mapbox_directions/fork )
|
145
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
146
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
147
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
148
|
+
5. Create a new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
require "mapbox_directions/version"
|
2
|
+
require "mapbox_directions/parametizer"
|
3
|
+
require "mapbox_directions/response_parser"
|
4
|
+
require "mapbox_directions/client"
|
5
|
+
|
6
|
+
module MapboxDirections
|
7
|
+
module_function
|
8
|
+
|
9
|
+
def directions(options)
|
10
|
+
Client.new(options).directions
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require_relative "./parametizer"
|
3
|
+
require_relative "./model"
|
4
|
+
require_relative "./response_parser"
|
5
|
+
|
6
|
+
module MapboxDirections
|
7
|
+
class Client
|
8
|
+
BASE_URL = "https://api.tiles.mapbox.com"
|
9
|
+
PATH = "/v4/directions"
|
10
|
+
|
11
|
+
def initialize(options)
|
12
|
+
@options = options
|
13
|
+
end
|
14
|
+
|
15
|
+
def directions
|
16
|
+
response = Faraday.get(directions_url, parametizer.params_hash)
|
17
|
+
parse_response(response)
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def parse_response(response)
|
23
|
+
body = JSON.parse(response.body)
|
24
|
+
|
25
|
+
case response.status
|
26
|
+
when 200
|
27
|
+
ResponseParser.directions(body)
|
28
|
+
when 401
|
29
|
+
raise InvalidAccessTokenError
|
30
|
+
else
|
31
|
+
Response.new(message: body["message"], error: body["error"])
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def directions_url
|
36
|
+
"#{BASE_URL}#{PATH}/#{parametizer.profile}/#{parametizer.waypoints}.json"
|
37
|
+
end
|
38
|
+
|
39
|
+
def parametizer
|
40
|
+
@parametizer ||= Parametizer.new(@options)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module MapboxDirections
|
4
|
+
class Location
|
5
|
+
extend Forwardable
|
6
|
+
delegate %i(lat lng) => :@point
|
7
|
+
|
8
|
+
attr_reader :point, :name
|
9
|
+
|
10
|
+
def self.from_geojson(geojson)
|
11
|
+
new(point: Point.from_geojson(geojson), name: geojson["properties"]["name"])
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(attrs)
|
15
|
+
@point = attrs[:point] || Point.new(attrs[:lat], attrs[:lng])
|
16
|
+
@name = attrs[:name]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module MapboxDirections
|
2
|
+
class Maneuver
|
3
|
+
extend Forwardable
|
4
|
+
delegate %i(lat lng) => :@location
|
5
|
+
|
6
|
+
attr_reader :type, :location, :instruction
|
7
|
+
|
8
|
+
def initialize(attrs)
|
9
|
+
@type = attrs[:type]
|
10
|
+
@location = attrs[:location]
|
11
|
+
@instruction = attrs[:instruction]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative "./point"
|
2
|
+
|
3
|
+
module MapboxDirections
|
4
|
+
class Point
|
5
|
+
attr_reader :lat, :lng
|
6
|
+
|
7
|
+
def self.from_geojson(geojson)
|
8
|
+
coords = geojson["geometry"]["coordinates"]
|
9
|
+
new(coords.last, coords.first)
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(lat, lng)
|
13
|
+
@lat = lat
|
14
|
+
@lng = lng
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative "./route"
|
2
|
+
|
3
|
+
module MapboxDirections
|
4
|
+
class Response
|
5
|
+
attr_reader :origin, :destination, :waypoints, :routes, :message, :error
|
6
|
+
|
7
|
+
def initialize(attrs)
|
8
|
+
@origin = attrs[:origin]
|
9
|
+
@destination = attrs[:destination]
|
10
|
+
@waypoints = attrs[:waypoints] || []
|
11
|
+
@routes = attrs[:routes] || []
|
12
|
+
@message = attrs[:message]
|
13
|
+
@error = attrs[:error]
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require_relative "./location"
|
2
|
+
require "polylines"
|
3
|
+
|
4
|
+
module MapboxDirections
|
5
|
+
class Route
|
6
|
+
POLYLINE_PRECISION = 1e6
|
7
|
+
|
8
|
+
attr_reader :distance, :duration, :summary, :geometry, :steps
|
9
|
+
|
10
|
+
def initialize(attrs)
|
11
|
+
@distance = attrs[:distance]
|
12
|
+
@duration = attrs[:duration]
|
13
|
+
@summary = attrs[:summary]
|
14
|
+
@geometry = attrs[:geometry]
|
15
|
+
@steps = attrs[:steps]
|
16
|
+
end
|
17
|
+
|
18
|
+
def transform_polyline_precision(precision = 1e5)
|
19
|
+
return @geometry unless @geometry.is_a?(String)
|
20
|
+
line_coordinates = Polylines::Decoder.decode_polyline(@geometry, POLYLINE_PRECISION)
|
21
|
+
Polylines::Encoder.encode_points(line_coordinates, precision)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require_relative "./maneuver"
|
2
|
+
|
3
|
+
module MapboxDirections
|
4
|
+
class Step
|
5
|
+
extend Forwardable
|
6
|
+
delegate %i(lat lng) => :@maneuver
|
7
|
+
|
8
|
+
attr_reader :distance, :duration, :way_name, :direction, :heading, :maneuver
|
9
|
+
|
10
|
+
def initialize(attrs)
|
11
|
+
@distance = attrs[:distance]
|
12
|
+
@duration = attrs[:duration]
|
13
|
+
@way_name = attrs[:way_name]
|
14
|
+
@direction = attrs[:direction]
|
15
|
+
@heading = attrs[:heading]
|
16
|
+
@maneuver = attrs[:maneuver]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require_relative "./error"
|
2
|
+
|
3
|
+
module MapboxDirections
|
4
|
+
class Parametizer
|
5
|
+
ACCEPTED_PARAMS = %w(access_token geometry alternatives instructions)
|
6
|
+
TRANSPORT_MODES = %w(driving cycling walking)
|
7
|
+
ALLOWED_VALUES = {
|
8
|
+
geometry: %w(polyline geojson false),
|
9
|
+
alternatives: [true, false],
|
10
|
+
instructions: %w(text html)
|
11
|
+
}
|
12
|
+
|
13
|
+
def initialize(options)
|
14
|
+
@options = options
|
15
|
+
end
|
16
|
+
|
17
|
+
def params_hash
|
18
|
+
raise MissingAccessTokenError unless filtered_params[:access_token]
|
19
|
+
filtered_params
|
20
|
+
end
|
21
|
+
|
22
|
+
def profile
|
23
|
+
raise UnsupportedTransportModeError unless TRANSPORT_MODES.include?(@options[:mode])
|
24
|
+
"mapbox.#{@options[:mode]}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def waypoints
|
28
|
+
raise CoordinatesFormatError if invalid_waypoints?
|
29
|
+
"#{@options[:origin]};#{@options[:destination]}"
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def filtered_params
|
35
|
+
@filtered_params ||= @options.select { |key, value| valid_key_value?(key, value) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def invalid_waypoints?
|
39
|
+
invalid_coordinates?(@options[:origin]) || invalid_coordinates?(@options[:destination])
|
40
|
+
end
|
41
|
+
|
42
|
+
def invalid_coordinates?(coordinates)
|
43
|
+
/^(\-?\d*(\.\d+)?),(\-?\d*(\.\d+)?)$/.match(coordinates).nil?
|
44
|
+
end
|
45
|
+
|
46
|
+
def valid_key_value?(key, value)
|
47
|
+
key == :access_token || ACCEPTED_PARAMS.include?(key.to_s) && ALLOWED_VALUES[key].include?(value)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|