geonames-wrapper 1.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a7fccc103d99772879807bf97cf16dd02174ada1
4
+ data.tar.gz: 830586cc4d990bce38f3c11c93849301662e06e3
5
+ SHA512:
6
+ metadata.gz: 75131eabeeffa9bfec7ea7432ecd533128f24cfb88949ca779c63b78b6c8279e1f7c43b2d5625b2e806bf3b490938ce24cc85822117934a5d2dd65456b6b0278
7
+ data.tar.gz: bf1594d5120ea4568ddd8cb138541042a96a6b2ec3362015de013c02d129a25ebd0355a976c7f7fa5bf401a40b5098f6491e7949ef301ade1c8cfada84a3d332
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,20 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ geonames-wrapper (1.0.0)
5
+ addressable (~> 2.3)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ addressable (2.3.2)
11
+ rake (10.0.2)
12
+ yard (0.8.3)
13
+
14
+ PLATFORMS
15
+ ruby
16
+
17
+ DEPENDENCIES
18
+ geonames-wrapper!
19
+ rake
20
+ yard
@@ -0,0 +1,55 @@
1
+ # GeoNames API wrapper
2
+
3
+ The GeoNames geographical database covers all countries and contains over eight
4
+ million placenames that are available for download free of charge.
5
+
6
+ http://www.geonames.org/
7
+
8
+
9
+ ## Dependencies
10
+
11
+ This library depends on addressable, you can install it with
12
+ `gem install addressable`.
13
+
14
+
15
+ ## Usage
16
+
17
+ Instantiate the API and make a query:
18
+
19
+ >> api = GeoNames.new
20
+ >> api.ocean(lat: 0, lng: 0)
21
+ => {"name"=>"North Atlantic Ocean"}
22
+
23
+ Please read the documentation of the methods in the GeoNames class for more
24
+ information about the available methods and their arguments.
25
+
26
+
27
+ ## About
28
+
29
+ I wrote this library in hopes to improve upon the original geonames library
30
+ written by Adam Wisniewski.
31
+ It's around 1/5 of the code now, and should be easier to read, understand,
32
+ extend, and hack while being closer to the original specification of the API.
33
+
34
+
35
+ ### This library is licensed under the MIT License
36
+
37
+ Copyright (c) 2010 Michael Fellinger
38
+
39
+ Permission is hereby granted, free of charge, to any person obtaining a copy
40
+ of this software and associated documentation files (the "Software"), to deal
41
+ in the Software without restriction, including without limitation the rights
42
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
43
+ copies of the Software, and to permit persons to whom the Software is
44
+ furnished to do so, subject to the following conditions:
45
+
46
+ The above copyright notice and this permission notice shall be included in
47
+ all copies or substantial portions of the Software.
48
+
49
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
50
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
51
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
52
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
53
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
54
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
55
+ THE SOFTWARE.
@@ -0,0 +1,24 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "geonames-wrapper"
6
+ s.version = "1.1.0"
7
+ s.summary = "GeoNames JSON Web Service Wrapper"
8
+ s.description = "Bare-metal wrapper for GeoNames JSON Web Service API. Simple and effective."
9
+
10
+ s.platform = Gem::Platform::RUBY
11
+ s.required_ruby_version = ">= 1.9.0"
12
+
13
+ s.authors = ["Michael Fellinger", "Marcello Barnaba"]
14
+ s.email = ["m.fellinger@gmail.com", "vjt@openssl.it" ]
15
+ s.homepage = "http://github.com/vjt/geonames"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency 'addressable', '~> 2.3'
21
+
22
+ s.add_development_dependency("rake")
23
+ s.add_development_dependency("yard")
24
+ end
@@ -0,0 +1,788 @@
1
+ require 'json'
2
+ require 'open-uri'
3
+ require 'addressable/template'
4
+
5
+ class GeoNames
6
+ class APIError < RuntimeError; end
7
+
8
+ OPTIONS = {
9
+ host: 'api.geonames.org',
10
+ time_format: '%Y-%m-%d %T %z',
11
+ timezone: 'UTC',
12
+ username: nil,
13
+ }
14
+
15
+ QUERY = {}
16
+
17
+ attr_reader :options, :uris
18
+
19
+ def initialize(options = {})
20
+ @options = OPTIONS.merge(options)
21
+ @uris = Hash[QUERY.map{|name, args|
22
+ if args.empty?
23
+ template = Addressable::Template.new(
24
+ "http://{host}/#{name}JSON"
25
+ )
26
+ else
27
+ joined = (%w{ username } + args.flatten).uniq.sort.join(',')
28
+ template = Addressable::Template.new(
29
+ "http://{host}/#{name}JSON{?#{joined}}"
30
+ )
31
+ end
32
+ [name, template]
33
+ }]
34
+ end
35
+
36
+ # Execute query for given +name+ with +parameters+ translated via URI
37
+ # template expansion.
38
+ def query(name, parameters)
39
+ default = {host: options[:host]}
40
+ default[:username] = options[:username] if options[:username]
41
+
42
+ uri = uris[name].expand(default.merge(parameters))
43
+
44
+ result =
45
+ if block_given?
46
+ open(uri.to_s){|io| yield(io.read) }
47
+ else
48
+ open(uri.to_s){|io| JSON.parse(io.read) }
49
+ end
50
+
51
+ if status = result["status"]
52
+ raise APIError, status.inspect
53
+ else
54
+ result
55
+ end
56
+ end
57
+
58
+ # Utility method for some queries that return times, we convert them to real
59
+ # Time instances with proper UTC timezone.
60
+ def fix_datetime(hash)
61
+ if time = hash['datetime']
62
+ zone, format = options.values_at(:timezone, :time_format)
63
+ hash['datetime'] = Time.strptime("#{time} #{zone}", format)
64
+ end
65
+
66
+ hash
67
+ end
68
+
69
+ # Returns the attribute of the geoNames feature with the given geonameId
70
+ #
71
+ # Parameters: geonameId
72
+ #
73
+ # Example:
74
+ #
75
+ # api.get(geonameId: 2643743)
76
+ def get(parameters)
77
+ query(:get, parameters)
78
+ end
79
+ QUERY[:get] = %w[geonameId]
80
+
81
+ # Returns a list of recent earthquakes, ordered by magnitude
82
+ #
83
+ # north, south, east, west: coordinates of bounding box
84
+ # callback: name of javascript function (optional parameter)
85
+ # date: date of earthquakes 'yyyy-MM-dd', optional parameter
86
+ # minMagnitude: minimal magnitude, optional parameter
87
+ # maxRows: maximal number of rows returned (default = 10)
88
+ #
89
+ # Example:
90
+ #
91
+ # api.earthquakes(north: 44.1, south: -9.9, east: -22.4, west: 55.2)
92
+ def earthquakes(parameters = {})
93
+ quakes = query(:earthquakes, parameters)['earthquakes']
94
+ quakes.map{|quake| fix_datetime(quake) }
95
+ end
96
+ QUERY[:earthquakes] = %w[
97
+ north south east west date callback minMagnitude maxRows
98
+ ]
99
+
100
+ # Elevation - Aster Global Digital Elevation Model
101
+ #
102
+ # Parameters: lat,lng
103
+ #
104
+ # Sample area: ca 30m x 30m, between 83N and 65S latitude.
105
+ # Result: a single number giving the elevation in meters according to aster
106
+ # gdem, ocean areas have been masked as "no data" and have been assigned a
107
+ # value of -9999.
108
+ #
109
+ # Example:
110
+ #
111
+ # api.astergdem(lat: 50.01, lng: 10.2)
112
+ def astergdem(parameters = {})
113
+ query(:astergdem, parameters)
114
+ end
115
+ QUERY[:astergdem] = %w[lat lng]
116
+
117
+ # GTOPO30 is a global digital elevation model (DEM) with a horizontal grid
118
+ # spacing of 30 arc seconds (approximately 1 kilometer). GTOPO30 was derived
119
+ # from several raster and vector sources of topographic information.
120
+ #
121
+ # Parameters: lat,lng
122
+ #
123
+ # Sample area: ca 1km x 1km Result : a single number giving the elevation in
124
+ # meters according to gtopo30, ocean areas have been masked as "no data" and
125
+ # have been assigned a value of -9999.
126
+ #
127
+ # Example:
128
+ #
129
+ # api.gtopo30(lat: 50.01, lng: 10.2)
130
+ def gtopo30(parameters = {})
131
+ query(:gtopo30, parameters)
132
+ end
133
+ QUERY[:gtopo30] = %w[lat lng]
134
+
135
+ # Returns the children for a given geonameId. The children are the
136
+ # administrative divisions within an other administrative division. Like the
137
+ # counties (ADM2) in a state (ADM1) or also the countries in a continent.
138
+ #
139
+ # Parameters:
140
+ # geonameId: the geonameId of the parent
141
+ # maxRows: number of rows returned, default is 200
142
+ #
143
+ # Result: returns a list of GeoName records
144
+ #
145
+ # Example:
146
+ #
147
+ # api.children(geonameId: 3175395, maxRows: 5)
148
+ def children(parameters = {})
149
+ query(:children, parameters)
150
+ end
151
+ QUERY[:children] = %w[geonameId maxRows]
152
+
153
+ # Returns all GeoNames higher up in the hierarchy of a place name.
154
+ #
155
+ # Parameters:
156
+ # geonameId: the geonameId for the hierarchy
157
+ #
158
+ # Result: returns a list of GeoName records, ordered by hierarchy level. The
159
+ # top hierarchy (continent) is the first element in the list
160
+ #
161
+ # Example:
162
+ #
163
+ # api.hierarchy(geonameId: 2657896)
164
+ def hierarchy(parameters = {})
165
+ query(:hierarchy, parameters)
166
+ end
167
+ QUERY[:hierarchy] = %w[geonameId]
168
+
169
+ # Returns all neighbours for a place name (currently only available for
170
+ # countries).
171
+ #
172
+ # Parameters:
173
+ # geonameId: the geonameId for the neighbours
174
+ #
175
+ # Result: returns the neighbours of a toponym, currently only implemented for
176
+ # countries
177
+ #
178
+ # Example:
179
+ #
180
+ # api.neighbours(geonameId: 2658434)
181
+ def neighbours(parameters = {})
182
+ query(:neighbours, parameters)
183
+ end
184
+ QUERY[:neighbours] = %w[geonameId]
185
+
186
+ # Returns all siblings of a GeoNames toponym.
187
+ #
188
+ # Parameters:
189
+ # geonameId: the geonameId for the siblings
190
+ #
191
+ # Result: returns a list of GeoNames records that have the same
192
+ # administrative level and the same father
193
+ #
194
+ # Example:
195
+ #
196
+ # api.siblings(geonameId: 3017382)
197
+ def siblings(parameters = {})
198
+ query(:siblings, parameters)['geonames']
199
+ end
200
+ QUERY[:siblings] = %w[geonameId]
201
+
202
+ # Cities and Placenames
203
+ #
204
+ # Returns a list of cities and placenames in the bounding box, ordered by
205
+ # relevancy (capital/population).
206
+ # Placenames close together are filterered out and only the larger name is
207
+ # included in the resulting list.
208
+ #
209
+ # Parameters:
210
+ # north,south,east,west: coordinates of bounding box
211
+ # callback: name of javascript function (optional parameter)
212
+ # lang: language of placenames and wikipedia urls (default = en)
213
+ # maxRows: maximal number of rows returned (default = 10)
214
+ #
215
+ # Example:
216
+ #
217
+ # api.cities(north: 44.1, south: -9.9, east: -22.4, west: 55.2, lang: 'de')
218
+ def cities(parameters = {})
219
+ query(:cities, parameters)['geonames']
220
+ end
221
+ QUERY[:cities] = %w[north south east west callback lang maxRows]
222
+
223
+ # Weather Stations with most recent Weather Observation
224
+ #
225
+ # Returns a list of weather stations with the most recent weather observation.
226
+ #
227
+ # Parameters:
228
+ # north,south,east,west: coordinates of bounding box
229
+ # callback: name of javascript function (optional parameter)
230
+ # maxRows: maximal number of rows returned (default = 10)
231
+ #
232
+ # Example:
233
+ #
234
+ # api.weather(north: 44.1, south: -9.9, east: -22.4, west: 55.2)
235
+ def weather(parameters = {})
236
+ observations = query(:weather, parameters)['weatherObservations']
237
+ observations.map{|observation| fix_datetime(observation) }
238
+ end
239
+ QUERY[:weather] = %w[north south east west callbck maxRows]
240
+
241
+ # Returns the weather station and the most recent weather observation for the
242
+ # ICAO code.
243
+ #
244
+ # Parameters:
245
+ # ICAO: International Civil Aviation Organization (ICAO) code
246
+ # callback: name of javascript function (optional parameter)
247
+ #
248
+ # Example:
249
+ #
250
+ # api.weather_icao(ICAO: 'LSZH')
251
+ def weather_icao(parameters = {})
252
+ weather = query(:weatherIcao, parameters)['weatherObservation']
253
+ fix_datetime(weather)
254
+ end
255
+ QUERY[:weatherIcao] = %w[ICAO callback]
256
+
257
+ # Country information: Capital, Population, Area in square km, Bounding Box
258
+ # of mainland (excluding offshore islands)
259
+
260
+ # Parameters : country (default = all countries)
261
+ # lang: ISO-639-1 language code (en,de,fr,it,es,...) (default = english)
262
+ #
263
+ # Example:
264
+ #
265
+ # api.country_info(lang: 'it', country: 'DE')
266
+ def country_info(parameters = {})
267
+ query(:countryInfo, parameters)["geonames"]
268
+ end
269
+ QUERY[:countryInfo] = %w[country lang]
270
+
271
+ # The ISO country code of any given point.
272
+ #
273
+ # Parameters: lat, lng, type, lang, and radius (buffer in km for closest
274
+ # country in coastal areas)
275
+ #
276
+ # With the parameter type=xml this service returns an xml document with iso
277
+ # country code and country name. The optional parameter lang can be used to
278
+ # specify the language the country name should be in.
279
+ # JSON output is produced with type=JSON, which is the default for this
280
+ # library and will be parsed automatically.
281
+ #
282
+ # Example:
283
+ #
284
+ # api.country_code(lat: 47.03, lng: 10.2)
285
+ def country_code(parameters = {})
286
+ if parameters[:type].to_s =~ /^xml$/i
287
+ query(:countryCode, parameters){|content| return content }
288
+ else
289
+ query(:countryCode, {type: 'JSON'}.merge(parameters))
290
+ end
291
+ end
292
+ QUERY[:countryCode] = %w[lat lng type lang radius]
293
+
294
+ # Country Subdivision / reverse geocoding
295
+ # The ISO country code and the administrative subdivision (state, province, ...) of any given point.
296
+ #
297
+ # Parameters: lat, lng, lang, radius
298
+ #
299
+ # If lang is not given, will return the name in the local language.
300
+ # The radius is measured in km and acts as buffer for closest country in
301
+ # costal areas.
302
+ #
303
+ # Example:
304
+ #
305
+ # api.country_subdivision(lat: 47.03, lng: 10.2)
306
+ #
307
+ # # With the parameters 'radius' and 'maxRows' you get the closest
308
+ # # subdivisions ordered by distance:
309
+ # api.country_subdivision(lat: 47.03, lng: 10.2, maxRows: 10, radius: 40)
310
+ def country_subdivision(parameters = {})
311
+ query(:countrySubdivision, parameters)
312
+ end
313
+ QUERY[:countrySubdivision] = %w[lat lng lang radius]
314
+
315
+ # Ocean / reverse geocoding
316
+ # Returns the name of the ocean or sea for the given latitude/longitude.
317
+ #
318
+ # Parameters : lat,lng
319
+ #
320
+ # Example:
321
+ #
322
+ # api.ocean(lat: 40.78343, lng: -43.96625)
323
+ def ocean(parameters = {})
324
+ query(:ocean, parameters)["ocean"]
325
+ end
326
+ QUERY[:ocean] = %w[lat lng]
327
+
328
+ # Neighbourhood / reverse geocoding
329
+ # The neighbourhood for US cities. Data provided by Zillow under cc-by-sa
330
+ # license.
331
+ #
332
+ # Parameters: lat,lng
333
+ #
334
+ # Example:
335
+ #
336
+ # api.neighbourhood(lat: 40.78343, lng: -73.96625)
337
+ def neighbourhood(parameters = {})
338
+ query(:neighbourhood, parameters)["neighbourhood"]
339
+ end
340
+ QUERY[:neighbourhood] = %w[lat lng]
341
+
342
+ # Elevation - SRTM3
343
+ #
344
+ # Shuttle Radar Topography Mission (SRTM) elevation data. SRTM consisted of a
345
+ # specially modified radar system that flew onboard the Space Shuttle
346
+ # Endeavour during an 11-day mission in February of 2000. The dataset covers
347
+ # land areas between 60 degrees north and 56 degrees south.
348
+ # This web service is using SRTM3 data with data points located every
349
+ # 3-arc-second (approximately 90 meters) on a latitude/longitude grid.
350
+ #
351
+ # Parameters : lat,lng;
352
+ # sample area: ca 90m x 90m Result : a single number giving the elevation in
353
+ # meters according to srtm3, ocean areas have been masked as "no data" and
354
+ # have been assigned a value of -32768.
355
+ #
356
+ # Example:
357
+ #
358
+ # api.srtm3(lat: 50.01, lng: 10.2)
359
+ def srtm3(parameters = {})
360
+ query(:srtm3, parameters)
361
+ end
362
+ QUERY[:srtm3] = %w[lat lng]
363
+
364
+ # The timezone at the lat/lng with gmt offset (1. January) and dst offset (1. July)
365
+ #
366
+ # Parameters: lat, lng, radius (buffer in km for closest timezone in coastal areas)
367
+ # needs username
368
+ #
369
+ # If you want to work with the returned time, I recommend the tzinfo library,
370
+ # which can handle the timezoneId. In order to keep dependencies low and the
371
+ # code flexible and fast, we won't do any further handling here.
372
+ #
373
+ # Example:
374
+ #
375
+ # api.timezone(lat: 47.01, lng: 10.2)
376
+ def timezone(parameters = {})
377
+ query(:timezone, parameters)
378
+ end
379
+ QUERY[:timezone] = %w[lat lng radius]
380
+
381
+ # Find nearby toponym
382
+ #
383
+ # Parameters: lat, lng, featureClass, featureCode,
384
+ # radius: radius in km (optional)
385
+ # maxRows: max number of rows (default 10)
386
+ # style: SHORT, MEDIUM, LONG, FULL (default = MEDIUM), verbosity result.
387
+ #
388
+ # Example:
389
+ #
390
+ # api.find_nearby(lat: 47.3, lng: 9)
391
+ def find_nearby(parameters = {})
392
+ query(:findNearby, parameters)["geonames"]
393
+ end
394
+ QUERY[:findNearby] = %w[
395
+ lat lng featureClass featureCode radius maxRows style
396
+ ]
397
+
398
+ # Returns the most detailed information available for the lat/lng query.
399
+ # It is a combination of several services. Example:
400
+ # In the US it returns the address information.
401
+ # In other countries it returns the hierarchy service: http://ws.geonames.org/extendedFindNearby?lat=47.3&lng=9
402
+ # On oceans it returns the ocean name.
403
+ #
404
+ # Parameters : lat,lng
405
+ #
406
+ # Example:
407
+ #
408
+ # api.extended_find_nearby(lat: 47.3, lng: 9)
409
+ def extended_find_nearby(parameters = {})
410
+ raise(NotImplementedError, "XML queries haven't been implemented.")
411
+ query(:extendedFindNearby, parameters)
412
+ end
413
+ QUERY[:extendedFindNearby] = %w[lat lng]
414
+
415
+ # Find nearby populated place / reverse geocoding
416
+ # Returns the closest populated place for the lat/lng query.
417
+ # The unit of the distance element is 'km'.
418
+ #
419
+ # Parameters:
420
+ # lat, lng,
421
+ # radius: radius in km (optional),
422
+ # maxRows: max number of rows (default 10),
423
+ # style: SHORT, MEDIUM, LONG, FULL (default = MEDIUM), verbosity of result
424
+ #
425
+ # Example:
426
+ #
427
+ # api.find_nearby_place_name(lat: 47.3, lng: 9)
428
+ def find_nearby_place_name(parameters = {})
429
+ query(:findNearbyPlaceName, parameters)["geonames"]
430
+ end
431
+ QUERY[:findNearbyPlaceName] = %w[lat lng radius maxRows style]
432
+
433
+ # List of nearby postalcodes and places for the lat/lng query.
434
+ # The result is sorted by distance.
435
+ #
436
+ # This service comes in two flavors. You can either pass the lat/long or a
437
+ # postalcode/placename.
438
+ #
439
+ # Parameters:
440
+ #
441
+ # lat, lng, radius (in km),
442
+ # maxRows (default = 5),
443
+ # style (verbosity : SHORT,MEDIUM,LONG,FULL),
444
+ # country (default = all countries),
445
+ # localCountry (restrict search to local country in border areas)
446
+ #
447
+ # or
448
+ #
449
+ # postalcode, country, radius (in Km), maxRows (default = 5)
450
+ #
451
+ # Example:
452
+ #
453
+ # api.find_nearby_postal_codes(lat: 47, lng: 9)
454
+ # api.find_nearby_postal_codes(postalcode: 8775, country: 'CH', radius: 10)
455
+ def find_nearby_postal_codes(parameters = {})
456
+ query(:findNearbyPostalCodes, parameters)["postalCodes"]
457
+ end
458
+ QUERY[:findNearbyPostalCodes] = %w[
459
+ lat lng radius maxRows style country localCountry postalcode country radius
460
+ ]
461
+
462
+ # Returns the nearest street segments for the given latitude/longitude, this
463
+ # service is only available for the US.
464
+ #
465
+ # @param [Float] latitude Latitude
466
+ # @param [Float] longitude Longitude
467
+ #
468
+ # @return [Array] An Array containing zero or more street segments.
469
+ #
470
+ # A street segment has following keys:
471
+ # "adminCode1": Identifier of state.
472
+ # "adminCode2": Area code.
473
+ # "adminName1": Name of state.
474
+ # "adminName2": Name of province.
475
+ # "countryCode": Name of country (usually "US")
476
+ # "distance": Distance of street to given coordinates in km.
477
+ # "fraddl": From address left.
478
+ # "fraddr": From address right.
479
+ # "line": A string with lng/lat points, comma separated.
480
+ # "mtfcc": MAF/TIGER Feature class code.
481
+ # "name:" Name of the street.
482
+ # "postalcode": Postal code of the address.
483
+ # "toaddl": To address left.
484
+ # "toaddr": To address right.
485
+ #
486
+ # @example
487
+ # api.find_nearby_streets(37.451, -122.18)
488
+ def find_nearby_streets(latitude, longitude)
489
+ [*query(:findNearbyStreets, lat: latitude, lng: longitude)['streetSegment']]
490
+ end
491
+ QUERY[:findNearbyStreets] = %w[lat lng]
492
+
493
+
494
+ # Find nearby street segments on OpenStreetMap for the given
495
+ # latitude/longitude.
496
+ #
497
+ # @param [Float, String] latitude
498
+ # @param [Float, String] longitude
499
+ #
500
+ # @example
501
+ # api.find_nearby_streets_osm(37.451, -122.18)
502
+ def find_nearby_streets_osm(latitude, longitude)
503
+ query(:findNearbyStreetsOSM, lat: latitude, lng: longitude)
504
+ end
505
+ QUERY[:findNearbyStreetsOSM] = %w[lat lng]
506
+
507
+ # Weather Station with most recent weather observation / reverse geocoding
508
+ # needs username
509
+ #
510
+ # Webservice Type : REST
511
+ # Url : ws.geonames.org/findNearByWeatherJSON?
512
+ # Parameters :
513
+ # lat,lng : the service will return the station closest to this given point (reverse geocoding)
514
+ # callback : name of javascript function (optional parameter)
515
+ #
516
+ # Result : returns a weather station with the most recent weather observation
517
+ #
518
+ # Example http://ws.geonames.org/findNearByWeatherJSON?lat=43&lng=-2
519
+ def find_near_by_weather(parameters = {})
520
+ query(:findNearByWeather, parameters)
521
+ end
522
+ QUERY[:findNearByWeather] = %w[lat lng]
523
+
524
+ # Find nearby Wikipedia Entries / reverse geocoding
525
+ #
526
+ # This service comes in two flavors. You can either pass the lat/long or a postalcode/placename.
527
+ # Webservice Type : XML,JSON or RSS
528
+ # Url : ws.geonames.org/findNearbyWikipedia?
529
+ # ws.geonames.org/findNearbyWikipediaJSON?
530
+ # ws.geonames.org/findNearbyWikipediaRSS?
531
+ # Parameters :
532
+ # lang : language code (around 240 languages) (default = en)
533
+ # lat,lng, radius (in km), maxRows (default = 5),country (default = all countries)
534
+ # or
535
+ # postalcode,country, radius (in Km), maxRows (default = 5)
536
+ # Result : returns a list of wikipedia entries as xml document
537
+ # Example:
538
+ # http://ws.geonames.org/findNearbyWikipedia?lat=47&lng=9
539
+ # or
540
+ # ws.geonames.org/findNearbyWikipedia?postalcode=8775&country=CH&radius=10
541
+ def find_nearby_wikipedia(parameters = {})
542
+ query(:findNearbyWikipedia, parameters)
543
+ end
544
+ QUERY[:findNearbyWikipedia] = %w[
545
+ lang lat lng maxRows country postalcode country radius
546
+ ]
547
+
548
+ # Find nearest Address
549
+ #
550
+ # Finds the nearest street and address for a given lat/lng pair.
551
+ # Url : ws.geonames.org/findNearestAddress?
552
+ # Parameters : lat,lng;
553
+ # Restriction : this webservice is only available for the US.
554
+ # Result : returns the nearest address for the given latitude/longitude, the street number is an 'educated guess' using an interpolation of street number at the end of a street segment.
555
+ # Example http://ws.geonames.org/findNearestAddress?lat=37.451&lng=-122.18
556
+ #
557
+ # This service is also available in JSON format :
558
+ # http://ws.geonames.org/findNearestAddressJSON?lat=37.451&lng=-122.18
559
+ def find_nearest_address(parameters = {})
560
+ query(:findNearestAddress, parameters)
561
+ end
562
+ QUERY[:findNearestAddress] = %w[lat lng]
563
+
564
+ # Find nearest Intersection
565
+ #
566
+ # Finds the nearest street and the next crossing street for a given lat/lng pair.
567
+ # Url : ws.geonames.org/findNearestIntersection?
568
+ # Parameters : lat,lng;
569
+ # Restriction : this webservice is only available for the US.
570
+ # Result : returns the nearest intersection for the given latitude/longitude
571
+ # Example http://ws.geonames.org/findNearestIntersection?lat=37.451&lng=-122.18
572
+ #
573
+ # This service is also available in JSON format :
574
+ # http://ws.geonames.org/findNearestIntersectionJSON?lat=37.451&lng=-122.18
575
+ def find_nearest_intersection(parameters = {})
576
+ query(:findNearestIntersection, parameters)
577
+ end
578
+ QUERY[:findNearestIntersection] = %w[lat lng]
579
+
580
+ # Find nearest street and crossing for a given latitude/longitude pair on
581
+ # OpenStreetMap.
582
+ #
583
+ # @param [Float] latitude
584
+ # @param [Float] longitude
585
+ #
586
+ # @example
587
+ # api.find_nearest_intersection_osm(37.451, -122.18)
588
+ def find_nearest_intersection_osm(parameters = {})
589
+ query(:findNearestIntersectionOSM, parameters)
590
+ end
591
+ QUERY[:findNearestIntersectionOSM] = %w[lat lng]
592
+
593
+ # Postal code country info
594
+ #
595
+ # @return [Array] Countries for which postal code geocoding is available.
596
+ #
597
+ # @example
598
+ # api.postal_code_country_info
599
+ def postal_code_country_info(parameters = {})
600
+ query(:postalCodeCountryInfo, {})['geonames']
601
+ end
602
+ QUERY[:postalCodeCountryInfo] = []
603
+
604
+ # Placename lookup with postalcode
605
+ #
606
+ #
607
+ # @param [Hash] parameters
608
+ # @option parameters [String, Fixnum] :postalcode
609
+ # @option parameters [String] :country
610
+ # @option parameters [Fixnum] :maxRows (20)
611
+ # @option parameters [String] :callback
612
+ # @option parameters [String] :charset ('UTF-8')
613
+ #
614
+ # @return [Array] List of places for the given postalcode.
615
+ #
616
+ # @example
617
+ # api.postal_code_lookup(postalcode: 6600, country: 'AT')
618
+ def postal_code_lookup(parameters = {})
619
+ query(:postalCodeLookup, parameters)
620
+ end
621
+ QUERY[:postalCodeLookup] = %w[postalcode country maxRows, callback charset]
622
+
623
+ # Postal Code Search
624
+ # Returns a list of postal codes and places for the placename/postalcode query.
625
+ #
626
+ # For the US the first returned zip code is determined using zip code area
627
+ # shapes, the following zip codes are based on the centroid. For all other
628
+ # supported countries all returned postal codes are based on centroids.
629
+ #
630
+ # Parameter Value Description
631
+ # postalcode string (postalcode or placename required) postal code
632
+ # postalcode_startsWith string the first characters or letters of a postal code
633
+ # placename string (postalcode or placename required) all fields : placename,postal code, country, admin name (Important:urlencoded utf8)
634
+ # placename_startsWith string the first characters of a place name
635
+ # country string : country code, ISO-3166 (optional) Default is all countries.
636
+ # countryBias string records from the countryBias are listed first
637
+ # maxRows integer (optional) the maximal number of rows in the document returned by the service. Default is 10
638
+ # style string SHORT,MEDIUM,LONG,FULL (optional) verbosity of returned xml document, default = MEDIUM
639
+ # operator string AND,OR (optional) the operator 'AND' searches for all terms in the placename parameter, the operator 'OR' searches for any term, default = AND
640
+ # charset string (optional) default is 'UTF8', defines the encoding used for the document returned by the web service.
641
+ # isReduced true or false (optional) default is 'false', when set to 'true' only the UK outer codes are returned. Attention: the default value on the commercial servers is currently set to 'true'. It will be changed later to 'false'.
642
+ #
643
+ # @example
644
+ # api.postal_code_search(postalcode: 9011, maxRows: 10)
645
+ def postal_code_search(parameters = {})
646
+ query(:postalCodeSearch, parameters)
647
+ end
648
+ QUERY[:postalCodeSearch] = %w[
649
+ postalcode postalcode_starts placename placename_starts country countryBias
650
+ maxRows style operator charset isReduced
651
+ ]
652
+
653
+ # Returns the names found for the searchterm as xml, json, or rdf document,
654
+ # the search is using the AND operator.
655
+ #
656
+ # @param [Hash] parameters
657
+ # @option parameters [String] :q
658
+ # search over all attributes of a place, place name, country name,
659
+ # continent, admin codes, ...
660
+ # @option parameters [String] :name
661
+ # place name only
662
+ # @option parameters [String] :name_equals
663
+ # exact place name
664
+ # @option parameters [String] :name_startsWith
665
+ # place name starts with given characters
666
+ # @option parameters [Fixnum] :maxRows (100)
667
+ # maximum number of results, up to 1000
668
+ # @option parameters [Fixnum] :startRow (0)
669
+ # used for paging results.
670
+ # @option parameters [String, Array] :country
671
+ # Country code, ISO-3166 (optional). Default is all countries. May have
672
+ # more than one country as an Array.
673
+ # @option parameters [String] :countryBias
674
+ # records from this country will be listed first.
675
+ # @option parameters [String] :continentCode
676
+ # AF,AS,EU,NA,OC,SA,AN (optional) restricts the search to the given
677
+ # continent.
678
+ # @option parameters [String] :adminCode1
679
+ # code of administrative subdivision
680
+ # @option parameters [String] :adminCode2
681
+ # code of administrative subdivision
682
+ # @option parameters [String] :adminCode3
683
+ # code of administrative subdivision
684
+ # @option parameters [String, Array] :featureClass
685
+ # one or more feature class codes, explanation at
686
+ # http://forum.geonames.org/gforum/posts/list/130.page
687
+ # @option parameters [String, Array] :featureCode
688
+ # one or more feature class codes, explanation at
689
+ # http://forum.geonames.org/gforum/posts/list/130.page
690
+ # @option parameters [String] :lang ('en')
691
+ # ISO-636 2-letter language code; en, de, fr, it, es, ...
692
+ # place names and country names will be returned in the specified language.
693
+ # Feature classes and codes are only available in English and Bulgarian.
694
+ # @option parameters [String] :type ('json')
695
+ # format of returned document.
696
+ # @option parameters [String] :style ('MEDIUM')
697
+ # verbosity of returned document.
698
+ # @option parameters [String] :isNameRequired (false)
699
+ # At least one of the search term needs to be part of the place name.
700
+ # Example: A normal seach for Berlin will return all places within the
701
+ # state of Berlin. If we only want to find places with 'Berlin' in the name
702
+ # we se the parameter isNameRequired to `true`. The difference to the
703
+ # :name_equals parameter is that this will allow searches for 'Berlin,
704
+ # Germany' as only one search term needs to be part of the name.
705
+ # @option parameters [String] :tag
706
+ # search for toponyms tagged with the given tag.
707
+ # @option parameters [String] :charset ('UTF8')
708
+ # encoding of returned document, this wrapper only handles UTF8 for now.
709
+ #
710
+ # @example
711
+ # api.search(q: 'london', maxRows: 10)
712
+ # api.search(q: 'london', maxRows: 10, type: 'rdf')
713
+ # api.search(q: 'skiresort')
714
+ # api.search(q: 'tags:skiresort')
715
+ # api.search(q: 'tags:skiresort@marc')
716
+ #
717
+ # With the parameter `type: 'rdf'` the search service returns the result in RDF
718
+ # format defined by the GeoNames Semantic Web Ontology.
719
+ #
720
+ #
721
+ # Tags
722
+ # GeoNames is using a simple tagging system. Every user can tag places. In
723
+ # contrast to the feature codes and feature classes which are one-dimensional
724
+ # (a place name can only have one feature code) several tags can be used for
725
+ # each place name. It is an additional categorization mechanism where the
726
+ # simple classification with feature codes is not sufficient.
727
+ #
728
+ # I have tagged a place with the tag 'skiresort'. You can search for tags
729
+ # with the search: `api.search(q: 'skiresort')` If you only want to search
730
+ # for a tag and not for other occurences of the term (in case you tag
731
+ # something with 'spain' for example), then you add the attribute 'tags:' to
732
+ # the search term: `api.search(q: 'tags:skiresort')`
733
+ #
734
+ # And if you want to search for tags of a particular user (or your own) then
735
+ # you append '@username' to the tag. Like this:
736
+ # `api.search(q: 'tags:skiresort@marc')
737
+ def search(parameters = {})
738
+ query(:search, parameters)['geonames']
739
+ end
740
+ QUERY[:search] = %w[
741
+ q name name_equals name_startsWith maxRows startRow country countryBias
742
+ continentCode adminCode1 adminCode2 adminCode3 featureClass featureCode
743
+ lang type style isNameRequired tag operator charset
744
+ ]
745
+
746
+ # Wikipedia articles within a bounding box
747
+ #
748
+ # @param [Hash] parameters
749
+ # @option parameters [Float] :south Southern latitude
750
+ # @option parameters [Float] :north Northern latitude
751
+ # @option parameters [Float] :east Eastern longitude
752
+ # @option parameters [Float] :west Western longitude
753
+ # @option parameters [String] :lang ('en') language
754
+ # @option parameters [Fixnum] :maxRows ('10') maximum number of results
755
+ #
756
+ # @return [Array] The Wikipedia entries found.
757
+ #
758
+ # @example
759
+ # api.wikipedia_bounding_box(north: 44.1, south: -9.9, east: -22.4, west: 55.2)
760
+ def wikipedia_bounding_box(parameters = {})
761
+ [*query(:wikipediaBoundingBox, parameters)['geonames']]
762
+ end
763
+ QUERY[:wikipediaBoundingBox] = %w[south north east west lang maxRows]
764
+
765
+ # Wikipedia Fulltext Search
766
+ #
767
+ # @param [Hash] parameters
768
+ # @option parameters [String] :q
769
+ # place name
770
+ # @option parameters [String] :title (false)
771
+ # search in the wikipedia title (optional, true/false)
772
+ # @option parameters [String] :lang ('en')
773
+ # language
774
+ # @option parameters [Fixnum] :maxRows (10)
775
+ # maximum number of results
776
+ #
777
+ # @return [Array] The Wikipedia entries found.
778
+ #
779
+ # @example
780
+ # api.wikipedia_search(q: 'London', maxRows: 10, lang: 'en', title: true)
781
+ # api.wikipedia_search(q: '秋葉原')
782
+ def wikipedia_search(parameters = {})
783
+ params = parameters.dup
784
+ params[:title] = '' if params[:title] # weird?
785
+ [*query(:wikipediaSearch, params)['geonames']]
786
+ end
787
+ QUERY[:wikipediaSearch] = %w[q title lang maxRows]
788
+ end
metadata ADDED
@@ -0,0 +1,92 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geonames-wrapper
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Michael Fellinger
8
+ - Marcello Barnaba
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-01-08 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: addressable
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: '2.3'
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: '2.3'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - '>='
40
+ - !ruby/object:Gem::Version
41
+ version: '0'
42
+ - !ruby/object:Gem::Dependency
43
+ name: yard
44
+ requirement: !ruby/object:Gem::Requirement
45
+ requirements:
46
+ - - '>='
47
+ - !ruby/object:Gem::Version
48
+ version: '0'
49
+ type: :development
50
+ prerelease: false
51
+ version_requirements: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - '>='
54
+ - !ruby/object:Gem::Version
55
+ version: '0'
56
+ description: Bare-metal wrapper for GeoNames JSON Web Service API. Simple and effective.
57
+ email:
58
+ - m.fellinger@gmail.com
59
+ - vjt@openssl.it
60
+ executables: []
61
+ extensions: []
62
+ extra_rdoc_files: []
63
+ files:
64
+ - Gemfile
65
+ - Gemfile.lock
66
+ - README.md
67
+ - geonames-wrapper.gemspec
68
+ - lib/geonames.rb
69
+ homepage: http://github.com/vjt/geonames
70
+ licenses: []
71
+ metadata: {}
72
+ post_install_message:
73
+ rdoc_options: []
74
+ require_paths:
75
+ - lib
76
+ required_ruby_version: !ruby/object:Gem::Requirement
77
+ requirements:
78
+ - - '>='
79
+ - !ruby/object:Gem::Version
80
+ version: 1.9.0
81
+ required_rubygems_version: !ruby/object:Gem::Requirement
82
+ requirements:
83
+ - - '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ requirements: []
87
+ rubyforge_project:
88
+ rubygems_version: 2.1.11
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: GeoNames JSON Web Service Wrapper
92
+ test_files: []