what3words 2.0.4 → 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,27 +1,32 @@
1
- # encoding: utf-8
1
+ # frozen_string_literal: true
2
2
 
3
- require "rest-client"
3
+ require 'rest-client'
4
+ require File.expand_path('../version', __FILE__)
5
+ require 'what3words/version'
4
6
 
5
7
  module What3Words
6
- class API
7
-
8
+ # What3Words v3 API wrapper
9
+ class API # rubocop:disable Metrics/ClassLength
10
+ # This class provides an interface to the what3words API
11
+ # at https://developer.what3words.com/public-api/docs
8
12
  class Error < RuntimeError; end
9
13
  class ResponseError < Error; end
10
14
  class WordError < Error; end
11
15
 
12
- REGEX_3_WORD_ADDRESS = /^\p{L}+\.\p{L}+\.\p{L}+$/u
13
- REGEX_STRICT = /^\p{L}{4,}+\.\p{L}{4,}+\.\p{L}{4,}+$/u
16
+ REGEX_3_WORD_ADDRESS = /^\p{L}+\.\p{L}+\.\p{L}+$/u.freeze
17
+ REGEX_STRICT = /^\p{L}{3,}+\.\p{L}{3,}+\.\p{L}{3,}+$/u.freeze
14
18
 
15
- BASE_URL = "https://api.what3words.com/v2/"
19
+ BASE_URL = 'https://api.what3words.com/v3/'
16
20
 
17
21
  ENDPOINTS = {
18
- :forward => "forward",
19
- :reverse => "reverse",
20
- :languages => "languages",
21
- :autosuggest => "autosuggest",
22
- :standardblend => "standardblend",
23
- :grid => "grid"
24
- }
22
+ convert_to_coordinates: 'convert-to-coordinates',
23
+ convert_to_3wa: 'convert-to-3wa',
24
+ available_languages: 'available-languages',
25
+ autosuggest: 'autosuggest',
26
+ grid_section: 'grid-section'
27
+ }.freeze
28
+
29
+ WRAPPER_VERSION = What3Words::VERSION
25
30
 
26
31
  def initialize(params)
27
32
  @key = params.fetch(:key)
@@ -29,114 +34,194 @@ module What3Words
29
34
 
30
35
  attr_reader :key
31
36
 
32
- def forward(words, params = {})
37
+ def convert_to_coordinates(words, params = {})
38
+ # Take a 3 word address and turn it into a pair of coordinates.
39
+ # @:param string words: A 3 word address as a string
40
+ # @:param string format: Return data format type; can be one of json (the default), geojson
41
+ # API Reference: https://docs.what3words.com/api/v3/#convert-to-coordinates
33
42
  words_string = get_words_string words
34
- request_params = assemble_forward_request_params(words_string, params)
35
- response = request! :forward, request_params
43
+ request_params = assemble_convert_to_coordinates_request_params(words_string, params)
44
+ response = request! :convert_to_coordinates, request_params
36
45
  response
37
46
  end
38
47
 
39
- def reverse(position, params = {})
40
- request_params = assemble_reverse_request_params(position, params)
41
- response = request! :reverse, request_params
48
+ def convert_to_3wa(position, params = {})
49
+ # Take latitude and longitude coordinates and turn them into a 3 word address.
50
+ # @:param coordinates: the coordinates of the location to convert to 3 word address
51
+ # @:param string format: Return data format type; can be one of json (the default), geojson
52
+ # @:param string language: A supported 3 word address language as an ISO 639-1 2 letter code.
53
+ # API Reference: https://docs.what3words.com/api/v3/#convert-to-3wa
54
+ request_params = assemble_convert_to_3wa_request_params(position, params)
55
+ response = request! :convert_to_3wa, request_params
42
56
  response
43
57
  end
44
58
 
45
- def grid(bbox, params = {})
59
+ def grid_section(bbox, params = {})
60
+ # Returns a section of the 3m x 3m what3words grid for a given area.
61
+ # @:param bounding-box: Bounding box, specified by the northeast and southwest corner coordinates,
62
+ # for which the grid should be returned.
63
+ # @:param string format: Return data format type; can be one of json (the default), geojson
64
+ # API Reference: https://docs.what3words.com/api/v3/#grid-section
46
65
  request_params = assemble_grid_request_params(bbox, params)
47
- response = request! :grid, request_params
66
+ response = request! :grid_section, request_params
48
67
  response
49
68
  end
50
69
 
51
- def languages()
70
+ def available_languages
71
+ # Retrieve a list of available 3 word languages.
72
+ # API Reference: https://docs.what3words.com/api/v3/#available-languages
52
73
  request_params = assemble_common_request_params({})
53
- response = request! :languages, request_params
74
+ response = request! :available_languages, request_params
54
75
  response
55
76
  end
56
77
 
57
- def autosuggest(addr, lang, focus = {}, clip = {}, params = {})
58
- request_params = assemble_autosuggest_request_params(addr, lang, focus, clip, params)
59
- response = request! :autosuggest, request_params
60
- response
61
- end
78
+ def autosuggest(input, params = {})
79
+ # Returns a list of 3 word addresses based on user input and other parameters.
80
+ # @:param string input: The full or partial 3 word address to obtain suggestions for.
81
+ # At minimum this must be the first two complete words plus at least one character
82
+ # from the third word.
83
+ # @:param int n_results: The number of AutoSuggest results to return.
84
+ # A maximum of 100 results can be specified, if a number greater than this is requested,
85
+ # this will be truncated to the maximum. The default is 3.
86
+ # @:param int n_focus_results: Specifies the number of results (must be <= n_results)
87
+ # within the results set which will have a focus. Defaults to n_results.
88
+ # This allows you to run autosuggest with a mix of focussed and unfocussed results,
89
+ # to give you a "blend" of the two.
90
+ # @:param string clip-to-country: Restricts autosuggest to only return results inside
91
+ # the countries specified by comma-separated list of uppercase ISO 3166-1
92
+ # alpha-2 country codes (for example, to restrict to Belgium and the UK,
93
+ # use clip_to_country="GB,BE").
94
+ # @:param clip-to-bounding-box: Restrict autosuggest results to a bounding box, specified by coordinates.
95
+ # @:param clip-to-circle: Restrict autosuggest results to a circle, specified by
96
+ # the center of the circle, latitude and longitude, and a distance in kilometres which represents the radius.
97
+ # For convenience, longitude is allowed to wrap around 180 degrees. For example 181 is equivalent to -179.
98
+ # @:param clip-to-polygon: Restrict autosuggest results to a polygon, specified by a list of coordinates.
99
+ # The polygon should be closed, i.e. the first element should be repeated as the
100
+ # last element; also the list should contain at least 4 entries.
101
+ # The API is currently limited to accepting up to 25 pairs.
102
+ # @:param string input-type: For power users, used to specify voice input mode.
103
+ # Can be text (default), vocon-hybrid, nmdp-asr or generic-voice.
104
+ # @:param string prefer-land: Makes autosuggest prefer results on land to those in the sea.
105
+ # @:param string language: A supported 3 word address language as an ISO 639-1 2 letter code.
106
+ # This setting is on by default. Use false to disable this setting and receive more suggestions in the sea.
62
107
 
63
- def standardblend(addr, lang, focus = {}, params = {})
64
- request_params = assemble_standardblend_request_params(addr, lang, focus, params)
65
- response = request! :standardblend, request_params
108
+ # API Reference: https://docs.what3words.com/api/v3/#autosuggest
109
+ request_params = assemble_autosuggest_request_params(input, params)
110
+ response = request! :autosuggest, request_params
66
111
  response
67
112
  end
68
113
 
69
114
  def assemble_common_request_params(params)
70
- h = {:key => key}
71
- h[:lang] = params[:lang] if params[:lang]
115
+ # Return common request params
116
+ # @:param api_key: A valid API key
117
+ # @:param string language: A supported 3 word address language as an ISO 639-1 2 letter code.
118
+ # @:param string format: Return data format type; can be one of json (the default), geojson
119
+ h = { key: key }
120
+ h[:language] = params[:language] if params[:language]
72
121
  h[:format] = params[:format] if params[:format]
73
- h[:display] = params[:display] if params[:display]
74
122
  h
75
123
  end
76
124
  private :assemble_common_request_params
77
125
 
78
- def assemble_forward_request_params(words_string, params)
79
- h = {:addr => words_string}
126
+ def assemble_convert_to_coordinates_request_params(words_string, params)
127
+ # Returns request params for the convert to coordinates function
128
+ # @:param string words: A 3 word address as a string
129
+ h = { words: words_string }
80
130
  h.merge(assemble_common_request_params(params))
81
131
  end
82
- private :assemble_forward_request_params
132
+ private :assemble_convert_to_coordinates_request_params
83
133
 
84
- def assemble_grid_request_params(bbox, params)
85
- h = {:bbox => bbox}
134
+ def assemble_convert_to_3wa_request_params(position, params)
135
+ # Return request params for the convert to 3wa function
136
+ # @:param coordinates: the coordinates of the location to convert to 3 word address
137
+ h = { coordinates: position.join(',') }
86
138
  h.merge(assemble_common_request_params(params))
87
139
  end
88
- private :assemble_grid_request_params
140
+ private :assemble_convert_to_3wa_request_params
89
141
 
90
- def assemble_reverse_request_params(position, params)
91
- h = {:coords => position.join(",")}
142
+ def assemble_grid_request_params(bbox, params)
143
+ # Returns the request params for the grid_section function
144
+ # @:param bounding-box: Bounding box, specified by the northeast and
145
+ # southwest corner coordinates, for which the grid should be returned.
146
+ h = { 'bounding-box': bbox }
92
147
  h.merge(assemble_common_request_params(params))
93
148
  end
94
- private :assemble_reverse_request_params
149
+ private :assemble_grid_request_params
95
150
 
96
- def assemble_autosuggest_request_params(addr, lang, focus, clip, params)
97
- h = {:addr => addr}
98
- h[:lang] = lang
99
- if focus.respond_to? :join
100
- h[:focus] = focus.join(",")
101
- end
102
- h[:clip] = clip if clip.respond_to? :to_str
151
+ def assemble_autosuggest_request_params(input, params)
152
+ # Returns the request params for the autosuggest function
153
+ # @:param string input: The full or partial 3 word address to obtain suggestions for.
154
+ # At minimum this must be the first two complete words plus
155
+ # at least one character from the third word.
156
+ # @:param int n_results: The number of AutoSuggest results to return.
157
+ # A maximum of 100 results can be specified, if a number greater than this is requested,
158
+ # this will be truncated to the maximum. The default is 3.
159
+ # @:param int n_focus_results: Specifies the number of results (must be <= n_results)
160
+ # within the results set which will have a focus. Defaults to n_results.
161
+ # This allows you to run autosuggest with a mix of
162
+ # focussed and unfocussed results, to give you a "blend" of the two.
163
+ # @:param string clip-to-country: Restricts autosuggest to only return results inside
164
+ # the countries specified by comma-separated list of uppercase ISO 3166-1
165
+ # alpha-2 country codes (for example, to restrict to Belgium and the UK,
166
+ # use clip_to_country="GB,BE").
167
+ # @:param clip-to-bounding-box: Restrict autosuggest results to a bounding box, specified by coordinates.
168
+ # @:param clip-to-circle: Restrict autosuggest results to a circle, specified by
169
+ # the center of the circle, latitude and longitude, and a distance in kilometres
170
+ # which represents the radius. For convenience, longitude
171
+ # is allowed to wrap around 180 degrees. For example 181 is equivalent to -179.
172
+ # @:param clip-to-polygon: Restrict autosuggest results to a polygon, specified by a list of coordinates.
173
+ # The polygon should be closed, i.e. the first element should be repeated as the
174
+ # last element; also the list should contain at least 4 entries.
175
+ # The API is currently limited to accepting up to 25 pairs.
176
+ # @:param string input-type: For power users, used to specify voice input mode.
177
+ # Can be text (default), vocon-hybrid, nmdp-asr or generic-voice.
178
+ # @:param string prefer-land: Makes autosuggest prefer results on land to those in the sea.
179
+ h = { input: input }
180
+ h[:'n-results'] = params[:'n-results'].to_i if params[:'n-results']
181
+ h[:focus] = params[:focus].join(',') if params[:focus].respond_to? :join
182
+ h[:'n-focus-results'] = params[:'n-focus-results'].to_i if params[:'n-focus-results']
183
+ h[:'clip-to-country'] = params[:'clip-to-country'] if params[:'clip-to-country'].respond_to? :to_str
184
+ h[:'clip-to-bounding-box'] = params[:'clip-to-bounding-box'].join(',') if params[:'clip-to-bounding-box'].respond_to? :join
185
+ h[:'clip-to-circle'] = params[:'clip-to-circle'].join(',') if params[:'clip-to-circle'].respond_to? :join
186
+ h[:'clip-to-polygon'] = params[:'clip-to-polygon'].join(',') if params[:'clip-to-polygon'].respond_to? :join
187
+ h[:'input-type'] = params[:'input-type'] if params[:'input-type'].respond_to? :to_str
188
+ h[:'prefer-land'] = params[:'prefer-land'] if params[:'prefer-land']
103
189
  h.merge(assemble_common_request_params(params))
104
190
  end
105
191
  private :assemble_autosuggest_request_params
106
192
 
107
- def assemble_standardblend_request_params(addr, lang, focus, params)
108
- h = {:addr => addr}
109
- h[:lang] = lang
110
- if focus.respond_to? :join
111
- h[:focus] = focus.join(",")
112
- end
113
- h.merge(assemble_common_request_params(params))
114
- end
115
- private :assemble_standardblend_request_params
116
-
117
193
  def request!(endpoint_name, params)
118
- # puts endpoint_name.inspect
194
+ # Defines HTTP request methods
195
+ # puts endpoint(endpoint_name).inspect
119
196
  # puts params.inspect
120
197
  begin
121
- response = RestClient.get endpoint(endpoint_name), params: params
198
+ headers = { "X-W3W-Wrapper": "what3words-Ruby/#{WRAPPER_VERSION}" }
199
+ response = RestClient.get endpoint(endpoint_name), params: params, headers: headers
122
200
  rescue => e
201
+ # puts e.inspect
202
+ # puts e.methods.sort
123
203
  response = e.response
124
204
  end
125
- # puts "#{response.to_str}"
126
- # puts "Response status: #{response.code}"
205
+ # puts '#{response.to_str}'
206
+ # puts 'Response status: #{response.code}'
127
207
  response = JSON.parse(response.body)
128
- if response["code"].to_s.strip != ""
129
- raise ResponseError, "#{response["code"]}: #{response["message"]}"
208
+ # puts response.inspect
209
+
210
+ if response['error'].to_s.strip != ''
211
+ raise ResponseError, "#{response['code']}: #{response['message']}"
130
212
  end
213
+
131
214
  deep_symbolize_keys(response)
215
+
132
216
  end
133
217
  private :request!
134
218
 
135
219
  def get_words_string(words)
220
+ # Returns words in string otherwise raise an issue
136
221
  if words.respond_to? :to_str
137
222
  w = words
138
223
  elsif words.respond_to? :join
139
- w = words.join(".")
224
+ w = words.join('.')
140
225
  else
141
226
  raise Error, "Cannot get words string for #{words.inspect}"
142
227
  end
@@ -148,15 +233,16 @@ module What3Words
148
233
  unless REGEX_3_WORD_ADDRESS.match(words)
149
234
  raise WordError, "#{words} is not a valid 3 word address"
150
235
  end
151
- return words
236
+
237
+ words
152
238
  end
153
239
  private :check_words
154
240
 
155
241
  def deep_symbolize_keys(i)
156
- if i.kind_of? Hash
242
+ if i.is_a? Hash
157
243
  ni = {}
158
- i.each {|k,v| ni[k.respond_to?(:to_sym) ? k.to_sym : k] = deep_symbolize_keys(v) }
159
- elsif i.kind_of? Array
244
+ i.each { |k, v| ni[k.respond_to?(:to_sym) ? k.to_sym : k] = deep_symbolize_keys(v) }
245
+ elsif i.is_a? Array
160
246
  ni = i.map(&method(:deep_symbolize_keys))
161
247
  else
162
248
  ni = i
@@ -165,14 +251,13 @@ module What3Words
165
251
  ni
166
252
  end
167
253
 
168
- def base_url()
254
+ def base_url
169
255
  BASE_URL
170
256
  end
171
257
  private :base_url
172
258
 
173
259
  def endpoint(name)
174
- return base_url() + ENDPOINTS.fetch(name)
260
+ base_url + ENDPOINTS.fetch(name)
175
261
  end
176
-
177
262
  end
178
263
  end
@@ -1,3 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ # What3Words v3 API wrapper
1
4
  module What3Words
2
- VERSION = "2.0.4"
5
+ VERSION = '3.0.0' unless defined?(::What3Words::VERSION)
3
6
  end
data/lib/what3words.rb CHANGED
@@ -1,4 +1,6 @@
1
- module What3Words
1
+ # frozen_string_literal: true
2
+
3
+ module What3Words # :nodoc: don't document this
2
4
  end
3
5
 
4
- require "what3words/api"
6
+ require 'what3words/api'