google_map_services 0.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,85 @@
1
+ require 'google_maps_service/convert'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps Geocoding API.
6
+ module Geocoding
7
+
8
+ # Geocoding is the process of converting addresses
9
+ # (like `"1600 Amphitheatre Parkway, Mountain View, CA"`) into geographic
10
+ # coordinates (like latitude 37.423021 and longitude -122.083739), which you
11
+ # can use to place markers or position the map.
12
+ #
13
+ # @example Geocode an address
14
+ # results = client.geocode('Sydney')
15
+ #
16
+ # @example Geocode a component only
17
+ # results = client.geocode(nil, components: {administrative_area: 'TX', country: 'US'})
18
+ #
19
+ # @example Geocode an address and component
20
+ # results = client.geocode('Sydney', components: {administrative_area: 'TX', country: 'US'})
21
+ #
22
+ # @example Multiple parameters
23
+ # results = client.geocode('Sydney',
24
+ # components: {administrative_area: 'TX', country: 'US'},
25
+ # bounds: {
26
+ # northeast: {lat: 32.7183997, lng: -97.26864001970849},
27
+ # southwest: {lat: 32.7052583, lng: -97.27133798029149}
28
+ # },
29
+ # region: 'us')
30
+ #
31
+ # @param [String] address The address to geocode. You must specify either this value and/or `components`.
32
+ # @param [Hash] components A component filter for which you wish to obtain a geocode,
33
+ # for example: `{'administrative_area': 'TX','country': 'US'}`
34
+ # @param [String, Hash] bounds The bounding box of the viewport within which to bias geocode
35
+ # results more prominently. Accept string or hash with `northeast` and `southwest` keys.
36
+ # @param [String] region The region code, specified as a ccTLD (_top-level domain_)
37
+ # two-character value.
38
+ # @param [String] language The language in which to return results.
39
+ #
40
+ # @return [Array] Array of geocoding results.
41
+ def geocode(address, components: nil, bounds: nil, region: nil, language: nil)
42
+ params = {}
43
+
44
+ params[:address] = address if address
45
+ params[:components] = GoogleMapsService::Convert.components(components) if components
46
+ params[:bounds] = GoogleMapsService::Convert.bounds(bounds) if bounds
47
+ params[:region] = region if region
48
+ params[:language] = language if language
49
+
50
+ return get('/maps/api/geocode/json', params)[:results]
51
+ end
52
+
53
+ # Reverse geocoding is the process of converting geographic coordinates into a
54
+ # human-readable address.
55
+ #
56
+ # @example Simple lat/lon pair
57
+ # client.reverse_geocode({lat: 40.714224, lng: -73.961452})
58
+ #
59
+ # @example Multiple parameters
60
+ # client.reverse_geocode([40.714224, -73.961452],
61
+ # location_type: ['ROOFTOP', 'RANGE_INTERPOLATED'],
62
+ # result_type: ['street_address', 'route'],
63
+ # language: 'es')
64
+ #
65
+ # @param [Hash, Array] latlng The latitude/longitude value for which you wish to obtain
66
+ # the closest, human-readable address.
67
+ # @param [String, Array<String>] location_type One or more location types to restrict results to.
68
+ # @param [String, Array<String>] result_type One or more address types to restrict results to.
69
+ # @param [String] language The language in which to return results.
70
+ #
71
+ # @return [Array] Array of reverse geocoding results.
72
+ def reverse_geocode(latlng, location_type: nil, result_type: nil, language: nil)
73
+ params = {
74
+ latlng: GoogleMapsService::Convert.latlng(latlng)
75
+ }
76
+
77
+ params[:result_type] = GoogleMapsService::Convert.join_list('|', result_type) if result_type
78
+ params[:location_type] = GoogleMapsService::Convert.join_list('|', location_type) if location_type
79
+ params[:language] = language if language
80
+
81
+ return get('/maps/api/geocode/json', params)[:results]
82
+ end
83
+
84
+ end
85
+ end
@@ -0,0 +1,20 @@
1
+ require 'google_maps_service/convert'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps Geocoding API.
6
+ module Places
7
+ def places_autocomplete(input, components: nil, bounds: nil, types: nil, region: nil, language: nil)
8
+ params = {}
9
+
10
+ params[:input] = input
11
+ params[:components] = GoogleMapsService::Convert.components(components) if components
12
+ params[:bounds] = GoogleMapsService::Convert.bounds(bounds) if bounds
13
+ params[:region] = region if region
14
+ params[:language] = language if language
15
+ params[:types] = types if types
16
+
17
+ return get('/maps/api/place/autocomplete/json', params)[:predictions]
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,187 @@
1
+ require 'multi_json'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps Roads API.
6
+ module Roads
7
+
8
+ # Base URL of Google Maps Roads API
9
+ ROADS_BASE_URL = "https://roads.googleapis.com"
10
+
11
+ # Snaps a path to the most likely roads travelled.
12
+ #
13
+ # Takes up to 100 GPS points collected along a route, and returns a similar
14
+ # set of data with the points snapped to the most likely roads the vehicle
15
+ # was traveling along.
16
+ #
17
+ # @example Single point snap
18
+ # results = client.snap_to_roads([40.714728, -73.998672])
19
+ #
20
+ # @example Multi points snap
21
+ # path = [
22
+ # [-33.8671, 151.20714],
23
+ # [-33.86708, 151.20683000000002],
24
+ # [-33.867070000000005, 151.20674000000002],
25
+ # [-33.86703, 151.20625]
26
+ # ]
27
+ # results = client.snap_to_roads(path, interpolate: true)
28
+ #
29
+ # @param [Array] path The path to be snapped. Array of latitude/longitude pairs.
30
+ # @param [Boolean] interpolate Whether to interpolate a path to include all points
31
+ # forming the full road-geometry. When true, additional interpolated
32
+ # points will also be returned, resulting in a path that smoothly
33
+ # follows the geometry of the road, even around corners and through
34
+ # tunnels. Interpolated paths may contain more points than the
35
+ # original path.
36
+ #
37
+ # @return [Array] Array of snapped points.
38
+ def snap_to_roads(path, interpolate: false)
39
+ path = GoogleMapsService::Convert.waypoints(path)
40
+
41
+ params = {
42
+ path: path
43
+ }
44
+
45
+ params[:interpolate] = 'true' if interpolate
46
+
47
+ return get('/v1/snapToRoads', params,
48
+ base_url: ROADS_BASE_URL,
49
+ accepts_client_id: false,
50
+ custom_response_decoder: method(:extract_roads_body))[:snappedPoints]
51
+ end
52
+
53
+ # Returns the posted speed limit (in km/h) for given road segments.
54
+ #
55
+ # @example Multi places snap
56
+ # place_ids = [
57
+ # 'ChIJ0wawjUCuEmsRgfqC5Wd9ARM',
58
+ # 'ChIJ6cs2kkCuEmsRUfqC5Wd9ARM'
59
+ # ]
60
+ # results = client.speed_limits(place_ids)
61
+ #
62
+ # @param [String, Array<String>] place_ids The Place ID of the road segment. Place IDs are returned
63
+ # by the snap_to_roads function. You can pass up to 100 Place IDs.
64
+ #
65
+ # @return [Array] Array of speed limits.
66
+ def speed_limits(place_ids)
67
+ params = GoogleMapsService::Convert.as_list(place_ids).map { |place_id| ['placeId', place_id] }
68
+
69
+ return get('/v1/speedLimits', params,
70
+ base_url: ROADS_BASE_URL,
71
+ accepts_client_id: false,
72
+ custom_response_decoder: method(:extract_roads_body))[:speedLimits]
73
+ end
74
+
75
+ # Returns the posted speed limit (in km/h) for given road segments.
76
+ #
77
+ # The provided points will first be snapped to the most likely roads the
78
+ # vehicle was traveling along.
79
+ #
80
+ # @example Multi points snap
81
+ # path = [
82
+ # [-33.8671, 151.20714],
83
+ # [-33.86708, 151.20683000000002],
84
+ # [-33.867070000000005, 151.20674000000002],
85
+ # [-33.86703, 151.20625]
86
+ # ]
87
+ # results = client.snapped_speed_limits(path)
88
+ #
89
+ # @param [Hash, Array] path The path of points to be snapped. A list of (or single)
90
+ # latitude/longitude tuples.
91
+ #
92
+ # @return [Hash] A hash with both a list of speed limits and a list of the snapped
93
+ # points.
94
+ def snapped_speed_limits(path)
95
+ path = GoogleMapsService::Convert.waypoints(path)
96
+
97
+ params = {
98
+ path: path
99
+ }
100
+
101
+ return get('/v1/speedLimits', params,
102
+ base_url: ROADS_BASE_URL,
103
+ accepts_client_id: false,
104
+ custom_response_decoder: method(:extract_roads_body))
105
+ end
106
+
107
+ # Returns the nearest road segments for provided points.
108
+ # The points passed do not need to be part of a continuous path.
109
+ #
110
+ # @example Single point snap
111
+ # results = client.nearest_roads([40.714728, -73.998672])
112
+ #
113
+ # @example Multi points snap
114
+ # points = [
115
+ # [-33.8671, 151.20714],
116
+ # [-33.86708, 151.20683000000002],
117
+ # [-33.867070000000005, 151.20674000000002],
118
+ # [-33.86703, 151.20625]
119
+ # ]
120
+ # results = client.nearest_roads(points)
121
+ #
122
+ # @param [Array] points The points to be used for nearest road segment lookup. Array of latitude/longitude pairs
123
+ # which do not need to be a part of continuous part.
124
+ # Takes up to 100 independent coordinates, and returns the closest road segment for each point.
125
+ #
126
+ # @return [Array] Array of snapped points.
127
+
128
+ def nearest_roads(points)
129
+ points = GoogleMapsService::Convert.waypoints(points)
130
+
131
+ params = {
132
+ points: points
133
+ }
134
+
135
+ return get('/v1/nearestRoads', params,
136
+ base_url: ROADS_BASE_URL,
137
+ accepts_client_id: false,
138
+ custom_response_decoder: method(:extract_roads_body))[:snappedPoints]
139
+ end
140
+
141
+
142
+
143
+ private
144
+ # Extracts a result from a Roads API HTTP response.
145
+ def extract_roads_body(response)
146
+ begin
147
+ body = MultiJson.load(response.body, :symbolize_keys => true)
148
+ rescue
149
+ unless response.status == 200
150
+ check_response_status(response)
151
+ end
152
+ raise GoogleMapsService::Error::ApiError.new(response), 'Received a malformed response.'
153
+ end
154
+
155
+ check_roads_body_error(response, body)
156
+
157
+ unless response.status == 200
158
+ raise GoogleMapsService::Error::ApiError.new(response)
159
+ end
160
+ return body
161
+ end
162
+
163
+ # Check response body for error status.
164
+ #
165
+ # @param [Faraday::Response] response Response object.
166
+ # @param [Hash] body Response body.
167
+ def check_roads_body_error(response, body)
168
+ error = body[:error]
169
+ return unless error
170
+
171
+ case error[:status]
172
+ when 'INVALID_ARGUMENT'
173
+ if error[:message] == 'The provided API key is invalid.'
174
+ raise GoogleMapsService::Error::RequestDeniedError.new(response), error[:message]
175
+ end
176
+ raise GoogleMapsService::Error::InvalidRequestError.new(response), error[:message]
177
+ when 'PERMISSION_DENIED'
178
+ raise GoogleMapsService::Error::RequestDeniedError.new(response), error[:message]
179
+ when 'RESOURCE_EXHAUSTED'
180
+ raise GoogleMapsService::Error::RateLimitError.new(response), error[:message]
181
+ else
182
+ raise GoogleMapsService::Error::ApiError.new(response), error[:message]
183
+ end
184
+ end
185
+
186
+ end
187
+ end
@@ -0,0 +1,41 @@
1
+ require 'date'
2
+
3
+ module GoogleMapsService::Apis
4
+
5
+ # Performs requests to the Google Maps TimeZone API."""
6
+ module TimeZone
7
+
8
+ # Get time zone for a location on the earth, as well as that location's
9
+ # time offset from UTC.
10
+ #
11
+ # @example Current time zone
12
+ # timezone = client.timezone([39.603481, -119.682251])
13
+ #
14
+ # @example Time zone at certain time
15
+ # timezone = client.timezone([39.603481, -119.682251], timestamp: Time.at(1608))
16
+ #
17
+ # @param [Hash, Array] location The latitude/longitude value representing the location to
18
+ # look up.
19
+ # @param [Integer, DateTime] timestamp Timestamp specifies the desired time as seconds since
20
+ # midnight, January 1, 1970 UTC. The Time Zone API uses the timestamp to
21
+ # determine whether or not Daylight Savings should be applied. Times
22
+ # before 1970 can be expressed as negative values. Optional. Defaults to
23
+ # `Time.now`.
24
+ # @param [String] language The language in which to return results.
25
+ #
26
+ # @return [Hash] Time zone object.
27
+ def timezone(location, timestamp: Time.now, language: nil)
28
+ location = GoogleMapsService::Convert.latlng(location)
29
+ timestamp = GoogleMapsService::Convert.time(timestamp)
30
+
31
+ params = {
32
+ location: location,
33
+ timestamp: timestamp
34
+ }
35
+
36
+ params[:language] = language if language
37
+
38
+ return get('/maps/api/timezone/json', params)
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,6 @@
1
+ module GoogleMapsService
2
+
3
+ # Collections of Google Maps Web Services
4
+ module Apis
5
+ end
6
+ end
@@ -0,0 +1,292 @@
1
+ require 'faraday'
2
+ #require 'faraday/retry'
3
+ require 'multi_json'
4
+ require 'thread'
5
+
6
+ require 'google_maps_service/errors'
7
+ require 'google_maps_service/convert'
8
+ require 'google_maps_service/url'
9
+ require 'google_maps_service/apis/directions'
10
+ require 'google_maps_service/apis/distance_matrix'
11
+ require 'google_maps_service/apis/elevation'
12
+ require 'google_maps_service/apis/geocoding'
13
+ require 'google_maps_service/apis/roads'
14
+ require 'google_maps_service/apis/time_zone'
15
+ require 'google_maps_service/apis/places'
16
+
17
+ module GoogleMapsService
18
+
19
+ # Core client functionality, common across all API requests (including performing
20
+ # HTTP requests).
21
+ class Client
22
+ # Default Google Maps Web Service base endpoints
23
+ DEFAULT_BASE_URL = 'https://maps.googleapis.com'
24
+
25
+ # Errors those could be retriable.
26
+ RETRIABLE_ERRORS = [GoogleMapsService::Error::ServerError, GoogleMapsService::Error::RateLimitError]
27
+
28
+ include GoogleMapsService::Apis::Directions
29
+ include GoogleMapsService::Apis::DistanceMatrix
30
+ include GoogleMapsService::Apis::Elevation
31
+ include GoogleMapsService::Apis::Geocoding
32
+ include GoogleMapsService::Apis::Roads
33
+ include GoogleMapsService::Apis::TimeZone
34
+ include GoogleMapsService::Apis::Places
35
+
36
+ # Secret key for accessing Google Maps Web Service.
37
+ # Can be obtained at https://developers.google.com/maps/documentation/geocoding/get-api-key#key.
38
+ # @return [String]
39
+ attr_accessor :key
40
+
41
+ # Client id for using Maps API for Work services.
42
+ # @return [String]
43
+ attr_accessor :client_id
44
+
45
+ # Client secret for using Maps API for Work services.
46
+ # @return [String]
47
+ attr_accessor :client_secret
48
+
49
+ # Timeout across multiple retriable requests, in seconds.
50
+ # @return [Integer]
51
+ attr_accessor :retry_timeout
52
+
53
+ # Number of queries per second permitted.
54
+ # If the rate limit is reached, the client will sleep for
55
+ # the appropriate amount of time before it runs the current query.
56
+ # @return [Integer]
57
+ attr_reader :queries_per_second
58
+
59
+ # Construct Google Maps Web Service API client.
60
+ #
61
+ # You can configure `Hurley::Client` through `request_options` and `ssl_options` parameters.
62
+ # You can also directly get the `Hurley::Client` object via {#client} method.
63
+ #
64
+ # @example Setup API keys
65
+ # gmaps = GoogleMapsService::Client.new(key: 'Add your key here')
66
+ #
67
+ # @example Setup client IDs
68
+ # gmaps = GoogleMapsService::Client.new(
69
+ # client_id: 'Add your client id here',
70
+ # client_secret: 'Add your client secret here'
71
+ # )
72
+ #
73
+ # @example Setup time out and QPS limit
74
+ # gmaps = GoogleMapsService::Client.new(
75
+ # key: 'Add your key here',
76
+ # retry_timeout: 20,
77
+ # queries_per_second: 10
78
+ # )
79
+ #
80
+ # @example Request behind proxy
81
+ # request_options = Hurley::RequestOptions.new
82
+ # request_options.proxy = Hurley::Url.parse 'http://user:password@proxy.example.com:3128'
83
+ #
84
+ # gmaps = GoogleMapsService::Client.new(
85
+ # key: 'Add your key here',
86
+ # request_options: request_options
87
+ # )
88
+ #
89
+ # @example Using Excon and Http Cache
90
+ # require 'hurley-excon' # https://github.com/lostisland/hurley-excon
91
+ # require 'hurley/http_cache' # https://github.com/plataformatec/hurley-http-cache
92
+ #
93
+ # gmaps = GoogleMapsService::Client.new(
94
+ # key: 'Add your key here',
95
+ # connection: Hurley::HttpCache.new(HurleyExcon::Connection.new)
96
+ # )
97
+ #
98
+ # @option options [String] :key Secret key for accessing Google Maps Web Service.
99
+ # Can be obtained at https://developers.google.com/maps/documentation/geocoding/get-api-key#key.
100
+ # @option options [String] :client_id Client id for using Maps API for Work services.
101
+ # @option options [String] :client_secret Client secret for using Maps API for Work services.
102
+ # @option options [Integer] :retry_timeout Timeout across multiple retriable requests, in seconds.
103
+ # @option options [Integer] :queries_per_second Number of queries per second permitted.
104
+ #
105
+ # @option options [Hurley::RequestOptions] :request_options HTTP client request options.
106
+ # See https://github.com/lostisland/hurley/blob/master/lib/hurley/options.rb.
107
+ # @option options [Hurley::SslOptions] :ssl_options HTTP client SSL options.
108
+ # See https://github.com/lostisland/hurley/blob/master/lib/hurley/options.rb.
109
+ # @option options [Object] :connection HTTP client connection.
110
+ # By default, the default Hurley's HTTP client connection (Net::Http) will be used.
111
+ # See https://github.com/lostisland/hurley/blob/master/README.md#connections.
112
+ def initialize(**options)
113
+ [:key, :client_id, :client_secret,
114
+ :retry_timeout, :queries_per_second,
115
+ :request_options, :ssl_options, :connection].each do |key|
116
+ self.instance_variable_set("@#{key}".to_sym, options[key] || GoogleMapsService.instance_variable_get("@#{key}"))
117
+ end
118
+
119
+ initialize_query_tickets
120
+ end
121
+
122
+ # Get the current HTTP client.
123
+ # @return [Faraday::Client]
124
+ def client
125
+ @client ||= new_client
126
+ end
127
+
128
+ protected
129
+
130
+ # Initialize QPS queue. QPS queue is a "tickets" for calling API
131
+ def initialize_query_tickets
132
+ if @queries_per_second
133
+ @qps_queue = SizedQueue.new @queries_per_second
134
+ @queries_per_second.times do
135
+ @qps_queue << 0
136
+ end
137
+ end
138
+ end
139
+
140
+ # Create a new HTTP client.
141
+ # @return [Faraday::Connection]
142
+ def new_client
143
+ client = Faraday.new(DEFAULT_BASE_URL)
144
+ #client.request_options.query_class = Hurley::Query::Flat
145
+ #client.request_options.redirection_limit = 0
146
+ client.headers[:user_agent] = user_agent
147
+
148
+ #client.connection = @connection if @connection
149
+ #@request_options.each_pair {|key, value| client.request_options[key] = value } if @request_options
150
+ #@ssl_options.each_pair {|key, value| client.ssl_options[key] = value } if @ssl_options
151
+
152
+ client
153
+ end
154
+
155
+ # Build the user agent header
156
+ # @return [String]
157
+ def user_agent
158
+ sprintf('google-maps-services-ruby/%s %s',
159
+ GoogleMapsService::VERSION,
160
+ GoogleMapsService::OS_VERSION)
161
+ end
162
+
163
+ # Make API call.
164
+ #
165
+ # @param [String] path Url path.
166
+ # @param [String] params Request parameters.
167
+ # @param [String] base_url Base Google Maps Web Service API endpoint url.
168
+ # @param [Boolean] accepts_client_id Sign the request using API {#keys} instead of {#client_id}.
169
+ # @param [Method] custom_response_decoder Custom method to decode raw API response.
170
+ #
171
+ # @return [Object] Decoded response body.
172
+ def get(path, params, base_url: DEFAULT_BASE_URL, accepts_client_id: true, custom_response_decoder: nil)
173
+ url = base_url + generate_auth_url(path, params, accepts_client_id)
174
+
175
+ #Retriable.retriable timeout: @retry_timeout, on: RETRIABLE_ERRORS do |try|
176
+ #begin
177
+ #request_query_ticket
178
+ response = client.get url
179
+ #ensure
180
+ #release_query_ticket
181
+ #end
182
+
183
+ return custom_response_decoder.call(response) if custom_response_decoder
184
+ decode_response_body(response)
185
+ #end
186
+ end
187
+
188
+ # Get/wait the request "ticket" if QPS is configured.
189
+ # Check for previous request time, it must be more than a second ago before calling new request.
190
+ #
191
+ # @return [void]
192
+ def request_query_ticket
193
+ if @qps_queue
194
+ elapsed_since_earliest = Time.now - @qps_queue.pop
195
+ sleep(1 - elapsed_since_earliest) if elapsed_since_earliest.to_f < 1
196
+ end
197
+ end
198
+
199
+ # Release request "ticket".
200
+ #
201
+ # @return [void]
202
+ def release_query_ticket
203
+ @qps_queue << Time.now if @qps_queue
204
+ end
205
+
206
+ # Returns the path and query string portion of the request URL,
207
+ # first adding any necessary parameters.
208
+ #
209
+ # @param [String] path The path portion of the URL.
210
+ # @param [Hash] params URL parameters.
211
+ # @param [Boolean] accepts_client_id Sign the request using API {#keys} instead of {#client_id}.
212
+ #
213
+ # @return [String]
214
+ def generate_auth_url(path, params, accepts_client_id)
215
+ # Deterministic ordering through sorting by key.
216
+ # Useful for tests, and in the future, any caching.
217
+ if params.kind_of?(Hash)
218
+ params = params.sort
219
+ else
220
+ params = params.dup
221
+ end
222
+
223
+ if accepts_client_id and @client_id and @client_secret
224
+ params << ["client", @client_id]
225
+
226
+ path = [path, GoogleMapsService::Url.urlencode_params(params)].join("?")
227
+ sig = GoogleMapsService::Url.sign_hmac(@client_secret, path)
228
+ return path + "&signature=" + sig
229
+ end
230
+
231
+ if @key
232
+ params << ["key", @key]
233
+ return path + "?" + GoogleMapsService::Url.urlencode_params(params)
234
+ end
235
+
236
+ raise ArgumentError, "Must provide API key for this API. It does not accept enterprise credentials."
237
+ end
238
+
239
+ # Extract and parse body response as hash. Throw an error if there is something wrong with the response.
240
+ #
241
+ # @param [Faraday::Response] response Web API response.
242
+ #
243
+ # @return [Hash] Response body as hash. The hash key will be symbolized.
244
+ def decode_response_body(response)
245
+ check_response_status(response)
246
+ body = MultiJson.load(response.body, :symbolize_keys => true)
247
+ check_body_error(response, body)
248
+ body
249
+ end
250
+
251
+ # Check HTTP response status code. Raise error if the status is not 2xx.
252
+ #
253
+ # @param [Faraday::Response] response Web API response.
254
+ def check_response_status(response)
255
+ case response.status
256
+ when 200..300
257
+ # Do-nothing
258
+ when 301, 302, 303, 307
259
+ raise GoogleMapsService::Error::RedirectError.new(response), sprintf('Redirect to %s', response.headers[:location])
260
+ when 401
261
+ raise GoogleMapsService::Error::ClientError.new(response), 'Unauthorized'
262
+ when 304, 400, 402...500
263
+ raise GoogleMapsService::Error::ClientError.new(response), 'Invalid request'
264
+ when 500..600
265
+ raise GoogleMapsService::Error::ServerError.new(response), 'Server error'
266
+ end
267
+ end
268
+
269
+ # Check response body for error status.
270
+ #
271
+ # @param [Faraday::Response] response Response object.
272
+ # @param [Hash] body Response body.
273
+ #
274
+ # @return [void]
275
+ def check_body_error(response, body)
276
+ case body[:status]
277
+ when 'OK', 'ZERO_RESULTS'
278
+ # Do-nothing
279
+ when 'OVER_QUERY_LIMIT'
280
+ raise GoogleMapsService::Error::RateLimitError.new(response), body[:error_message]
281
+ when 'REQUEST_DENIED'
282
+ raise GoogleMapsService::Error::RequestDeniedError.new(response), body[:error_message]
283
+ when 'INVALID_REQUEST'
284
+ raise GoogleMapsService::Error::InvalidRequestError.new(response), body[:error_message]
285
+ when 'NOT_FOUND'
286
+ raise GoogleMapsService::Error::NotFoundError.new(response), (body[:error_message] || 'ADDRESS NOT FOUND')
287
+ else
288
+ raise GoogleMapsService::Error::ApiError.new(response), body[:error_message]
289
+ end
290
+ end
291
+ end
292
+ end