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.
- checksums.yaml +5 -5
- data/.travis.yml +2 -2
- data/Gemfile +3 -1
- data/LICENSE.txt +1 -1
- data/README.md +175 -69
- data/Rakefile +9 -4
- data/lib/what3words/api.rb +160 -75
- data/lib/what3words/version.rb +4 -1
- data/lib/what3words.rb +4 -2
- data/spec/lib/what3words/what3words_api_spec.rb +248 -66
- data/spec/spec_helper.rb +5 -3
- data/what3words.gemspec +20 -16
- metadata +31 -12
data/lib/what3words/api.rb
CHANGED
@@ -1,27 +1,32 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
3
|
+
require 'rest-client'
|
4
|
+
require File.expand_path('../version', __FILE__)
|
5
|
+
require 'what3words/version'
|
4
6
|
|
5
7
|
module What3Words
|
6
|
-
|
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}{
|
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 =
|
19
|
+
BASE_URL = 'https://api.what3words.com/v3/'
|
16
20
|
|
17
21
|
ENDPOINTS = {
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
|
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
|
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 =
|
35
|
-
response = request! :
|
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
|
40
|
-
|
41
|
-
|
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
|
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! :
|
66
|
+
response = request! :grid_section, request_params
|
48
67
|
response
|
49
68
|
end
|
50
69
|
|
51
|
-
def
|
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! :
|
74
|
+
response = request! :available_languages, request_params
|
54
75
|
response
|
55
76
|
end
|
56
77
|
|
57
|
-
def autosuggest(
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
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
|
-
|
64
|
-
request_params =
|
65
|
-
response = request! :
|
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
|
-
|
71
|
-
|
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
|
79
|
-
|
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 :
|
132
|
+
private :assemble_convert_to_coordinates_request_params
|
83
133
|
|
84
|
-
def
|
85
|
-
|
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 :
|
140
|
+
private :assemble_convert_to_3wa_request_params
|
89
141
|
|
90
|
-
def
|
91
|
-
|
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 :
|
149
|
+
private :assemble_grid_request_params
|
95
150
|
|
96
|
-
def assemble_autosuggest_request_params(
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
-
#
|
194
|
+
# Defines HTTP request methods
|
195
|
+
# puts endpoint(endpoint_name).inspect
|
119
196
|
# puts params.inspect
|
120
197
|
begin
|
121
|
-
|
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
|
126
|
-
# puts
|
205
|
+
# puts '#{response.to_str}'
|
206
|
+
# puts 'Response status: #{response.code}'
|
127
207
|
response = JSON.parse(response.body)
|
128
|
-
|
129
|
-
|
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
|
-
|
236
|
+
|
237
|
+
words
|
152
238
|
end
|
153
239
|
private :check_words
|
154
240
|
|
155
241
|
def deep_symbolize_keys(i)
|
156
|
-
if i.
|
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.
|
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
|
-
|
260
|
+
base_url + ENDPOINTS.fetch(name)
|
175
261
|
end
|
176
|
-
|
177
262
|
end
|
178
263
|
end
|
data/lib/what3words/version.rb
CHANGED
data/lib/what3words.rb
CHANGED