google_distance_matrix 0.4.0 → 0.6.3

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.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/.editorconfig +16 -0
  3. data/.rubocop.yml +6 -0
  4. data/.ruby-version +1 -1
  5. data/.travis.yml +4 -6
  6. data/CHANGELOG.md +40 -0
  7. data/Gemfile +2 -0
  8. data/README.md +0 -3
  9. data/Rakefile +9 -4
  10. data/google_distance_matrix.gemspec +21 -19
  11. data/lib/google_distance_matrix.rb +25 -23
  12. data/lib/google_distance_matrix/client.rb +32 -18
  13. data/lib/google_distance_matrix/client_cache.rb +9 -3
  14. data/lib/google_distance_matrix/configuration.rb +39 -24
  15. data/lib/google_distance_matrix/errors.rb +6 -3
  16. data/lib/google_distance_matrix/log_subscriber.rb +14 -14
  17. data/lib/google_distance_matrix/logger.rb +7 -5
  18. data/lib/google_distance_matrix/matrix.rb +45 -22
  19. data/lib/google_distance_matrix/place.rb +37 -28
  20. data/lib/google_distance_matrix/places.rb +5 -4
  21. data/lib/google_distance_matrix/polyline_encoder.rb +2 -2
  22. data/lib/google_distance_matrix/polyline_encoder/delta.rb +4 -2
  23. data/lib/google_distance_matrix/polyline_encoder/value_encoder.rb +13 -5
  24. data/lib/google_distance_matrix/railtie.rb +4 -1
  25. data/lib/google_distance_matrix/route.rb +22 -15
  26. data/lib/google_distance_matrix/routes_finder.rb +27 -29
  27. data/lib/google_distance_matrix/url_builder.rb +44 -16
  28. data/lib/google_distance_matrix/url_builder/polyline_encoder_buffer.rb +3 -0
  29. data/lib/google_distance_matrix/version.rb +3 -1
  30. data/spec/lib/google_distance_matrix/client_cache_spec.rb +27 -11
  31. data/spec/lib/google_distance_matrix/client_spec.rb +40 -30
  32. data/spec/lib/google_distance_matrix/configuration_spec.rb +36 -24
  33. data/spec/lib/google_distance_matrix/log_subscriber_spec.rb +13 -44
  34. data/spec/lib/google_distance_matrix/logger_spec.rb +16 -13
  35. data/spec/lib/google_distance_matrix/matrix_spec.rb +90 -57
  36. data/spec/lib/google_distance_matrix/place_spec.rb +38 -25
  37. data/spec/lib/google_distance_matrix/places_spec.rb +29 -28
  38. data/spec/lib/google_distance_matrix/polyline_encoder/delta_spec.rb +5 -3
  39. data/spec/lib/google_distance_matrix/polyline_encoder_spec.rb +7 -2
  40. data/spec/lib/google_distance_matrix/route_spec.rb +11 -9
  41. data/spec/lib/google_distance_matrix/routes_finder_spec.rb +124 -81
  42. data/spec/lib/google_distance_matrix/url_builder_spec.rb +97 -48
  43. data/spec/spec_helper.rb +3 -1
  44. metadata +46 -18
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 3ca9d7d93abd6340a3cb5d36d03cbadfda5e4e1c
4
- data.tar.gz: 2cb7956404bd763af695eae8c10b81de5db48450
2
+ SHA256:
3
+ metadata.gz: de97d6fbd5c11056be61c2fbdade541bcd9e04f95dfdc3d3994d25e97b21476b
4
+ data.tar.gz: 71fb7ba1f8c2e707a95878219ddf99e040892d6d197a1ed5c33bed671191628e
5
5
  SHA512:
6
- metadata.gz: 2c5364924b1a055ce8c67c1508b219a1fc187ee9ecfa95d683775c21888f1076518bd1617b6a2e5be0020f5ef862e6707341bf8c71fff60e12e011d4dad719b9
7
- data.tar.gz: 59c211df2561ea00a1da7858051fb87de4a02e35642faba695852baf974e9e3d30d34c9b710e3078e05a2cf1ea1caefb6411f35a0604a90a6f01c37f9c9af715
6
+ metadata.gz: 0304ccbedb35ddde62968025032e2b3d83a962ec857d739df35e3645c4b4220e1aa554729876bcc4aa26e0a9db008ff0e67e314c23ddf4bcbef4951f9d0d13c8
7
+ data.tar.gz: 650669b42ece96bb992ffccc3738f09ab97d81c02129fdcd4ca0007c921e32fbd834126aec5af62074be5f25ad422f88be3ca454d15c47d83cf60e33ba990ede
@@ -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
@@ -0,0 +1,6 @@
1
+ Metrics/LineLength:
2
+ Max: 100
3
+
4
+ Metrics/BlockLength:
5
+ Exclude:
6
+ - 'spec/**/*_spec.rb'
@@ -1 +1 @@
1
- 2.3.1
1
+ 2.5.5
@@ -1,12 +1,10 @@
1
1
  before_install:
2
2
  - gem update bundler
3
3
  rvm:
4
- - 2.1.0
5
- - 2.1.2
6
- - 2.1.5
7
- - 2.2.3
8
- - 2.3.0
9
- - 2.3.1
4
+ - 2.3.8
5
+ - 2.4.5
6
+ - 2.5.5
7
+ - 2.6.2
10
8
  - ruby-head
11
9
  matrix:
12
10
  allow_failures:
@@ -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
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in google_distance_matrix.gemspec
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
- require "bundler/gem_tasks"
1
+ # frozen_string_literal: true
2
2
 
3
- require "rspec/core/rake_task"
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 = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
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: :spec
14
+ task default: %i[rubocop spec]
@@ -1,30 +1,32 @@
1
- # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
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 = "google_distance_matrix"
8
+ spec.name = 'google_distance_matrix'
8
9
  spec.version = GoogleDistanceMatrix::VERSION
9
- spec.authors = ["Thorbjørn Hermansen"]
10
- spec.email = ["thhermansen@gmail.com"]
11
- spec.description = %q{Ruby client for The Google Distance Matrix API}
12
- spec.summary = %q{Ruby client for The Google Distance Matrix API}
13
- spec.homepage = ""
14
- spec.license = "MIT"
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 = ["lib"]
20
+ spec.require_paths = ['lib']
20
21
 
21
- spec.add_dependency "activesupport", ">= 3.2.13"
22
- spec.add_dependency "activemodel", ">= 3.2.13"
23
- spec.add_dependency "google_business_api_url_signer", "~> 0.1.3"
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 "bundler"
26
- spec.add_development_dependency "rspec", "~> 3.4.0"
27
- spec.add_development_dependency "shoulda-matchers", "~> 3.1.1"
28
- spec.add_development_dependency "webmock", "~> 2.0.2"
29
- spec.add_development_dependency "rake"
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
- require "google_distance_matrix/version"
2
-
3
- require "cgi"
4
- require "json"
5
- require "active_model"
6
- require "active_support/core_ext/hash"
7
- require "google_business_api_url_signer"
8
-
9
- require "google_distance_matrix/logger"
10
- require "google_distance_matrix/errors"
11
- require "google_distance_matrix/configuration"
12
- require "google_distance_matrix/url_builder"
13
- require "google_distance_matrix/client"
14
- require "google_distance_matrix/client_cache"
15
- require "google_distance_matrix/routes_finder"
16
- require "google_distance_matrix/matrix"
17
- require "google_distance_matrix/places"
18
- require "google_distance_matrix/place"
19
- require "google_distance_matrix/route"
20
- require "google_distance_matrix/polyline_encoder"
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
- extend self
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 "google_distance_matrix/log_subscriber"
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
- def get(url, options = {})
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 "client_request_matrix_data.google_distance_matrix", instrumentation do
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
- fail MatrixUrlTooLong.new url, UrlBuilder::MAX_URL_SIZE, response
44
+ raise MatrixUrlTooLong.new url, UrlBuilder::MAX_URL_SIZE, response
24
45
  when Net::HTTPClientError
25
- fail ClientError.new response
46
+ raise ClientError, response
26
47
  when Net::HTTPServerError
27
- fail ServerError.new response
48
+ raise ServerError, response
28
49
  else # Handle this as a request error for now. Maybe fine tune this more later.
29
- fail ServerError.new response
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 "status"
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
- def self.key(url)
6
- url
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: "driving",
22
- units: "metric",
23
- traffic_model: "best_guess",
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: ['key', 'signature'].freeze
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 *ATTRIBUTES
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
- validates :mode, inclusion: {in: ["driving", "walking", "bicycling", "transit"]}, allow_blank: true
54
- validates :avoid, inclusion: {in: ["tolls", "highways", "ferries", "indoor"]}, allow_blank: true
55
- validates :units, inclusion: {in: ["metric", "imperial"]}, allow_blank: true
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, inclusion: {in: %w[bus subway train tram rail]}, allow_blank: true
61
- validates :transit_routing_preference, inclusion: {in: %w[less_walking fewer_transfers]}, allow_blank: true
62
- validates :traffic_model, inclusion: {in: %w[best_guess pessimistic optimistic]}, allow_blank: true
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: ["http", "https"]}, allow_blank: true
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] = value.dup rescue value
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
- out << ['client', google_business_api_client_id]
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
- API_DEFAULTS[param[0]] == param[1]
115
+ API_DEFAULTS[param[0]] == param[1]
101
116
  end
102
117
  end
103
118
  end