google_maps_juice 1.0.0 → 1.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.
- checksums.yaml +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +2 -2
- data/README.md +54 -2
- data/google_maps_juice.gemspec +2 -2
- data/lib/google_maps_juice.rb +4 -3
- data/lib/google_maps_juice/client.rb +1 -1
- data/lib/google_maps_juice/directions.rb +55 -0
- data/lib/google_maps_juice/directions/response.rb +63 -0
- data/lib/google_maps_juice/endpoint.rb +1 -1
- data/lib/google_maps_juice/version.rb +1 -1
- metadata +11 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f26ed08354506950932680c98e078c385bce57047a1b99bcab2a122bc26c2112
|
4
|
+
data.tar.gz: 9ea5e1e090fb76f2189468cacfdd9e6993a45936501d78f1bd6ee018a99c80b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dc3ae38123522b60496ff3094678f1aef15dbda36fc4eecd0dc0cc3f18f3389c54b995064e384167ec33e945ab2f8de9766ae80c8bdf8e1086ccb855acfe9cbd
|
7
|
+
data.tar.gz: 612b4cd78edf58cc7ac7c9ba67884c37b32130d7d4eb065aabeaf5cfb9011b3652e684eae4d78fef0f7ceb65584a45721a0a1d1e3de8b20746c7737659bea9c3
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.6.3
|
data/.travis.yml
CHANGED
data/README.md
CHANGED
@@ -17,6 +17,7 @@ This gem aims at progressively covering a fair amount of those widely-used servi
|
|
17
17
|
|
18
18
|
* Geocoding
|
19
19
|
* Time Zone
|
20
|
+
* Directions
|
20
21
|
|
21
22
|
Contributors are welcome!
|
22
23
|
|
@@ -72,13 +73,13 @@ This is especially useful in some "hybrid" scenario, where an API key is shared
|
|
72
73
|
|
73
74
|
## Error Handling
|
74
75
|
|
75
|
-
If Google servers respond with a non-successful HTTP status code, i.e. `4xx` or `5xx`, a `GoogleMapsJuice::
|
76
|
+
If Google servers respond with a non-successful HTTP status code, i.e. `4xx` or `5xx`, a `GoogleMapsJuice::ResponseError` is raised with a message of the form `'HTTP 503 - Error details as returned by the server'`.
|
76
77
|
|
77
78
|
API errors are also handled, based on the `status` attribute of Google's JSON response, and the optional `error_message` attribute.
|
78
79
|
|
79
80
|
* `GoogleMapsJuice::ZeroResults` is raised when `status` is `'ZERO_RESULTS'`
|
80
81
|
* `GoogleMapsJuice::ApiLimitError` is raised when `status` is `'OVER_DAILY_LIMIT'` or `'OVER_QUERY_LIMIT'`
|
81
|
-
* `GoogleMapsJuice::
|
82
|
+
* `GoogleMapsJuice::ResponseError` is raised when `status` is not `OK` with a message of the form `API <status> - <error_message>`
|
82
83
|
|
83
84
|
|
84
85
|
## Geocoding
|
@@ -181,6 +182,57 @@ The `by_location` method returns a `GoogleMapsJuice::Timezone::Response`. It's a
|
|
181
182
|
* `dst_offset`: the offset for daylight-savings time in seconds
|
182
183
|
|
183
184
|
|
185
|
+
## Directions
|
186
|
+
|
187
|
+
[Google's Directions API](https://developers.google.com/maps/documentation/directions/intro#DirectionsRequests) returns the possible routes of given origin and destination geographic locations; Google's API accepts address, textual latitude/longitude value, or place ID of which you wish to calculate directions. Currently this gem implements only latitude/longitude mode.
|
188
|
+
`GoogleMapsJuice` will raise an `ArgumentError` if some unsupported param is passed, or when none of the required params are passed.
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
response = GoogleMapsJuice::Directions.find(origin: '41.8892732,12.4921921', destination: '41.9016488,12.4583003')
|
192
|
+
```
|
193
|
+
|
194
|
+
Compared to Google's raw API request, it provides validation of both origin and destination, in order to avoid sending requests when they would fail for sure - to learn more see `spec/unit/directions_spec.rb`.
|
195
|
+
|
196
|
+
**Accepted params:**
|
197
|
+
|
198
|
+
* Both `origin` and `destination` are mandatory
|
199
|
+
* `origin` is composed by `latitude` and `longitude`, comma separated float values
|
200
|
+
* `destination` same format as `origin`
|
201
|
+
|
202
|
+
|
203
|
+
### Directions Response
|
204
|
+
|
205
|
+
The `find` method returns a `GoogleMapsJuice::Directions::Response`. It's a `Hash` representation of Google's JSON response. However, it also provides a few useful methods:
|
206
|
+
|
207
|
+
* `results`: the `Hash` raw result
|
208
|
+
|
209
|
+
* `routes`: an `Array` of `GoogleMapsJuice::Directions::Response::Route` objects
|
210
|
+
|
211
|
+
* `first`: the first `Route` of the `routes` `List`
|
212
|
+
|
213
|
+
As described in [Google's Directions API](https://developers.google.com/maps/documentation/directions/intro#Routes), the response contains all possible routes. Each route has some attributes and one or more *legs*, wich in turn have one or more *steps*.
|
214
|
+
If no waypoints are passed, the route response will contain a single leg. Since `GoogleMapsJuice::Directions` doesn't handles waypoints yet, only the first leg is considered for each route.
|
215
|
+
The `GoogleMapsJuice::Directions::Response::Route` is a representation of a response route and provides methods to access all route's attributes:
|
216
|
+
|
217
|
+
* `summary`: a brief description of the route
|
218
|
+
|
219
|
+
* `legs`: all legs of the route, generally a single one
|
220
|
+
|
221
|
+
* `steps`: all steps of the first route's leg
|
222
|
+
|
223
|
+
* `duration`: time duration of the first route's leg
|
224
|
+
|
225
|
+
* `distance`: distance between origin and destination of first route's leg
|
226
|
+
|
227
|
+
* `start_location`: `latitude`/`longitude` of the origin first route's leg
|
228
|
+
|
229
|
+
* `end_location`: `latitude`/`longitude` of the destination first route's leg
|
230
|
+
|
231
|
+
* `start_address`: address of the origin first route's leg
|
232
|
+
|
233
|
+
* `end_address`: address of the destination first route's leg
|
234
|
+
|
235
|
+
|
184
236
|
## Development
|
185
237
|
|
186
238
|
After checking out the repo, run `bin/setup` to install dependencies. Create a `.env` file and save your Google API key there; if you want to use a different key for testing, put it in `.env.test` and it will override the one in `.env`.
|
data/google_maps_juice.gemspec
CHANGED
@@ -22,10 +22,10 @@ Gem::Specification.new do |spec|
|
|
22
22
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
23
23
|
spec.require_paths = ["lib"]
|
24
24
|
|
25
|
-
spec.add_dependency 'activesupport'
|
25
|
+
spec.add_dependency 'activesupport'
|
26
26
|
spec.add_dependency 'excon'
|
27
27
|
|
28
|
-
spec.add_development_dependency 'bundler', '~> 1.
|
28
|
+
spec.add_development_dependency 'bundler', '~> 1.17.2'
|
29
29
|
spec.add_development_dependency 'rake', '~> 12.3'
|
30
30
|
spec.add_development_dependency 'rspec', '~> 3.5'
|
31
31
|
spec.add_development_dependency 'webmock', '~> 3.4'
|
data/lib/google_maps_juice.rb
CHANGED
@@ -14,8 +14,9 @@ module GoogleMapsJuice
|
|
14
14
|
autoload :Endpoint, 'google_maps_juice/endpoint'
|
15
15
|
autoload :Geocoding, 'google_maps_juice/geocoding'
|
16
16
|
autoload :Timezone, 'google_maps_juice/timezone'
|
17
|
+
autoload :Directions, 'google_maps_juice/directions'
|
17
18
|
|
18
|
-
class
|
19
|
-
class ApiLimitError <
|
20
|
-
class ZeroResults <
|
19
|
+
class ResponseError < RuntimeError; end
|
20
|
+
class ApiLimitError < ResponseError; end
|
21
|
+
class ZeroResults < ResponseError; end
|
21
22
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module GoogleMapsJuice
|
2
|
+
class Directions < Endpoint
|
3
|
+
|
4
|
+
ENDPOINT = '/directions'
|
5
|
+
|
6
|
+
autoload :Response, 'google_maps_juice/directions/response'
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def find(params, api_key: GoogleMapsJuice.config.api_key)
|
10
|
+
client = GoogleMapsJuice::Client.new(api_key: api_key)
|
11
|
+
new(client).find(params)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def find(params)
|
16
|
+
validate_find_params(params)
|
17
|
+
response_text = @client.get("#{ENDPOINT}/json", params)
|
18
|
+
response = JSON.parse(response_text, object_class: Response)
|
19
|
+
detect_errors(response)
|
20
|
+
end
|
21
|
+
|
22
|
+
def validate_find_params(params)
|
23
|
+
raise ArgumentError, 'Hash argument expected' unless params.is_a?(Hash)
|
24
|
+
|
25
|
+
supported_keys = %w[origin destination]
|
26
|
+
validate_supported_params(params, supported_keys)
|
27
|
+
|
28
|
+
required_keys = %w[origin destination]
|
29
|
+
validate_any_required_params(params, required_keys)
|
30
|
+
|
31
|
+
validate_geo_coordinate(params)
|
32
|
+
end
|
33
|
+
|
34
|
+
def validate_geo_coordinate(params)
|
35
|
+
raise ArgumentError, 'String argument expected' unless params.values.all?(String)
|
36
|
+
|
37
|
+
geocoords = params.values.map { |x| x.split(',') }.flatten
|
38
|
+
geocoords.map! { |x| Float(x).round(7) }
|
39
|
+
raise ArgumentError, 'Wrong geo-coordinates' if geocoords.size != 4
|
40
|
+
|
41
|
+
validate_location_params(geocoords)
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_location_params(params)
|
45
|
+
latitudes = params[0], params[2]
|
46
|
+
if latitudes.any? { |l| l.abs > 90 }
|
47
|
+
raise ArgumentError, 'Wrong latitude value'
|
48
|
+
end
|
49
|
+
longitudes = params[1], params[3]
|
50
|
+
if longitudes.any? { |l| l.abs > 180 }
|
51
|
+
raise ArgumentError, 'Wrong longitude value'
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'active_support/core_ext/hash/slice'
|
4
|
+
|
5
|
+
module GoogleMapsJuice
|
6
|
+
class Directions::Response < GoogleMapsJuice::Endpoint::Response
|
7
|
+
def results
|
8
|
+
self['routes']
|
9
|
+
end
|
10
|
+
|
11
|
+
def routes
|
12
|
+
results.map { |r| Route.new(r) }
|
13
|
+
end
|
14
|
+
|
15
|
+
def first
|
16
|
+
routes.first
|
17
|
+
end
|
18
|
+
|
19
|
+
class Route
|
20
|
+
attr_reader :route, :first_leg
|
21
|
+
def initialize(route)
|
22
|
+
@route = route
|
23
|
+
@first_leg = route['legs'].first
|
24
|
+
end
|
25
|
+
|
26
|
+
def legs
|
27
|
+
route['legs']
|
28
|
+
end
|
29
|
+
|
30
|
+
def summary
|
31
|
+
route['summary']
|
32
|
+
end
|
33
|
+
|
34
|
+
def steps
|
35
|
+
first_leg['steps']
|
36
|
+
end
|
37
|
+
|
38
|
+
def duration
|
39
|
+
first_leg['duration']
|
40
|
+
end
|
41
|
+
|
42
|
+
def distance
|
43
|
+
first_leg['distance']
|
44
|
+
end
|
45
|
+
|
46
|
+
def start_location
|
47
|
+
first_leg['start_location']
|
48
|
+
end
|
49
|
+
|
50
|
+
def end_location
|
51
|
+
first_leg['end_location']
|
52
|
+
end
|
53
|
+
|
54
|
+
def start_address
|
55
|
+
first_leg['start_address']
|
56
|
+
end
|
57
|
+
|
58
|
+
def end_address
|
59
|
+
first_leg['end_address']
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -14,7 +14,7 @@ module GoogleMapsJuice
|
|
14
14
|
elsif response.limit_error?
|
15
15
|
raise GoogleMapsJuice::ApiLimitError, build_error_message(response)
|
16
16
|
elsif response.error?
|
17
|
-
raise GoogleMapsJuice::
|
17
|
+
raise GoogleMapsJuice::ResponseError, "API #{build_error_message(response)}"
|
18
18
|
else
|
19
19
|
response
|
20
20
|
end
|
metadata
CHANGED
@@ -1,29 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: google_maps_juice
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Algonauti srl
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-07-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: excon
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 1.17.2
|
48
48
|
type: :development
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 1.17.2
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: rake
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -159,6 +159,8 @@ files:
|
|
159
159
|
- lib/google_maps_juice.rb
|
160
160
|
- lib/google_maps_juice/client.rb
|
161
161
|
- lib/google_maps_juice/configuration.rb
|
162
|
+
- lib/google_maps_juice/directions.rb
|
163
|
+
- lib/google_maps_juice/directions/response.rb
|
162
164
|
- lib/google_maps_juice/endpoint.rb
|
163
165
|
- lib/google_maps_juice/geocoding.rb
|
164
166
|
- lib/google_maps_juice/geocoding/response.rb
|
@@ -183,8 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
183
185
|
- !ruby/object:Gem::Version
|
184
186
|
version: '0'
|
185
187
|
requirements: []
|
186
|
-
|
187
|
-
rubygems_version: 2.7.3
|
188
|
+
rubygems_version: 3.0.3
|
188
189
|
signing_key:
|
189
190
|
specification_version: 4
|
190
191
|
summary: 'Client for popular Google Maps API Services: Geocoding, Time Zones'
|