google_distance_matrix 0.4.0 → 0.5.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/.editorconfig +16 -0
- data/.rubocop.yml +6 -0
- data/.ruby-version +1 -1
- data/.travis.yml +1 -0
- data/CHANGELOG.md +20 -0
- data/Gemfile +2 -0
- data/Rakefile +9 -4
- data/google_distance_matrix.gemspec +20 -18
- 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 +37 -19
- 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 +6 -4
- data/lib/google_distance_matrix/matrix.rb +45 -22
- data/lib/google_distance_matrix/place.rb +32 -25
- data/lib/google_distance_matrix/places.rb +5 -4
- data/lib/google_distance_matrix/polyline_encoder/delta.rb +4 -2
- data/lib/google_distance_matrix/polyline_encoder/value_encoder.rb +11 -4
- data/lib/google_distance_matrix/polyline_encoder.rb +2 -2
- 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 +25 -29
- data/lib/google_distance_matrix/url_builder/polyline_encoder_buffer.rb +3 -0
- data/lib/google_distance_matrix/url_builder.rb +44 -16
- data/lib/google_distance_matrix/version.rb +3 -1
- data/lib/google_distance_matrix.rb +25 -23
- data/spec/lib/google_distance_matrix/client_cache_spec.rb +26 -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 +30 -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 +95 -81
- data/spec/lib/google_distance_matrix/url_builder_spec.rb +97 -48
- data/spec/spec_helper.rb +3 -1
- metadata +35 -7
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
2
4
|
# Public: Represents a distance matrix.
|
3
5
|
#
|
@@ -25,23 +27,25 @@ module GoogleDistanceMatrix
|
|
25
27
|
# config.mode = "walking"
|
26
28
|
# end
|
27
29
|
#
|
28
|
-
# You can set default configuration by doing:
|
30
|
+
# You can set default configuration by doing:
|
31
|
+
# GoogleDistanceMatrix.configure_defaults { |c| c.sensor = true }
|
29
32
|
#
|
30
33
|
#
|
31
34
|
# Query API and get the matrix back
|
32
35
|
#
|
33
36
|
# matrix.data # Returns a two dimensional array.
|
34
37
|
# # Rows are ordered according to the values in the origins.
|
35
|
-
# # Each row corresponds to an origin, and each element
|
38
|
+
# # Each row corresponds to an origin, and each element
|
39
|
+
# # within that row corresponds to
|
36
40
|
# # a pairing of the origin with a destination.
|
37
41
|
#
|
38
42
|
#
|
39
43
|
class Matrix
|
40
44
|
include ActiveModel::Validations
|
41
45
|
|
42
|
-
validates :origins, length: {minimum: 1, too_short:
|
43
|
-
validates :destinations, length: {minimum: 1, too_short:
|
44
|
-
validate { errors.add(:configuration,
|
46
|
+
validates :origins, length: { minimum: 1, too_short: 'must have at least one origin' }
|
47
|
+
validates :destinations, length: { minimum: 1, too_short: 'must have at least one destination' }
|
48
|
+
validate { errors.add(:configuration, 'is invalid') if configuration.invalid? }
|
45
49
|
|
46
50
|
attr_reader :origins, :destinations, :configuration
|
47
51
|
|
@@ -53,6 +57,7 @@ module GoogleDistanceMatrix
|
|
53
57
|
@configuration = attributes[:configuration] || GoogleDistanceMatrix.default_configuration.dup
|
54
58
|
end
|
55
59
|
|
60
|
+
delegate :sensitive_url, :filtered_url, to: :url_builder
|
56
61
|
|
57
62
|
delegate :route_for, :routes_for, to: :routes_finder
|
58
63
|
delegate :route_for!, :routes_for!, to: :routes_finder
|
@@ -61,7 +66,6 @@ module GoogleDistanceMatrix
|
|
61
66
|
delegate :shortest_route_by_duration_in_traffic_to, to: :routes_finder
|
62
67
|
delegate :shortest_route_by_duration_in_traffic_to!, to: :routes_finder
|
63
68
|
|
64
|
-
|
65
69
|
# Public: The data for this matrix.
|
66
70
|
#
|
67
71
|
# Returns a two dimensional array, the matrix's data
|
@@ -83,40 +87,59 @@ module GoogleDistanceMatrix
|
|
83
87
|
@data.present?
|
84
88
|
end
|
85
89
|
|
86
|
-
|
87
|
-
|
88
90
|
def configure
|
89
91
|
yield configuration
|
90
92
|
end
|
91
93
|
|
92
|
-
def url
|
93
|
-
UrlBuilder.new(self).url
|
94
|
-
end
|
95
|
-
|
96
|
-
|
97
94
|
def inspect
|
98
95
|
attributes = %w[origins destinations]
|
99
|
-
attributes <<
|
96
|
+
attributes << 'data' if loaded?
|
100
97
|
inspection = attributes.map { |a| "#{a}: #{public_send(a).inspect}" }.join ', '
|
101
98
|
|
102
99
|
"#<#{self.class} #{inspection}>"
|
103
100
|
end
|
104
101
|
|
105
|
-
|
106
102
|
private
|
107
103
|
|
104
|
+
def url_builder
|
105
|
+
# We do not keep url builder as an instance variable as origins and destinations
|
106
|
+
# may be added after URL is being built for the first time. We should either
|
107
|
+
# make our matrix immutable or reset if origins/destinations are added after data (and
|
108
|
+
# the url) first being built and data fetched.
|
109
|
+
UrlBuilder.new self
|
110
|
+
end
|
111
|
+
|
108
112
|
def routes_finder
|
109
113
|
@routes_finder ||= RoutesFinder.new self
|
110
114
|
end
|
111
115
|
|
112
116
|
def load_matrix
|
113
|
-
|
117
|
+
body = client.get(
|
118
|
+
sensitive_url,
|
119
|
+
instrumentation: instrumentation_for_api_request,
|
120
|
+
configuration: configuration
|
121
|
+
).body
|
122
|
+
|
123
|
+
parsed = JSON.parse(body)
|
124
|
+
create_route_objects_for_parsed_data parsed
|
125
|
+
end
|
126
|
+
|
127
|
+
def instrumentation_for_api_request
|
128
|
+
{
|
129
|
+
elements: origins.length * destinations.length,
|
130
|
+
sensitive_url: sensitive_url,
|
131
|
+
filtered_url: filtered_url
|
132
|
+
}
|
133
|
+
end
|
114
134
|
|
115
|
-
|
135
|
+
def create_route_objects_for_parsed_data(parsed)
|
136
|
+
parsed['rows'].each_with_index.map do |row, origin_index|
|
116
137
|
origin = origins[origin_index]
|
117
138
|
|
118
|
-
row[
|
119
|
-
route_attributes = element.merge(
|
139
|
+
row['elements'].each_with_index.map do |element, destination_index|
|
140
|
+
route_attributes = element.merge(
|
141
|
+
origin: origin, destination: destinations[destination_index]
|
142
|
+
)
|
120
143
|
Route.new route_attributes
|
121
144
|
end
|
122
145
|
end
|
@@ -133,9 +156,9 @@ module GoogleDistanceMatrix
|
|
133
156
|
end
|
134
157
|
|
135
158
|
def clear_from_cache!
|
136
|
-
if configuration.cache
|
137
|
-
|
138
|
-
|
159
|
+
return if configuration.cache.nil?
|
160
|
+
|
161
|
+
configuration.cache.delete ClientCache.key(sensitive_url, configuration)
|
139
162
|
end
|
140
163
|
end
|
141
164
|
end
|
@@ -1,20 +1,22 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
# Examples
|
4
|
-
#
|
5
|
-
# GoogleDistanceMatrix::Place.new address: "My address"
|
6
|
-
# GoogleDistanceMatrix::Place.new lat: 1, lng: 3
|
7
|
-
#
|
8
|
-
# You may also build places by other objects responding to lat and lng or address.
|
9
|
-
# If your object responds to all of the attributes we'll use lat and lng as data
|
10
|
-
# for the Place.
|
11
|
-
#
|
12
|
-
# GoogleDistanceMatrix::Place.new object
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
13
3
|
module GoogleDistanceMatrix
|
4
|
+
# Public: Represents a place and knows how to convert it to param.
|
5
|
+
#
|
6
|
+
# Examples
|
7
|
+
#
|
8
|
+
# GoogleDistanceMatrix::Place.new address: "My address"
|
9
|
+
# GoogleDistanceMatrix::Place.new lat: 1, lng: 3
|
10
|
+
#
|
11
|
+
# You may also build places by other objects responding to lat and lng or address.
|
12
|
+
# If your object responds to all of the attributes we'll use lat and lng as data
|
13
|
+
# for the Place.
|
14
|
+
#
|
15
|
+
# GoogleDistanceMatrix::Place.new object
|
14
16
|
class Place
|
15
|
-
ATTRIBUTES = %w[address lat lng]
|
17
|
+
ATTRIBUTES = %w[address lat lng].freeze
|
16
18
|
|
17
|
-
attr_reader
|
19
|
+
attr_reader(*ATTRIBUTES, :extracted_attributes_from)
|
18
20
|
|
19
21
|
def initialize(attributes_or_object)
|
20
22
|
if respond_to_needed_attributes? attributes_or_object
|
@@ -22,7 +24,7 @@ module GoogleDistanceMatrix
|
|
22
24
|
elsif attributes_or_object.is_a? Hash
|
23
25
|
assign_attributes attributes_or_object
|
24
26
|
else
|
25
|
-
|
27
|
+
raise ArgumentError, 'Must be either hash or object responding to lat, lng or address. '
|
26
28
|
end
|
27
29
|
|
28
30
|
validate_attributes
|
@@ -33,7 +35,6 @@ module GoogleDistanceMatrix
|
|
33
35
|
address.present? ? address : lat_lng(options[:lat_lng_scale]).join(',')
|
34
36
|
end
|
35
37
|
|
36
|
-
|
37
38
|
def eql?(other)
|
38
39
|
if address.present?
|
39
40
|
address == other.address
|
@@ -58,7 +59,9 @@ module GoogleDistanceMatrix
|
|
58
59
|
end
|
59
60
|
|
60
61
|
def inspect
|
61
|
-
inspection =
|
62
|
+
inspection = (ATTRIBUTES | [:extracted_attributes_from])
|
63
|
+
.reject { |a| public_send(a).blank? }
|
64
|
+
.map { |a| "#{a}: #{public_send(a).inspect}" }.join ', '
|
62
65
|
|
63
66
|
"#<#{self.class} #{inspection}>"
|
64
67
|
end
|
@@ -66,19 +69,17 @@ module GoogleDistanceMatrix
|
|
66
69
|
private
|
67
70
|
|
68
71
|
def respond_to_needed_attributes?(object)
|
69
|
-
(object.respond_to?(:lat) &&
|
72
|
+
(object.respond_to?(:lat) && object.respond_to?(:lng)) || object.respond_to?(:address)
|
70
73
|
end
|
71
74
|
|
72
75
|
def extract_and_assign_attributes_from_object(object)
|
73
|
-
attrs =
|
76
|
+
attrs = Hash[ATTRIBUTES.map do |attr_name|
|
74
77
|
if object.respond_to? attr_name
|
75
78
|
[attr_name, object.public_send(attr_name)]
|
76
79
|
end
|
77
80
|
end.compact]
|
78
81
|
|
79
|
-
if attrs.
|
80
|
-
attrs.delete 'address'
|
81
|
-
end
|
82
|
+
attrs.delete 'address' if attrs.key?('lat') || attrs.key?('lng')
|
82
83
|
|
83
84
|
@extracted_attributes_from = object
|
84
85
|
assign_attributes attrs
|
@@ -92,14 +93,20 @@ module GoogleDistanceMatrix
|
|
92
93
|
@lng = attributes[:lng]
|
93
94
|
end
|
94
95
|
|
96
|
+
# rubocop:disable Metrics/AbcSize
|
97
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
98
|
+
# rubocop:disable Style/GuardClause
|
95
99
|
def validate_attributes
|
96
|
-
|
97
|
-
|
100
|
+
unless address.present? || (lat.present? && lng.present?)
|
101
|
+
raise ArgumentError, 'Must provide an address, or lat and lng.'
|
98
102
|
end
|
99
103
|
|
100
104
|
if address.present? && lat.present? && lng.present?
|
101
|
-
|
105
|
+
raise ArgumentError, 'Cannot provide address, lat and lng.'
|
102
106
|
end
|
103
107
|
end
|
108
|
+
# rubocop:enable Metrics/AbcSize
|
109
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
110
|
+
# rubocop:enable Style/GuardClause
|
104
111
|
end
|
105
112
|
end
|
@@ -1,4 +1,7 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
4
|
+
# Represents a collection of places
|
2
5
|
class Places
|
3
6
|
include Enumerable
|
4
7
|
|
@@ -7,10 +10,9 @@ module GoogleDistanceMatrix
|
|
7
10
|
concat Array.wrap(places)
|
8
11
|
end
|
9
12
|
|
10
|
-
|
11
13
|
delegate :each, :[], :length, :index, :pop, :shift, :delete_at, :compact, :inspect, to: :places
|
12
14
|
|
13
|
-
[
|
15
|
+
%i[<< push unshift].each do |method|
|
14
16
|
define_method method do |*args|
|
15
17
|
args = ensure_args_are_places args
|
16
18
|
|
@@ -22,10 +24,9 @@ module GoogleDistanceMatrix
|
|
22
24
|
end
|
23
25
|
|
24
26
|
def concat(other)
|
25
|
-
push
|
27
|
+
push(*other)
|
26
28
|
end
|
27
29
|
|
28
|
-
|
29
30
|
private
|
30
31
|
|
31
32
|
attr_reader :places
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
2
4
|
class PolylineEncoder
|
3
5
|
# Calculates deltas between lat_lng values, internal helper class for PolylineEncoder.
|
@@ -20,7 +22,6 @@ module GoogleDistanceMatrix
|
|
20
22
|
calculate_deltas rounded
|
21
23
|
end
|
22
24
|
|
23
|
-
|
24
25
|
private
|
25
26
|
|
26
27
|
def round_to_precision(array_of_lat_lng_pairs)
|
@@ -42,7 +43,8 @@ module GoogleDistanceMatrix
|
|
42
43
|
deltas << lat - delta_lat
|
43
44
|
deltas << lng - delta_lng
|
44
45
|
|
45
|
-
delta_lat
|
46
|
+
delta_lat = lat
|
47
|
+
delta_lng = lng
|
46
48
|
end
|
47
49
|
|
48
50
|
deltas
|
@@ -1,3 +1,6 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Style/NumericPredicate
|
1
4
|
module GoogleDistanceMatrix
|
2
5
|
class PolylineEncoder
|
3
6
|
# Encodes a single value, like 17998321, in to encoded polyline value,
|
@@ -9,6 +12,8 @@ module GoogleDistanceMatrix
|
|
9
12
|
#
|
10
13
|
# @see GoogleDistanceMatrix::PolylineEncoder
|
11
14
|
class ValueEncoder
|
15
|
+
# rubocop:disable Metrics/MethodLength
|
16
|
+
# rubocop:disable Metrics/AbcSize
|
12
17
|
def encode(value)
|
13
18
|
negative = value < 0
|
14
19
|
value = value.abs
|
@@ -27,7 +32,7 @@ module GoogleDistanceMatrix
|
|
27
32
|
# Right shift bits to get rid of the ones we just put on the array.
|
28
33
|
# Bits will end up in reverse order.
|
29
34
|
chunks_of_5_bits = []
|
30
|
-
while value > 0
|
35
|
+
while value > 0
|
31
36
|
chunks_of_5_bits.push(value & 0x1f)
|
32
37
|
value >>= 5
|
33
38
|
end
|
@@ -44,6 +49,8 @@ module GoogleDistanceMatrix
|
|
44
49
|
# step 11: Convert to ASCII
|
45
50
|
chunks_of_5_bits.map(&:chr)
|
46
51
|
end
|
52
|
+
# rubocop:enable Metrics/MethodLength
|
53
|
+
# rubocop:enable Metrics/AbcSize
|
47
54
|
|
48
55
|
private
|
49
56
|
|
@@ -52,9 +59,9 @@ module GoogleDistanceMatrix
|
|
52
59
|
# Example of usage
|
53
60
|
# p d 17998321 # => "00000001 00010010 10100001 11110001"
|
54
61
|
def d(v, bits = 32, chunk_size = 8)
|
55
|
-
(bits - 1).downto(0)
|
56
|
-
|
57
|
-
|
62
|
+
(bits - 1).downto(0)
|
63
|
+
.map { |n| v[n] }
|
64
|
+
.each_slice(chunk_size).map(&:join).join ' '
|
58
65
|
end
|
59
66
|
end
|
60
67
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require_relative 'polyline_encoder/delta'
|
2
4
|
require_relative 'polyline_encoder/value_encoder'
|
3
5
|
|
@@ -7,7 +9,6 @@ module GoogleDistanceMatrix
|
|
7
9
|
#
|
8
10
|
# See https://developers.google.com/maps/documentation/utilities/polylinealgorithm
|
9
11
|
class PolylineEncoder
|
10
|
-
|
11
12
|
# Encodes a set of lat/lng pairs
|
12
13
|
#
|
13
14
|
# Example
|
@@ -16,7 +17,6 @@ module GoogleDistanceMatrix
|
|
16
17
|
new(array_of_lat_lng_pairs).encode
|
17
18
|
end
|
18
19
|
|
19
|
-
|
20
20
|
# Initialize a new encoder
|
21
21
|
#
|
22
22
|
# Arguments
|
@@ -1,6 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
4
|
+
# Class integrating with rails
|
2
5
|
class Railtie < Rails::Railtie
|
3
|
-
initializer
|
6
|
+
initializer 'google_distance_matrix.logger_setup' do
|
4
7
|
GoogleDistanceMatrix.configure_defaults do |config|
|
5
8
|
config.logger = Rails.logger
|
6
9
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
2
4
|
# Public: Thin wrapper class for an element in the matrix.
|
3
5
|
#
|
@@ -15,10 +17,9 @@ module GoogleDistanceMatrix
|
|
15
17
|
duration_in_traffic_text duration_in_traffic_in_seconds
|
16
18
|
].freeze
|
17
19
|
|
18
|
-
attr_reader
|
19
|
-
|
20
|
-
delegate *(STATUSES.map { |s| s + '?' }), to: :status, allow_nil: true
|
20
|
+
attr_reader(*ATTRIBUTES)
|
21
21
|
|
22
|
+
delegate(*(STATUSES.map { |s| s + '?' }), to: :status, allow_nil: true)
|
22
23
|
|
23
24
|
def initialize(attributes = {})
|
24
25
|
attributes = attributes.with_indifferent_access
|
@@ -28,25 +29,31 @@ module GoogleDistanceMatrix
|
|
28
29
|
|
29
30
|
@status = ActiveSupport::StringInquirer.new attributes[:status].downcase
|
30
31
|
|
31
|
-
if ok?
|
32
|
-
|
33
|
-
@distance_in_meters = attributes[:distance][:value]
|
34
|
-
@duration_text = attributes[:duration][:text]
|
35
|
-
@duration_in_seconds = attributes[:duration][:value]
|
32
|
+
assign attributes if ok?
|
33
|
+
end
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
35
|
+
def inspect
|
36
|
+
attrs = ATTRIBUTES.reject do |a|
|
37
|
+
public_send(a).blank?
|
41
38
|
end
|
39
|
+
|
40
|
+
inspection = attrs.map { |a| "#{a}: #{public_send(a).inspect}" }.join ', '
|
41
|
+
|
42
|
+
"#<#{self.class} #{inspection}>"
|
42
43
|
end
|
43
44
|
|
45
|
+
private
|
44
46
|
|
47
|
+
def assign(attributes)
|
48
|
+
@distance_text = attributes[:distance][:text]
|
49
|
+
@distance_in_meters = attributes[:distance][:value]
|
50
|
+
@duration_text = attributes[:duration][:text]
|
51
|
+
@duration_in_seconds = attributes[:duration][:value]
|
45
52
|
|
46
|
-
|
47
|
-
inspection = ATTRIBUTES.reject { |a| public_send(a).blank? }.map { |a| "#{a}: #{public_send(a).inspect}" }.join ', '
|
53
|
+
return unless attributes.key? :duration_in_traffic
|
48
54
|
|
49
|
-
|
55
|
+
@duration_in_traffic_text = attributes[:duration_in_traffic][:text]
|
56
|
+
@duration_in_traffic_in_seconds = attributes[:duration_in_traffic][:value]
|
50
57
|
end
|
51
58
|
end
|
52
59
|
end
|
@@ -1,18 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
2
4
|
# Public: Has logic for doing finder operations on a matrix.
|
5
|
+
#
|
6
|
+
# rubocop:disable Metrics/ClassLength
|
3
7
|
class RoutesFinder
|
4
|
-
|
5
8
|
attr_reader :matrix
|
6
9
|
delegate :data, :origins, :destinations, :configuration, to: :matrix
|
7
10
|
|
8
|
-
|
9
11
|
def initialize(matrix)
|
10
12
|
@matrix = matrix
|
11
|
-
end
|
13
|
+
end # Public: Finds routes for given place.
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
# Public: Finds routes for given place.
|
16
15
|
#
|
17
16
|
# place - Either an origin or destination, or an object which you built the place from
|
18
17
|
#
|
@@ -25,7 +24,7 @@ module GoogleDistanceMatrix
|
|
25
24
|
elsif destinations.include? place
|
26
25
|
routes_for_destination place
|
27
26
|
else
|
28
|
-
|
27
|
+
raise ArgumentError, 'Given place not an origin nor destination.'
|
29
28
|
end
|
30
29
|
end
|
31
30
|
|
@@ -41,11 +40,11 @@ module GoogleDistanceMatrix
|
|
41
40
|
end
|
42
41
|
end
|
43
42
|
|
44
|
-
|
45
43
|
# Public: Finds a route for you based on one origin and destination
|
46
44
|
#
|
47
45
|
# origin - A place representing the origin, or an object which you built the origin from
|
48
|
-
# destination - A place representing the destination, or an object which you built the
|
46
|
+
# destination - A place representing the destination, or an object which you built the
|
47
|
+
# destination from
|
49
48
|
#
|
50
49
|
# A Route for given origin and destination
|
51
50
|
def route_for(options = {})
|
@@ -55,7 +54,7 @@ module GoogleDistanceMatrix
|
|
55
54
|
destination = ensure_place options[:destination]
|
56
55
|
|
57
56
|
if origin.nil? || destination.nil?
|
58
|
-
|
57
|
+
raise ArgumentError, 'Must provide origin and destination'
|
59
58
|
end
|
60
59
|
|
61
60
|
routes_for(origin).detect { |route| route.destination == destination }
|
@@ -71,7 +70,6 @@ module GoogleDistanceMatrix
|
|
71
70
|
end
|
72
71
|
end
|
73
72
|
|
74
|
-
|
75
73
|
# Public: Finds shortes route by distance to a place.
|
76
74
|
#
|
77
75
|
# place - The place, or object place was built from, you want the shortest route to
|
@@ -79,7 +77,7 @@ module GoogleDistanceMatrix
|
|
79
77
|
# Returns shortest route, or nil if no routes had status ok
|
80
78
|
def shortest_route_by_distance_to(place_or_object_place_was_built_from)
|
81
79
|
routes = routes_for place_or_object_place_was_built_from
|
82
|
-
select_ok_routes(routes).min_by
|
80
|
+
select_ok_routes(routes).min_by(&:distance_in_meters)
|
83
81
|
end
|
84
82
|
|
85
83
|
# Public: Finds shortes route by distance to a place.
|
@@ -88,7 +86,7 @@ module GoogleDistanceMatrix
|
|
88
86
|
#
|
89
87
|
# Returns shortest route, fails if any of the routes are not ok
|
90
88
|
def shortest_route_by_distance_to!(place_or_object_place_was_built_from)
|
91
|
-
routes_for!(place_or_object_place_was_built_from).min_by
|
89
|
+
routes_for!(place_or_object_place_was_built_from).min_by(&:distance_in_meters)
|
92
90
|
end
|
93
91
|
|
94
92
|
# Public: Finds shortes route by duration to a place.
|
@@ -98,7 +96,7 @@ module GoogleDistanceMatrix
|
|
98
96
|
# Returns shortest route, or nil if no routes had status ok
|
99
97
|
def shortest_route_by_duration_to(place_or_object_place_was_built_from)
|
100
98
|
routes = routes_for place_or_object_place_was_built_from
|
101
|
-
select_ok_routes(routes).min_by
|
99
|
+
select_ok_routes(routes).min_by(&:duration_in_seconds)
|
102
100
|
end
|
103
101
|
|
104
102
|
# Public: Finds shortes route by duration to a place.
|
@@ -107,7 +105,7 @@ module GoogleDistanceMatrix
|
|
107
105
|
#
|
108
106
|
# Returns shortest route, fails if any of the routes are not ok
|
109
107
|
def shortest_route_by_duration_to!(place_or_object_place_was_built_from)
|
110
|
-
routes_for!(place_or_object_place_was_built_from).min_by
|
108
|
+
routes_for!(place_or_object_place_was_built_from).min_by(&:duration_in_seconds)
|
111
109
|
end
|
112
110
|
|
113
111
|
# Public: Finds shortes route by duration in traffic to a place.
|
@@ -122,7 +120,7 @@ module GoogleDistanceMatrix
|
|
122
120
|
ensure_driving_and_departure_time_or_fail!
|
123
121
|
|
124
122
|
routes = routes_for place_or_object_place_was_built_from
|
125
|
-
select_ok_routes(routes).min_by
|
123
|
+
select_ok_routes(routes).min_by(&:duration_in_traffic_in_seconds)
|
126
124
|
end
|
127
125
|
|
128
126
|
# Public: Finds shortes route by duration in traffic to a place.
|
@@ -136,11 +134,9 @@ module GoogleDistanceMatrix
|
|
136
134
|
def shortest_route_by_duration_in_traffic_to!(place_or_object_place_was_built_from)
|
137
135
|
ensure_driving_and_departure_time_or_fail!
|
138
136
|
|
139
|
-
routes_for!(place_or_object_place_was_built_from).min_by
|
137
|
+
routes_for!(place_or_object_place_was_built_from).min_by(&:duration_in_traffic_in_seconds)
|
140
138
|
end
|
141
139
|
|
142
|
-
|
143
|
-
|
144
140
|
private
|
145
141
|
|
146
142
|
def ensure_place(object)
|
@@ -148,27 +144,27 @@ module GoogleDistanceMatrix
|
|
148
144
|
object
|
149
145
|
else
|
150
146
|
find_place_for_object(origins, object) ||
|
151
|
-
|
147
|
+
find_place_for_object(destinations, object)
|
152
148
|
end
|
153
149
|
end
|
154
150
|
|
155
151
|
def find_place_for_object(collection, object)
|
156
152
|
collection.detect do |place|
|
157
153
|
place.extracted_attributes_from.present? &&
|
158
|
-
|
154
|
+
place.extracted_attributes_from == object
|
159
155
|
end
|
160
156
|
end
|
161
157
|
|
162
158
|
def routes_for_origin(origin)
|
163
159
|
index = origins.index origin
|
164
|
-
|
160
|
+
raise ArgumentError, 'Given origin is not i matrix.' if index.nil?
|
165
161
|
|
166
162
|
data[index]
|
167
163
|
end
|
168
164
|
|
169
165
|
def routes_for_destination(destination)
|
170
166
|
index = destinations.index destination
|
171
|
-
|
167
|
+
raise ArgumentError, 'Given destination is not i matrix.' if index.nil?
|
172
168
|
|
173
169
|
[].tap do |routes|
|
174
170
|
data.each { |row| routes << row[index] }
|
@@ -180,24 +176,24 @@ module GoogleDistanceMatrix
|
|
180
176
|
destination_index = destinations.index destination
|
181
177
|
|
182
178
|
if origin_index.nil? || destination_index.nil?
|
183
|
-
|
179
|
+
raise ArgumentError, 'Given origin or destination is not i matrix.'
|
184
180
|
end
|
185
181
|
|
186
182
|
[data[origin_index][destination_index]]
|
187
183
|
end
|
188
184
|
|
189
185
|
def fail_unless_route_is_ok(route)
|
190
|
-
|
186
|
+
raise InvalidRoute, route unless route.ok?
|
191
187
|
end
|
192
188
|
|
193
189
|
def select_ok_routes(routes)
|
194
|
-
routes.select
|
190
|
+
routes.select(&:ok?)
|
195
191
|
end
|
196
192
|
|
197
193
|
def ensure_driving_and_departure_time_or_fail!
|
198
|
-
if configuration.mode
|
199
|
-
|
200
|
-
|
194
|
+
return if configuration.mode == 'driving' && configuration.departure_time.present?
|
195
|
+
|
196
|
+
raise InvalidQuery, 'Matrix must be in mode driving and a departure_time must be set'
|
201
197
|
end
|
202
198
|
end
|
203
199
|
end
|