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
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
2
4
|
# Public: Error class for lib.
|
3
5
|
class Error < StandardError
|
@@ -67,7 +69,8 @@ module GoogleDistanceMatrix
|
|
67
69
|
end
|
68
70
|
|
69
71
|
def to_s
|
70
|
-
"GoogleDistanceMatrix::ClientError -
|
72
|
+
"GoogleDistanceMatrix::ClientError - \
|
73
|
+
#{[response, status_read_from_api_response].compact.join('. ')}."
|
71
74
|
end
|
72
75
|
end
|
73
76
|
|
@@ -75,7 +78,8 @@ module GoogleDistanceMatrix
|
|
75
78
|
#
|
76
79
|
# See https://developers.google.com/maps/documentation/distancematrix/#Limits, which states:
|
77
80
|
# "Distance Matrix API URLs are restricted to 2048 characters, before URL encoding."
|
78
|
-
# "As some Distance Matrix API service URLs may involve many locations,
|
81
|
+
# "As some Distance Matrix API service URLs may involve many locations,
|
82
|
+
# be aware of this limit when constructing your URLs."
|
79
83
|
#
|
80
84
|
class MatrixUrlTooLong < ClientError
|
81
85
|
attr_reader :url, :max_url_size
|
@@ -91,5 +95,4 @@ module GoogleDistanceMatrix
|
|
91
95
|
"Matrix API URL max size is: #{max_url_size}. Built URL was: #{url.length}. URL: '#{url}'."
|
92
96
|
end
|
93
97
|
end
|
94
|
-
|
95
98
|
end
|
@@ -1,8 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
4
|
+
# LogSubscriber logs to GoogleDistanceMatrix.logger by subscribing to gem's intstrumentation.
|
5
|
+
#
|
6
|
+
# NOTE: This log subscruber uses the default_configuration as it's configuration.
|
7
|
+
# This is relevant for example for the filter_parameters_in_logged_url configuration
|
2
8
|
class LogSubscriber < ActiveSupport::LogSubscriber
|
3
9
|
attr_reader :logger, :config
|
4
10
|
|
5
|
-
def initialize(
|
11
|
+
def initialize(
|
12
|
+
logger: GoogleDistanceMatrix.logger,
|
13
|
+
config: GoogleDistanceMatrix.default_configuration
|
14
|
+
)
|
6
15
|
super()
|
7
16
|
|
8
17
|
@logger = logger
|
@@ -10,20 +19,11 @@ module GoogleDistanceMatrix
|
|
10
19
|
end
|
11
20
|
|
12
21
|
def client_request_matrix_data(event)
|
13
|
-
url =
|
14
|
-
logger.info "(#{event.duration}ms) (elements: #{event.payload[:elements]}) GET #{url}",
|
15
|
-
|
16
|
-
|
17
|
-
private
|
18
|
-
|
19
|
-
def filter_url!(url)
|
20
|
-
config.filter_parameters_in_logged_url.each do |param|
|
21
|
-
url.gsub! %r{(#{param})=.*?(&|$)}, '\1=[FILTERED]\2'
|
22
|
-
end
|
23
|
-
|
24
|
-
url
|
22
|
+
url = event.payload[:filtered_url]
|
23
|
+
logger.info "(#{event.duration}ms) (elements: #{event.payload[:elements]}) GET #{url}",
|
24
|
+
tag: :client
|
25
25
|
end
|
26
26
|
end
|
27
27
|
end
|
28
28
|
|
29
|
-
GoogleDistanceMatrix::LogSubscriber.attach_to
|
29
|
+
GoogleDistanceMatrix::LogSubscriber.attach_to 'google_distance_matrix'
|
@@ -1,7 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module GoogleDistanceMatrix
|
4
|
+
# Logger class for Google Distance Matrix
|
2
5
|
class Logger
|
3
|
-
PREFIXES = %w[google_distance_matrix]
|
4
|
-
LEVELS = %w[fatal error warn info debug]
|
6
|
+
PREFIXES = %w[google_distance_matrix].freeze
|
7
|
+
LEVELS = %w[fatal error warn info debug].freeze
|
5
8
|
|
6
9
|
attr_reader :backend
|
7
10
|
|
@@ -16,17 +19,16 @@ module GoogleDistanceMatrix
|
|
16
19
|
msg = args.first
|
17
20
|
tags = PREFIXES.dup.concat Array.wrap(options[:tag])
|
18
21
|
|
19
|
-
backend
|
22
|
+
backend&.public_send level, tag_msg(msg, tags)
|
20
23
|
end
|
21
24
|
end
|
22
25
|
|
23
|
-
|
24
26
|
private
|
25
27
|
|
26
28
|
def tag_msg(msg, tags)
|
27
29
|
msg_buffer = tags.map { |tag| "[#{tag}]" }
|
28
30
|
msg_buffer << msg
|
29
|
-
msg_buffer.join
|
31
|
+
msg_buffer.join ' '
|
30
32
|
end
|
31
33
|
end
|
32
34
|
end
|
@@ -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,28 +1,31 @@
|
|
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
|
21
23
|
extract_and_assign_attributes_from_object attributes_or_object
|
22
24
|
elsif attributes_or_object.is_a? Hash
|
25
|
+
@extracted_attributes_from = attributes_or_object.with_indifferent_access
|
23
26
|
assign_attributes attributes_or_object
|
24
27
|
else
|
25
|
-
|
28
|
+
raise ArgumentError, 'Must be either hash or object responding to lat, lng or address. '
|
26
29
|
end
|
27
30
|
|
28
31
|
validate_attributes
|
@@ -33,14 +36,16 @@ module GoogleDistanceMatrix
|
|
33
36
|
address.present? ? address : lat_lng(options[:lat_lng_scale]).join(',')
|
34
37
|
end
|
35
38
|
|
36
|
-
|
37
39
|
def eql?(other)
|
40
|
+
return false unless other.is_a? self.class
|
41
|
+
|
38
42
|
if address.present?
|
39
43
|
address == other.address
|
40
44
|
else
|
41
45
|
lat_lng == other.lat_lng
|
42
46
|
end
|
43
47
|
end
|
48
|
+
alias == eql?
|
44
49
|
|
45
50
|
def lat_lng?
|
46
51
|
lat.present? && lng.present?
|
@@ -58,7 +63,9 @@ module GoogleDistanceMatrix
|
|
58
63
|
end
|
59
64
|
|
60
65
|
def inspect
|
61
|
-
inspection =
|
66
|
+
inspection = (ATTRIBUTES | [:extracted_attributes_from])
|
67
|
+
.reject { |a| public_send(a).blank? }
|
68
|
+
.map { |a| "#{a}: #{public_send(a).inspect}" }.join ', '
|
62
69
|
|
63
70
|
"#<#{self.class} #{inspection}>"
|
64
71
|
end
|
@@ -66,19 +73,15 @@ module GoogleDistanceMatrix
|
|
66
73
|
private
|
67
74
|
|
68
75
|
def respond_to_needed_attributes?(object)
|
69
|
-
(object.respond_to?(:lat) &&
|
76
|
+
(object.respond_to?(:lat) && object.respond_to?(:lng)) || object.respond_to?(:address)
|
70
77
|
end
|
71
78
|
|
72
79
|
def extract_and_assign_attributes_from_object(object)
|
73
|
-
attrs =
|
74
|
-
if object.respond_to? attr_name
|
75
|
-
[attr_name, object.public_send(attr_name)]
|
76
|
-
end
|
80
|
+
attrs = Hash[ATTRIBUTES.map do |attr_name|
|
81
|
+
[attr_name, object.public_send(attr_name)] if object.respond_to? attr_name
|
77
82
|
end.compact]
|
78
83
|
|
79
|
-
if attrs.
|
80
|
-
attrs.delete 'address'
|
81
|
-
end
|
84
|
+
attrs.delete 'address' if attrs.key?('lat') || attrs.key?('lng')
|
82
85
|
|
83
86
|
@extracted_attributes_from = object
|
84
87
|
assign_attributes attrs
|
@@ -92,14 +95,20 @@ module GoogleDistanceMatrix
|
|
92
95
|
@lng = attributes[:lng]
|
93
96
|
end
|
94
97
|
|
98
|
+
# rubocop:disable Metrics/AbcSize
|
99
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
100
|
+
# rubocop:disable Style/GuardClause
|
95
101
|
def validate_attributes
|
96
|
-
|
97
|
-
|
102
|
+
unless address.present? || (lat.present? && lng.present?)
|
103
|
+
raise ArgumentError, 'Must provide an address, or lat and lng.'
|
98
104
|
end
|
99
105
|
|
100
106
|
if address.present? && lat.present? && lng.present?
|
101
|
-
|
107
|
+
raise ArgumentError, 'Cannot provide address, lat and lng.'
|
102
108
|
end
|
103
109
|
end
|
110
|
+
# rubocop:enable Metrics/AbcSize
|
111
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
112
|
+
# rubocop:enable Style/GuardClause
|
104
113
|
end
|
105
114
|
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
|
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,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
|
|
@@ -51,11 +58,12 @@ module GoogleDistanceMatrix
|
|
51
58
|
#
|
52
59
|
# Example of usage
|
53
60
|
# p d 17998321 # => "00000001 00010010 10100001 11110001"
|
54
|
-
def d(
|
55
|
-
(bits - 1).downto(0)
|
56
|
-
|
57
|
-
|
61
|
+
def d(val, bits = 32, chunk_size = 8)
|
62
|
+
(bits - 1).downto(0)
|
63
|
+
.map { |n| val[n] }
|
64
|
+
.each_slice(chunk_size).map(&:join).join ' '
|
58
65
|
end
|
59
66
|
end
|
60
67
|
end
|
61
68
|
end
|
69
|
+
# rubocop:enable Style/NumericPredicate
|