geocoder 1.5.1 → 1.6.7
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/CHANGELOG.md +45 -0
- data/LICENSE +1 -1
- data/README.md +16 -39
- data/bin/console +13 -0
- data/examples/autoexpire_cache_redis.rb +2 -0
- data/lib/easting_northing.rb +171 -0
- data/lib/geocoder/cache.rb +4 -0
- data/lib/geocoder/configuration.rb +2 -1
- data/lib/geocoder/configuration_hash.rb +4 -4
- data/lib/geocoder/ip_address.rb +2 -1
- data/lib/geocoder/lookup.rb +8 -3
- data/lib/geocoder/lookups/abstract_api.rb +46 -0
- data/lib/geocoder/lookups/ban_data_gouv_fr.rb +14 -1
- data/lib/geocoder/lookups/base.rb +2 -0
- data/lib/geocoder/lookups/esri.rb +6 -0
- data/lib/geocoder/lookups/freegeoip.rb +4 -4
- data/lib/geocoder/lookups/geocodio.rb +1 -1
- data/lib/geocoder/lookups/google.rb +7 -2
- data/lib/geocoder/lookups/google_places_details.rb +8 -14
- data/lib/geocoder/lookups/google_places_search.rb +28 -2
- data/lib/geocoder/lookups/google_premier.rb +4 -0
- data/lib/geocoder/lookups/here.rb +7 -16
- data/lib/geocoder/lookups/ip2location.rb +5 -13
- data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
- data/lib/geocoder/lookups/ipregistry.rb +68 -0
- data/lib/geocoder/lookups/latlon.rb +1 -2
- data/lib/geocoder/lookups/maxmind_local.rb +7 -1
- data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
- data/lib/geocoder/lookups/osmnames.rb +57 -0
- data/lib/geocoder/lookups/pickpoint.rb +1 -1
- data/lib/geocoder/lookups/smarty_streets.rb +6 -1
- data/lib/geocoder/lookups/telize.rb +1 -1
- data/lib/geocoder/lookups/tencent.rb +9 -9
- data/lib/geocoder/lookups/test.rb +4 -0
- data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/lookups/yandex.rb +3 -4
- data/lib/geocoder/results/abstract_api.rb +146 -0
- data/lib/geocoder/results/baidu.rb +0 -4
- data/lib/geocoder/results/ban_data_gouv_fr.rb +27 -2
- data/lib/geocoder/results/db_ip_com.rb +1 -1
- data/lib/geocoder/results/here.rb +4 -1
- data/lib/geocoder/results/ipgeolocation.rb +59 -0
- data/lib/geocoder/results/ipregistry.rb +304 -0
- data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
- data/lib/geocoder/results/nominatim.rb +4 -0
- data/lib/geocoder/results/osmnames.rb +56 -0
- data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
- data/lib/geocoder/results/yandex.rb +217 -59
- data/lib/geocoder/sql.rb +4 -4
- data/lib/geocoder/util.rb +29 -0
- data/lib/geocoder/version.rb +1 -1
- data/lib/maxmind_database.rb +3 -3
- metadata +22 -16
- data/lib/geocoder/lookups/geocoder_us.rb +0 -51
- data/lib/geocoder/results/geocoder_us.rb +0 -39
- data/lib/hash_recursive_merge.rb +0 -74
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Osmnames < Base
|
5
|
+
def address
|
6
|
+
@data['display_name']
|
7
|
+
end
|
8
|
+
|
9
|
+
def coordinates
|
10
|
+
[@data['lat'].to_f, @data['lon'].to_f]
|
11
|
+
end
|
12
|
+
|
13
|
+
def viewport
|
14
|
+
west, south, east, north = @data['boundingbox'].map(&:to_f)
|
15
|
+
[south, west, north, east]
|
16
|
+
end
|
17
|
+
|
18
|
+
def state
|
19
|
+
@data['state']
|
20
|
+
end
|
21
|
+
alias_method :state_code, :state
|
22
|
+
|
23
|
+
def place_class
|
24
|
+
@data['class']
|
25
|
+
end
|
26
|
+
|
27
|
+
def place_type
|
28
|
+
@data['type']
|
29
|
+
end
|
30
|
+
|
31
|
+
def postal_code
|
32
|
+
''
|
33
|
+
end
|
34
|
+
|
35
|
+
def country_code
|
36
|
+
@data['country_code']
|
37
|
+
end
|
38
|
+
|
39
|
+
def country
|
40
|
+
@data['country']
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.response_attributes
|
44
|
+
%w[house_number street city name osm_id osm_type boundingbox place_rank
|
45
|
+
importance county rank name_suffix]
|
46
|
+
end
|
47
|
+
|
48
|
+
response_attributes.each do |a|
|
49
|
+
unless method_defined?(a)
|
50
|
+
define_method a do
|
51
|
+
@data[a]
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
require 'easting_northing'
|
3
|
+
|
4
|
+
module Geocoder::Result
|
5
|
+
class UkOrdnanceSurveyNames < Base
|
6
|
+
|
7
|
+
def coordinates
|
8
|
+
@coordinates ||= Geocoder::EastingNorthing.new(
|
9
|
+
easting: data['GEOMETRY_X'],
|
10
|
+
northing: data['GEOMETRY_Y'],
|
11
|
+
).lat_lng
|
12
|
+
end
|
13
|
+
|
14
|
+
def city
|
15
|
+
is_postcode? ? data['DISTRICT_BOROUGH'] : data['NAME1']
|
16
|
+
end
|
17
|
+
|
18
|
+
def county
|
19
|
+
data['COUNTY_UNITARY']
|
20
|
+
end
|
21
|
+
alias state county
|
22
|
+
|
23
|
+
def county_code
|
24
|
+
code_from_uri data['COUNTY_UNITARY_URI']
|
25
|
+
end
|
26
|
+
alias state_code county_code
|
27
|
+
|
28
|
+
def province
|
29
|
+
data['REGION']
|
30
|
+
end
|
31
|
+
|
32
|
+
def province_code
|
33
|
+
code_from_uri data['REGION_URI']
|
34
|
+
end
|
35
|
+
|
36
|
+
def postal_code
|
37
|
+
is_postcode? ? data['NAME1'] : ''
|
38
|
+
end
|
39
|
+
|
40
|
+
def country
|
41
|
+
'United Kingdom'
|
42
|
+
end
|
43
|
+
|
44
|
+
def country_code
|
45
|
+
'UK'
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def is_postcode?
|
51
|
+
data['LOCAL_TYPE'] == 'Postcode'
|
52
|
+
end
|
53
|
+
|
54
|
+
def code_from_uri(uri)
|
55
|
+
return '' if uri.nil?
|
56
|
+
uri.split('/').last
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -2,78 +2,223 @@ require 'geocoder/results/base'
|
|
2
2
|
|
3
3
|
module Geocoder::Result
|
4
4
|
class Yandex < Base
|
5
|
+
# Yandex result has difficult tree structure,
|
6
|
+
# and presence of some nodes depends on exact search case.
|
7
|
+
|
8
|
+
# Also Yandex lacks documentation about it.
|
9
|
+
# See https://tech.yandex.com/maps/doc/geocoder/desc/concepts/response_structure-docpage/
|
10
|
+
|
11
|
+
# Ultimatly, we need to find Locality and/or Thoroughfare data.
|
12
|
+
|
13
|
+
# It may resides on the top (ADDRESS_DETAILS) level.
|
14
|
+
# example: 'Baltic Sea'
|
15
|
+
# "AddressDetails": {
|
16
|
+
# "Locality": {
|
17
|
+
# "Premise": {
|
18
|
+
# "PremiseName": "Baltic Sea"
|
19
|
+
# }
|
20
|
+
# }
|
21
|
+
# }
|
22
|
+
|
23
|
+
ADDRESS_DETAILS = %w[
|
24
|
+
GeoObject metaDataProperty GeocoderMetaData
|
25
|
+
AddressDetails
|
26
|
+
].freeze
|
27
|
+
|
28
|
+
# On COUNTRY_LEVEL.
|
29
|
+
# example: 'Potomak'
|
30
|
+
# "AddressDetails": {
|
31
|
+
# "Country": {
|
32
|
+
# "AddressLine": "reka Potomak",
|
33
|
+
# "CountryNameCode": "US",
|
34
|
+
# "CountryName": "United States of America",
|
35
|
+
# "Locality": {
|
36
|
+
# "Premise": {
|
37
|
+
# "PremiseName": "reka Potomak"
|
38
|
+
# }
|
39
|
+
# }
|
40
|
+
# }
|
41
|
+
# }
|
42
|
+
|
43
|
+
COUNTRY_LEVEL = %w[
|
44
|
+
GeoObject metaDataProperty GeocoderMetaData
|
45
|
+
AddressDetails Country
|
46
|
+
].freeze
|
47
|
+
|
48
|
+
# On ADMIN_LEVEL (usually state or city)
|
49
|
+
# example: 'Moscow, Tverskaya'
|
50
|
+
# "AddressDetails": {
|
51
|
+
# "Country": {
|
52
|
+
# "AddressLine": "Moscow, Tverskaya Street",
|
53
|
+
# "CountryNameCode": "RU",
|
54
|
+
# "CountryName": "Russia",
|
55
|
+
# "AdministrativeArea": {
|
56
|
+
# "AdministrativeAreaName": "Moscow",
|
57
|
+
# "Locality": {
|
58
|
+
# "LocalityName": "Moscow",
|
59
|
+
# "Thoroughfare": {
|
60
|
+
# "ThoroughfareName": "Tverskaya Street"
|
61
|
+
# }
|
62
|
+
# }
|
63
|
+
# }
|
64
|
+
# }
|
65
|
+
# }
|
66
|
+
|
67
|
+
ADMIN_LEVEL = %w[
|
68
|
+
GeoObject metaDataProperty GeocoderMetaData
|
69
|
+
AddressDetails Country
|
70
|
+
AdministrativeArea
|
71
|
+
].freeze
|
72
|
+
|
73
|
+
# On SUBADMIN_LEVEL (may refer to urban district)
|
74
|
+
# example: 'Moscow Region, Krasnogorsk'
|
75
|
+
# "AddressDetails": {
|
76
|
+
# "Country": {
|
77
|
+
# "AddressLine": "Moscow Region, Krasnogorsk",
|
78
|
+
# "CountryNameCode": "RU",
|
79
|
+
# "CountryName": "Russia",
|
80
|
+
# "AdministrativeArea": {
|
81
|
+
# "AdministrativeAreaName": "Moscow Region",
|
82
|
+
# "SubAdministrativeArea": {
|
83
|
+
# "SubAdministrativeAreaName": "gorodskoy okrug Krasnogorsk",
|
84
|
+
# "Locality": {
|
85
|
+
# "LocalityName": "Krasnogorsk"
|
86
|
+
# }
|
87
|
+
# }
|
88
|
+
# }
|
89
|
+
# }
|
90
|
+
# }
|
91
|
+
|
92
|
+
SUBADMIN_LEVEL = %w[
|
93
|
+
GeoObject metaDataProperty GeocoderMetaData
|
94
|
+
AddressDetails Country
|
95
|
+
AdministrativeArea
|
96
|
+
SubAdministrativeArea
|
97
|
+
].freeze
|
98
|
+
|
99
|
+
# On DEPENDENT_LOCALITY_1 (may refer to district of city)
|
100
|
+
# example: 'Paris, Etienne Marcel'
|
101
|
+
# "AddressDetails": {
|
102
|
+
# "Country": {
|
103
|
+
# "AddressLine": "Île-de-France, Paris, 1er Arrondissement, Rue Étienne Marcel",
|
104
|
+
# "CountryNameCode": "FR",
|
105
|
+
# "CountryName": "France",
|
106
|
+
# "AdministrativeArea": {
|
107
|
+
# "AdministrativeAreaName": "Île-de-France",
|
108
|
+
# "Locality": {
|
109
|
+
# "LocalityName": "Paris",
|
110
|
+
# "DependentLocality": {
|
111
|
+
# "DependentLocalityName": "1er Arrondissement",
|
112
|
+
# "Thoroughfare": {
|
113
|
+
# "ThoroughfareName": "Rue Étienne Marcel"
|
114
|
+
# }
|
115
|
+
# }
|
116
|
+
# }
|
117
|
+
# }
|
118
|
+
# }
|
119
|
+
# }
|
120
|
+
|
121
|
+
DEPENDENT_LOCALITY_1 = %w[
|
122
|
+
GeoObject metaDataProperty GeocoderMetaData
|
123
|
+
AddressDetails Country
|
124
|
+
AdministrativeArea Locality
|
125
|
+
DependentLocality
|
126
|
+
].freeze
|
127
|
+
|
128
|
+
# On DEPENDENT_LOCALITY_2 (for special cases like turkish "mahalle")
|
129
|
+
# https://en.wikipedia.org/wiki/Mahalle
|
130
|
+
# example: 'Istanbul Mabeyinci Yokuşu 17'
|
131
|
+
|
132
|
+
# "AddressDetails": {
|
133
|
+
# "Country": {
|
134
|
+
# "AddressLine": "İstanbul, Fatih, Saraç İshak Mah., Mabeyinci Yokuşu, 17",
|
135
|
+
# "CountryNameCode": "TR",
|
136
|
+
# "CountryName": "Turkey",
|
137
|
+
# "AdministrativeArea": {
|
138
|
+
# "AdministrativeAreaName": "İstanbul",
|
139
|
+
# "SubAdministrativeArea": {
|
140
|
+
# "SubAdministrativeAreaName": "Fatih",
|
141
|
+
# "Locality": {
|
142
|
+
# "DependentLocality": {
|
143
|
+
# "DependentLocalityName": "Saraç İshak Mah.",
|
144
|
+
# "Thoroughfare": {
|
145
|
+
# "ThoroughfareName": "Mabeyinci Yokuşu",
|
146
|
+
# "Premise": {
|
147
|
+
# "PremiseNumber": "17"
|
148
|
+
# }
|
149
|
+
# }
|
150
|
+
# }
|
151
|
+
# }
|
152
|
+
# }
|
153
|
+
# }
|
154
|
+
# }
|
155
|
+
# }
|
156
|
+
|
157
|
+
DEPENDENT_LOCALITY_2 = %w[
|
158
|
+
GeoObject metaDataProperty GeocoderMetaData
|
159
|
+
AddressDetails Country
|
160
|
+
AdministrativeArea
|
161
|
+
SubAdministrativeArea Locality
|
162
|
+
DependentLocality
|
163
|
+
].freeze
|
5
164
|
|
6
165
|
def coordinates
|
7
166
|
@data['GeoObject']['Point']['pos'].split(' ').reverse.map(&:to_f)
|
8
167
|
end
|
9
168
|
|
10
|
-
def address(
|
169
|
+
def address(_format = :full)
|
11
170
|
@data['GeoObject']['metaDataProperty']['GeocoderMetaData']['text']
|
12
171
|
end
|
13
172
|
|
14
173
|
def city
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
174
|
+
result =
|
175
|
+
if state.empty?
|
176
|
+
find_in_hash(@data, *COUNTRY_LEVEL, 'Locality', 'LocalityName')
|
177
|
+
elsif sub_state.empty?
|
178
|
+
find_in_hash(@data, *ADMIN_LEVEL, 'Locality', 'LocalityName')
|
179
|
+
else
|
180
|
+
find_in_hash(@data, *SUBADMIN_LEVEL, 'Locality', 'LocalityName')
|
181
|
+
end
|
182
|
+
|
183
|
+
result || ""
|
25
184
|
end
|
26
185
|
|
27
186
|
def country
|
28
|
-
|
29
|
-
address_details['CountryName']
|
30
|
-
else
|
31
|
-
""
|
32
|
-
end
|
187
|
+
find_in_hash(@data, *COUNTRY_LEVEL, 'CountryName') || ""
|
33
188
|
end
|
34
189
|
|
35
190
|
def country_code
|
36
|
-
|
37
|
-
address_details['CountryNameCode']
|
38
|
-
else
|
39
|
-
""
|
40
|
-
end
|
191
|
+
find_in_hash(@data, *COUNTRY_LEVEL, 'CountryNameCode') || ""
|
41
192
|
end
|
42
193
|
|
43
194
|
def state
|
44
|
-
|
45
|
-
address_details['AdministrativeArea']['AdministrativeAreaName']
|
46
|
-
else
|
47
|
-
""
|
48
|
-
end
|
195
|
+
find_in_hash(@data, *ADMIN_LEVEL, 'AdministrativeAreaName') || ""
|
49
196
|
end
|
50
197
|
|
51
198
|
def sub_state
|
52
|
-
if
|
53
|
-
|
54
|
-
else
|
55
|
-
""
|
56
|
-
end
|
199
|
+
return "" if state.empty?
|
200
|
+
find_in_hash(@data, *SUBADMIN_LEVEL, 'SubAdministrativeAreaName') || ""
|
57
201
|
end
|
58
202
|
|
59
203
|
def state_code
|
60
204
|
""
|
61
205
|
end
|
62
206
|
|
63
|
-
def
|
64
|
-
""
|
207
|
+
def street
|
208
|
+
thoroughfare_data.is_a?(Hash) ? thoroughfare_data['ThoroughfareName'] : ""
|
65
209
|
end
|
66
210
|
|
67
|
-
def
|
68
|
-
|
211
|
+
def street_number
|
212
|
+
premise.is_a?(Hash) ? premise.fetch('PremiseNumber', "") : ""
|
69
213
|
end
|
70
214
|
|
71
|
-
def
|
72
|
-
|
215
|
+
def premise_name
|
216
|
+
premise.is_a?(Hash) ? premise.fetch('PremiseName', "") : ""
|
73
217
|
end
|
74
218
|
|
75
|
-
def
|
76
|
-
|
219
|
+
def postal_code
|
220
|
+
return "" unless premise.is_a?(Hash)
|
221
|
+
find_in_hash(premise, 'PostalCode', 'PostalCodeNumber') || ""
|
77
222
|
end
|
78
223
|
|
79
224
|
def kind
|
@@ -93,42 +238,55 @@ module Geocoder::Result
|
|
93
238
|
|
94
239
|
private # ----------------------------------------------------------------
|
95
240
|
|
96
|
-
def
|
97
|
-
|
241
|
+
def top_level_locality
|
242
|
+
find_in_hash(@data, *ADDRESS_DETAILS, 'Locality')
|
98
243
|
end
|
99
244
|
|
100
|
-
def
|
101
|
-
|
245
|
+
def country_level_locality
|
246
|
+
find_in_hash(@data, *COUNTRY_LEVEL, 'Locality')
|
102
247
|
end
|
103
248
|
|
104
249
|
def admin_locality
|
105
|
-
|
106
|
-
address_details['AdministrativeArea']['Locality']
|
250
|
+
find_in_hash(@data, *ADMIN_LEVEL, 'Locality')
|
107
251
|
end
|
108
252
|
|
109
253
|
def subadmin_locality
|
110
|
-
|
111
|
-
address_details['AdministrativeArea']['SubAdministrativeArea'] &&
|
112
|
-
address_details['AdministrativeArea']['SubAdministrativeArea']['Locality']
|
254
|
+
find_in_hash(@data, *SUBADMIN_LEVEL, 'Locality')
|
113
255
|
end
|
114
256
|
|
115
257
|
def dependent_locality
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
258
|
+
find_in_hash(@data, *DEPENDENT_LOCALITY_1) ||
|
259
|
+
find_in_hash(@data, *DEPENDENT_LOCALITY_2)
|
260
|
+
end
|
261
|
+
|
262
|
+
def locality_data
|
263
|
+
dependent_locality || subadmin_locality || admin_locality ||
|
264
|
+
country_level_locality || top_level_locality
|
265
|
+
end
|
266
|
+
|
267
|
+
def thoroughfare_data
|
268
|
+
locality_data['Thoroughfare'] if locality_data.is_a?(Hash)
|
120
269
|
end
|
121
270
|
|
122
|
-
def
|
123
|
-
|
271
|
+
def premise
|
272
|
+
if thoroughfare_data.is_a?(Hash)
|
273
|
+
thoroughfare_data['Premise']
|
274
|
+
elsif locality_data.is_a?(Hash)
|
275
|
+
locality_data['Premise']
|
276
|
+
end
|
124
277
|
end
|
125
278
|
|
126
|
-
def
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
279
|
+
def find_in_hash(source, *keys)
|
280
|
+
key = keys.shift
|
281
|
+
result = source[key]
|
282
|
+
|
283
|
+
if keys.empty?
|
284
|
+
return result
|
285
|
+
elsif !result.is_a?(Hash)
|
286
|
+
return nil
|
131
287
|
end
|
288
|
+
|
289
|
+
find_in_hash(result, *keys)
|
132
290
|
end
|
133
291
|
end
|
134
292
|
end
|