what3words 2.0.4 → 3.0.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.
@@ -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'