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.
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