google_distance_matrix 0.4.0 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.editorconfig +16 -0
- data/.rubocop.yml +6 -0
- data/.ruby-version +1 -1
- data/.travis.yml +4 -6
- data/CHANGELOG.md +40 -0
- data/Gemfile +2 -0
- data/README.md +0 -3
- data/Rakefile +9 -4
- data/google_distance_matrix.gemspec +21 -19
- data/lib/google_distance_matrix.rb +25 -23
- data/lib/google_distance_matrix/client.rb +32 -18
- data/lib/google_distance_matrix/client_cache.rb +9 -3
- data/lib/google_distance_matrix/configuration.rb +39 -24
- data/lib/google_distance_matrix/errors.rb +6 -3
- data/lib/google_distance_matrix/log_subscriber.rb +14 -14
- data/lib/google_distance_matrix/logger.rb +7 -5
- data/lib/google_distance_matrix/matrix.rb +45 -22
- data/lib/google_distance_matrix/place.rb +37 -28
- data/lib/google_distance_matrix/places.rb +5 -4
- data/lib/google_distance_matrix/polyline_encoder.rb +2 -2
- data/lib/google_distance_matrix/polyline_encoder/delta.rb +4 -2
- data/lib/google_distance_matrix/polyline_encoder/value_encoder.rb +13 -5
- data/lib/google_distance_matrix/railtie.rb +4 -1
- data/lib/google_distance_matrix/route.rb +22 -15
- data/lib/google_distance_matrix/routes_finder.rb +27 -29
- data/lib/google_distance_matrix/url_builder.rb +44 -16
- data/lib/google_distance_matrix/url_builder/polyline_encoder_buffer.rb +3 -0
- data/lib/google_distance_matrix/version.rb +3 -1
- data/spec/lib/google_distance_matrix/client_cache_spec.rb +27 -11
- data/spec/lib/google_distance_matrix/client_spec.rb +40 -30
- data/spec/lib/google_distance_matrix/configuration_spec.rb +36 -24
- data/spec/lib/google_distance_matrix/log_subscriber_spec.rb +13 -44
- data/spec/lib/google_distance_matrix/logger_spec.rb +16 -13
- data/spec/lib/google_distance_matrix/matrix_spec.rb +90 -57
- data/spec/lib/google_distance_matrix/place_spec.rb +38 -25
- data/spec/lib/google_distance_matrix/places_spec.rb +29 -28
- data/spec/lib/google_distance_matrix/polyline_encoder/delta_spec.rb +5 -3
- data/spec/lib/google_distance_matrix/polyline_encoder_spec.rb +7 -2
- data/spec/lib/google_distance_matrix/route_spec.rb +11 -9
- data/spec/lib/google_distance_matrix/routes_finder_spec.rb +124 -81
- data/spec/lib/google_distance_matrix/url_builder_spec.rb +97 -48
- data/spec/spec_helper.rb +3 -1
- metadata +46 -18
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: de97d6fbd5c11056be61c2fbdade541bcd9e04f95dfdc3d3994d25e97b21476b
|
4
|
+
data.tar.gz: 71fb7ba1f8c2e707a95878219ddf99e040892d6d197a1ed5c33bed671191628e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0304ccbedb35ddde62968025032e2b3d83a962ec857d739df35e3645c4b4220e1aa554729876bcc4aa26e0a9db008ff0e67e314c23ddf4bcbef4951f9d0d13c8
|
7
|
+
data.tar.gz: 650669b42ece96bb992ffccc3738f09ab97d81c02129fdcd4ca0007c921e32fbd834126aec5af62074be5f25ad422f88be3ca454d15c47d83cf60e33ba990ede
|
data/.editorconfig
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# EditorConfig helps developers define and maintain consistent
|
2
|
+
# coding styles between different editors and IDEs
|
3
|
+
# editorconfig.org
|
4
|
+
|
5
|
+
root = true
|
6
|
+
|
7
|
+
[*]
|
8
|
+
end_of_line = lf
|
9
|
+
charset = utf-8
|
10
|
+
trim_trailing_whitespace = true
|
11
|
+
insert_final_newline = true
|
12
|
+
indent_style = space
|
13
|
+
indent_size = 2
|
14
|
+
|
15
|
+
[*.{diff,md}]
|
16
|
+
trim_trailing_whitespace = false
|
data/.rubocop.yml
ADDED
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
2.
|
1
|
+
2.5.5
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,43 @@
|
|
1
|
+
## v.0.6.3
|
2
|
+
|
3
|
+
* chore: bumped dependency support up to Rails 6.1 (by mintyfresh)
|
4
|
+
|
5
|
+
## v.0.6.2
|
6
|
+
|
7
|
+
* chore: bumped dependency support up to Rails 6 (by zackchandler)
|
8
|
+
|
9
|
+
## v.0.6.1
|
10
|
+
|
11
|
+
* fix: when matrix places were built from hashes, passing hashes to route/s_for doesnt't work (by brauliomartinezlm)
|
12
|
+
* fix: place comparison was not working with == (by brauliomartinezlm)
|
13
|
+
|
14
|
+
## v.0.6.0
|
15
|
+
|
16
|
+
* Depend on activemodel & activesupport < 5.3 (by brauliomartinezlm)
|
17
|
+
* Tested with Ruby 2.5.
|
18
|
+
* Dropped support for Ruby 2.2 and below.
|
19
|
+
* Added support for `channel` (by michaelgpearce)
|
20
|
+
|
21
|
+
## v.0.5.0
|
22
|
+
|
23
|
+
This release contains breaking change where `url` has been renamed to
|
24
|
+
`sensitive_url`. A `filtered_url` method is added to make it clear that
|
25
|
+
the URL returned is filtered according to configuration while the other one
|
26
|
+
will contain sensitive information like key and signature.
|
27
|
+
|
28
|
+
The cache key is changed so it no longer uses the URL, but a digest of the URL
|
29
|
+
as key. You may set `config.cache_key_transform` to a block passing given url
|
30
|
+
through if you don't want this.
|
31
|
+
|
32
|
+
* Fixed an issue where read/write to cache used url with sensitive data and
|
33
|
+
and filtered url resulting in cache miss.
|
34
|
+
* Instrumentation payload `url` renamed `sensitive_url`.
|
35
|
+
* Instrumentation payload added `filtered_url`.
|
36
|
+
* Cache key is a digest of the `sensitive_url` so we don't store in cache the
|
37
|
+
sensitive parts of the URL.
|
38
|
+
* Digesting cache key is configurable with `cache_key_transform`. It's a callable
|
39
|
+
object expected to take the url and transform it to the key you want.
|
40
|
+
|
1
41
|
## v.0.4.0
|
2
42
|
* When mode is `driving` and `departure_time` is set all `route` objects will contain
|
3
43
|
`duration_in_traffic_in_seconds` and `duration_in_traffic_text`.
|
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -11,9 +11,6 @@ pull the distance matrix from Google.
|
|
11
11
|
Once you have the matrix you can fetch all routes from a given
|
12
12
|
origin or to a given destination.
|
13
13
|
|
14
|
-
The matrix may also be used as a data set for traveling salesman problem,
|
15
|
-
but to solve it you may look at <http://ai4r.org/>.
|
16
|
-
|
17
14
|
|
18
15
|
|
19
16
|
|
data/Rakefile
CHANGED
@@ -1,9 +1,14 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'bundler/gem_tasks'
|
4
|
+
|
5
|
+
require 'rubocop/rake_task'
|
6
|
+
RuboCop::RakeTask.new
|
7
|
+
|
8
|
+
require 'rspec/core/rake_task'
|
4
9
|
RSpec::Core::RakeTask.new(:spec) do |t|
|
5
|
-
t.rspec_opts = [
|
10
|
+
t.rspec_opts = ['-c', '-f progress', '-r ./spec/spec_helper.rb']
|
6
11
|
t.pattern = 'spec/**/*_spec.rb'
|
7
12
|
end
|
8
13
|
|
9
|
-
task default:
|
14
|
+
task default: %i[rubocop spec]
|
@@ -1,30 +1,32 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_String_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'google_distance_matrix/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'google_distance_matrix'
|
8
9
|
spec.version = GoogleDistanceMatrix::VERSION
|
9
|
-
spec.authors = [
|
10
|
-
spec.email = [
|
11
|
-
spec.description = %
|
12
|
-
spec.summary = %
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
10
|
+
spec.authors = ['Thorbjørn Hermansen']
|
11
|
+
spec.email = ['thhermansen@gmail.com']
|
12
|
+
spec.description = %(Ruby client for The Google Distance Matrix API)
|
13
|
+
spec.summary = %(Ruby client for The Google Distance Matrix API)
|
14
|
+
spec.homepage = ''
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
|
-
spec.files = `git ls-files`.split(
|
17
|
+
spec.files = `git ls-files`.split($RS)
|
17
18
|
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
-
spec.require_paths = [
|
20
|
+
spec.require_paths = ['lib']
|
20
21
|
|
21
|
-
spec.add_dependency
|
22
|
-
spec.add_dependency
|
23
|
-
spec.add_dependency
|
22
|
+
spec.add_dependency 'activemodel', '>= 3.2.13', '< 6.2'
|
23
|
+
spec.add_dependency 'activesupport', '>= 3.2.13', '< 6.2'
|
24
|
+
spec.add_dependency 'google_business_api_url_signer', '~> 0.1.3'
|
24
25
|
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
28
|
-
spec.add_development_dependency
|
29
|
-
spec.add_development_dependency
|
26
|
+
spec.add_development_dependency 'bundler'
|
27
|
+
spec.add_development_dependency 'rake'
|
28
|
+
spec.add_development_dependency 'rspec', '~> 3.8.0'
|
29
|
+
spec.add_development_dependency 'rubocop', '~> 0.59.2'
|
30
|
+
spec.add_development_dependency 'shoulda-matchers', '~> 4.0.0.rc1'
|
31
|
+
spec.add_development_dependency 'webmock', '~> 3.4.2'
|
30
32
|
end
|
@@ -1,29 +1,31 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
|
9
|
-
require
|
10
|
-
|
11
|
-
require
|
12
|
-
require
|
13
|
-
require
|
14
|
-
require
|
15
|
-
require
|
16
|
-
require
|
17
|
-
require
|
18
|
-
require
|
19
|
-
require
|
20
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'google_distance_matrix/version'
|
4
|
+
|
5
|
+
require 'cgi'
|
6
|
+
require 'json'
|
7
|
+
require 'active_model'
|
8
|
+
require 'active_support/core_ext/hash'
|
9
|
+
require 'google_business_api_url_signer'
|
10
|
+
|
11
|
+
require 'google_distance_matrix/logger'
|
12
|
+
require 'google_distance_matrix/errors'
|
13
|
+
require 'google_distance_matrix/configuration'
|
14
|
+
require 'google_distance_matrix/url_builder'
|
15
|
+
require 'google_distance_matrix/client'
|
16
|
+
require 'google_distance_matrix/client_cache'
|
17
|
+
require 'google_distance_matrix/routes_finder'
|
18
|
+
require 'google_distance_matrix/matrix'
|
19
|
+
require 'google_distance_matrix/places'
|
20
|
+
require 'google_distance_matrix/place'
|
21
|
+
require 'google_distance_matrix/route'
|
22
|
+
require 'google_distance_matrix/polyline_encoder'
|
21
23
|
|
22
24
|
require 'google_distance_matrix/railtie' if defined? Rails
|
23
25
|
|
24
|
-
|
26
|
+
# Main module for the GoogleDistanceMatrix
|
25
27
|
module GoogleDistanceMatrix
|
26
|
-
|
28
|
+
module_function
|
27
29
|
|
28
30
|
def default_configuration
|
29
31
|
@default_configuration ||= Configuration.new
|
@@ -38,4 +40,4 @@ module GoogleDistanceMatrix
|
|
38
40
|
end
|
39
41
|
end
|
40
42
|
|
41
|
-
require
|
43
|
+
require 'google_distance_matrix/log_subscriber'
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
4
|
+
# HTTP client making request to Google's API
|
2
5
|
class Client
|
3
6
|
CLIENT_ERRORS = %w[
|
4
7
|
INVALID_REQUEST
|
@@ -6,41 +9,52 @@ module GoogleDistanceMatrix
|
|
6
9
|
OVER_QUERY_LIMIT
|
7
10
|
REQUEST_DENIED
|
8
11
|
UNKNOWN_ERROR
|
9
|
-
]
|
10
|
-
|
11
|
-
|
12
|
+
].freeze
|
13
|
+
|
14
|
+
# Make a GET request to given URL
|
15
|
+
#
|
16
|
+
# @param url The URL to Google's API we'll make a request to
|
17
|
+
# @param instrumentation A hash with instrumentation payload
|
18
|
+
# @param options Other options we don't care about, for example we'll capture
|
19
|
+
# `configuration` option which we are not using, but the ClientCache
|
20
|
+
# is using.
|
21
|
+
#
|
22
|
+
# @return Hash with data from parsed response body
|
23
|
+
def get(url, instrumentation: {}, **_options)
|
12
24
|
uri = URI.parse url
|
13
|
-
instrumentation = {url: url}.merge(options[:instrumentation] || {})
|
14
25
|
|
15
|
-
response = ActiveSupport::Notifications.instrument
|
26
|
+
response = ActiveSupport::Notifications.instrument(
|
27
|
+
'client_request_matrix_data.google_distance_matrix', instrumentation
|
28
|
+
) do
|
16
29
|
Net::HTTP.get_response uri
|
17
30
|
end
|
18
31
|
|
32
|
+
handle response, url
|
33
|
+
rescue Timeout::Error => error
|
34
|
+
raise ServerError, error
|
35
|
+
end
|
36
|
+
|
37
|
+
private
|
38
|
+
|
39
|
+
def handle(response, url) # rubocop:disable Metrics/MethodLength
|
19
40
|
case response
|
20
41
|
when Net::HTTPSuccess
|
21
42
|
inspect_for_client_errors! response
|
22
43
|
when Net::HTTPRequestURITooLong
|
23
|
-
|
44
|
+
raise MatrixUrlTooLong.new url, UrlBuilder::MAX_URL_SIZE, response
|
24
45
|
when Net::HTTPClientError
|
25
|
-
|
46
|
+
raise ClientError, response
|
26
47
|
when Net::HTTPServerError
|
27
|
-
|
48
|
+
raise ServerError, response
|
28
49
|
else # Handle this as a request error for now. Maybe fine tune this more later.
|
29
|
-
|
50
|
+
raise ServerError, response
|
30
51
|
end
|
31
|
-
rescue Timeout::Error => error
|
32
|
-
fail ServerError.new error
|
33
52
|
end
|
34
53
|
|
35
|
-
|
36
|
-
private
|
37
|
-
|
38
54
|
def inspect_for_client_errors!(response)
|
39
|
-
status = JSON.parse(response.body).fetch
|
55
|
+
status = JSON.parse(response.body).fetch 'status'
|
40
56
|
|
41
|
-
if CLIENT_ERRORS.include? status
|
42
|
-
fail ClientError.new response, status
|
43
|
-
end
|
57
|
+
raise ClientError.new response, status if CLIENT_ERRORS.include? status
|
44
58
|
|
45
59
|
response
|
46
60
|
end
|
@@ -1,9 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
4
|
+
# Cached client, which takes care of caching data from Google API
|
2
5
|
class ClientCache
|
3
6
|
attr_reader :client, :cache
|
4
7
|
|
5
|
-
|
6
|
-
|
8
|
+
# Returns a cache key for given URL
|
9
|
+
#
|
10
|
+
# @return String
|
11
|
+
def self.key(url, config)
|
12
|
+
config.cache_key_transform.call url
|
7
13
|
end
|
8
14
|
|
9
15
|
def initialize(client, cache)
|
@@ -12,7 +18,7 @@ module GoogleDistanceMatrix
|
|
12
18
|
end
|
13
19
|
|
14
20
|
def get(url, options = {})
|
15
|
-
cache.fetch self.class.key(url) do
|
21
|
+
cache.fetch self.class.key(url, options.fetch(:configuration)) do
|
16
22
|
client.get url, options
|
17
23
|
end
|
18
24
|
end
|
@@ -1,3 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'digest'
|
4
|
+
|
1
5
|
module GoogleDistanceMatrix
|
2
6
|
# Public: Configuration of matrix and it's request.
|
3
7
|
#
|
@@ -14,20 +18,21 @@ module GoogleDistanceMatrix
|
|
14
18
|
mode avoid units language
|
15
19
|
departure_time arrival_time
|
16
20
|
transit_mode transit_routing_preference
|
17
|
-
traffic_model
|
18
|
-
]
|
21
|
+
traffic_model channel
|
22
|
+
].freeze
|
19
23
|
|
20
24
|
API_DEFAULTS = {
|
21
|
-
mode:
|
22
|
-
units:
|
23
|
-
traffic_model:
|
25
|
+
mode: 'driving',
|
26
|
+
units: 'metric',
|
27
|
+
traffic_model: 'best_guess',
|
24
28
|
use_encoded_polylines: false,
|
25
29
|
protocol: 'https',
|
26
30
|
lat_lng_scale: 5,
|
27
|
-
filter_parameters_in_logged_url: [
|
31
|
+
filter_parameters_in_logged_url: %w[key signature].freeze,
|
32
|
+
cache_key_transform: ->(url) { Digest::SHA512.new.update(url).to_s }
|
28
33
|
}.with_indifferent_access
|
29
34
|
|
30
|
-
attr_accessor
|
35
|
+
attr_accessor(*ATTRIBUTES)
|
31
36
|
|
32
37
|
# The protocol to use, either http or https
|
33
38
|
attr_accessor :protocol
|
@@ -50,22 +55,38 @@ module GoogleDistanceMatrix
|
|
50
55
|
# When logging we filter sensitive parameters
|
51
56
|
attr_accessor :filter_parameters_in_logged_url
|
52
57
|
|
53
|
-
|
54
|
-
|
55
|
-
|
58
|
+
# Callable object which transform given url to key used in cache
|
59
|
+
# @see ClientCache
|
60
|
+
attr_accessor :cache_key_transform
|
61
|
+
|
62
|
+
validates :mode, inclusion: { in: %w[driving walking bicycling transit] }, allow_blank: true
|
63
|
+
validates :avoid, inclusion: { in: %w[tolls highways ferries indoor] }, allow_blank: true
|
64
|
+
validates :units, inclusion: { in: %w[metric imperial] }, allow_blank: true
|
56
65
|
|
57
66
|
validates :departure_time, format: /\A(\d+|now)\Z/, allow_blank: true
|
58
67
|
validates :arrival_time, numericality: true, allow_blank: true
|
59
68
|
|
60
|
-
validates :transit_mode,
|
61
|
-
|
62
|
-
|
69
|
+
validates :transit_mode,
|
70
|
+
inclusion: { in: %w[bus subway train tram rail] },
|
71
|
+
allow_blank: true
|
72
|
+
|
73
|
+
validates :transit_routing_preference,
|
74
|
+
inclusion: { in: %w[less_walking fewer_transfers] },
|
75
|
+
allow_blank: true
|
76
|
+
|
77
|
+
validates :traffic_model,
|
78
|
+
inclusion: { in: %w[best_guess pessimistic optimistic] },
|
79
|
+
allow_blank: true
|
63
80
|
|
64
|
-
validates :protocol, inclusion: {in: [
|
81
|
+
validates :protocol, inclusion: { in: %w[http https] }, allow_blank: true
|
65
82
|
|
66
83
|
def initialize
|
67
84
|
API_DEFAULTS.each_pair do |attr_name, value|
|
68
|
-
self[attr_name] =
|
85
|
+
self[attr_name] = begin
|
86
|
+
value.dup
|
87
|
+
rescue StandardError
|
88
|
+
value
|
89
|
+
end
|
69
90
|
end
|
70
91
|
end
|
71
92
|
|
@@ -77,7 +98,6 @@ module GoogleDistanceMatrix
|
|
77
98
|
public_send "#{attr_name}=", value
|
78
99
|
end
|
79
100
|
|
80
|
-
|
81
101
|
private
|
82
102
|
|
83
103
|
def array_param
|
@@ -85,19 +105,14 @@ module GoogleDistanceMatrix
|
|
85
105
|
attr_and_value[1].nil? || param_same_as_api_default?(attr_and_value)
|
86
106
|
end
|
87
107
|
|
88
|
-
if google_business_api_client_id.present?
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
if google_api_key.present?
|
93
|
-
out << ['key', google_api_key]
|
94
|
-
end
|
108
|
+
out << ['client', google_business_api_client_id] if google_business_api_client_id.present?
|
109
|
+
out << ['key', google_api_key] if google_api_key.present?
|
95
110
|
|
96
111
|
out
|
97
112
|
end
|
98
113
|
|
99
114
|
def param_same_as_api_default?(param)
|
100
|
-
|
115
|
+
API_DEFAULTS[param[0]] == param[1]
|
101
116
|
end
|
102
117
|
end
|
103
118
|
end
|