geocoder 0.9.13 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of geocoder might be problematic. Click here for more details.
- data/CHANGELOG.rdoc +16 -7
- data/README.rdoc +116 -51
- data/bin/geocode +5 -0
- data/lib/geocoder.rb +30 -43
- data/lib/geocoder/calculations.rb +4 -21
- data/lib/geocoder/cli.rb +111 -0
- data/lib/geocoder/configuration.rb +6 -7
- data/lib/geocoder/lookups/base.rb +36 -9
- data/lib/geocoder/lookups/bing.rb +33 -0
- data/lib/geocoder/lookups/google.rb +4 -0
- data/lib/geocoder/lookups/yahoo.rb +5 -2
- data/lib/geocoder/lookups/yandex.rb +39 -0
- data/lib/geocoder/models/base.rb +5 -1
- data/lib/geocoder/results/base.rb +16 -0
- data/lib/geocoder/results/bing.rb +48 -0
- data/lib/geocoder/results/freegeoip.rb +10 -3
- data/lib/geocoder/results/geocoder_ca.rb +14 -12
- data/lib/geocoder/results/google.rb +15 -2
- data/lib/geocoder/results/yahoo.rb +10 -2
- data/lib/geocoder/results/yandex.rb +48 -0
- data/lib/geocoder/stores/active_record.rb +2 -7
- data/lib/geocoder/stores/base.rb +2 -10
- data/lib/geocoder/version.rb +3 -0
- data/test/fixtures/bing_madison_square_garden.json +40 -0
- data/test/fixtures/bing_no_results.json +16 -0
- data/test/fixtures/bing_reverse.json +42 -0
- data/test/fixtures/yandex_invalid_key.json +1 -0
- data/test/fixtures/yandex_kremlin.json +48 -0
- data/test/fixtures/yandex_no_results.json +16 -0
- data/test/geocoder_test.rb +58 -8
- data/test/test_helper.rb +39 -3
- metadata +69 -58
- data/VERSION +0 -1
- data/lib/geocoder/stores/active_record_legacy.rb +0 -62
data/CHANGELOG.rdoc
CHANGED
@@ -2,6 +2,15 @@
|
|
2
2
|
|
3
3
|
Per-release changes to Geocoder.
|
4
4
|
|
5
|
+
== 1.0.0 (2011 May 9)
|
6
|
+
|
7
|
+
* Add command line interface.
|
8
|
+
* Add support for local proxy (thanks github.com/Olivier).
|
9
|
+
* Add support for Yandex.ru geocoding service.
|
10
|
+
* Add support for Bing geocoding service (thanks github.com/astevens).
|
11
|
+
* Fix single table inheritance bug (reported by github.com/enrico).
|
12
|
+
* Fix bug when Google result supplies no city (thanks github.com/jkeen).
|
13
|
+
|
5
14
|
== 0.9.13 (2011 Apr 11)
|
6
15
|
|
7
16
|
* Fix "can't find special index: 2d" error when using Mongoid with Ruby 1.8.
|
@@ -23,9 +32,9 @@ Per-release changes to Geocoder.
|
|
23
32
|
* Add support for Geocoder.ca geocoding service.
|
24
33
|
* Add +bearing+ attribute to objects returned by geo-aware queries (thanks github.com/matellis).
|
25
34
|
* Add config setting: language.
|
26
|
-
* Add config settings: use_https
|
27
|
-
* DEPRECATION: Geocoder.search now returns an array instead of a single result.
|
28
|
-
* DEPRECATION: obj.nearbys second argument is now an options hash (instead of units). Please change <tt>obj.nearbys(20, :km)</tt> to: <tt>obj.nearbys(20, :units => :km)</tt>.
|
35
|
+
* Add config settings: +use_https+, +google_api_key+ (thanks github.com/svesely).
|
36
|
+
* DEPRECATION: <tt>Geocoder.search</tt> now returns an array instead of a single result.
|
37
|
+
* DEPRECATION: <tt>obj.nearbys</tt> second argument is now an options hash (instead of units). Please change <tt>obj.nearbys(20, :km)</tt> to: <tt>obj.nearbys(20, :units => :km)</tt>.
|
29
38
|
|
30
39
|
== 0.9.10 (2011 Mar 9)
|
31
40
|
|
@@ -42,15 +51,15 @@ Per-release changes to Geocoder.
|
|
42
51
|
* Gem now works outside of Rails.
|
43
52
|
* DEPRECATION: +fetch_coordinates+ no longer takes an argument.
|
44
53
|
* DEPRECATION: +fetch_address+ no longer takes an argument.
|
45
|
-
* DEPRECATION: Geocoder.search now returns a single result instead of an array.
|
54
|
+
* DEPRECATION: <tt>Geocoder.search</tt> now returns a single result instead of an array.
|
46
55
|
* DEPRECATION: <tt>fetch_coordinates!</tt> has been superceded by +geocode+ (then save your object manually).
|
47
56
|
* DEPRECATION: <tt>fetch_address!</tt> has been superceded by +reverse_geocode+ (then save your object manually).
|
48
57
|
* Fix: don't die when trying to get coordinates with a nil address (github.com/zmack).
|
49
58
|
|
50
59
|
== 0.9.8 (2011 Feb 8)
|
51
60
|
|
52
|
-
* Include geocode:all Rake task in gem (was missing!).
|
53
|
-
* Add Geocoder.search for access to Google's full response.
|
61
|
+
* Include <tt>geocode:all</tt> Rake task in gem (was missing!).
|
62
|
+
* Add <tt>Geocoder.search</tt> for access to Google's full response.
|
54
63
|
* Add ability to configure Google connection timeout.
|
55
64
|
* Emit warnings on Google connection problems and errors.
|
56
65
|
* Refactor: insert Geocoder into ActiveRecord via Railtie.
|
@@ -133,7 +142,7 @@ Per-release changes to Geocoder.
|
|
133
142
|
|
134
143
|
== 0.8.1 (2009 Oct 8)
|
135
144
|
|
136
|
-
* Extract XML-fetching code from Geocoder.search and place in Geocoder._fetch_xml (for ease of mocking).
|
145
|
+
* Extract XML-fetching code from <tt>Geocoder.search</tt> and place in Geocoder._fetch_xml (for ease of mocking).
|
137
146
|
* Add tests for coordinate-fetching instance methods.
|
138
147
|
|
139
148
|
== 0.8.0 (2009 Oct 1)
|
data/README.rdoc
CHANGED
@@ -208,68 +208,121 @@ Every <tt>Geocoder::Result</tt> object, +result+, provides the following data:
|
|
208
208
|
* <tt>result.coordinates</tt> - array of the above two
|
209
209
|
* <tt>result.address</tt> - string
|
210
210
|
* <tt>result.city</tt> - string
|
211
|
+
* <tt>result.state</tt> - string
|
212
|
+
* <tt>result.state_code</tt> - string
|
211
213
|
* <tt>result.postal_code</tt> - string
|
212
214
|
* <tt>result.country_name</tt> - string
|
213
215
|
* <tt>result.country_code</tt> - string
|
214
216
|
|
215
|
-
|
217
|
+
If you're familiar with the results returned by the geocoding service you're using you can access even more data, but you'll need to be familiar with the particular <tt>Geocoder::Result</tt> object you're using and the structure of your geocoding service's responses. (See below for links to geocoding service documentation.)
|
216
218
|
|
217
219
|
|
218
220
|
== Geocoding Services
|
219
221
|
|
220
|
-
By default Geocoder uses Google's geocoding API to fetch coordinates and addresses. However
|
222
|
+
By default Geocoder uses Google's geocoding API to fetch coordinates and street addresses (FreeGeoIP is used for IP address info). However there are several other APIs supported, as well as a variety of settings. Please see the listing and comparison below for details on specific geocoding services (not all settings are supported by all services). The configuration options are:
|
221
223
|
|
222
224
|
# config/initializers/geocoder.rb
|
223
|
-
Geocoder::Configuration.lookup = :yahoo
|
224
|
-
|
225
|
-
Street address geocoding services currently supported (valid settings for the above):
|
226
|
-
|
227
|
-
* Google: <tt>:google</tt>
|
228
|
-
* Yahoo: <tt>:yahoo</tt>
|
229
|
-
* Geocoder.ca: <tt>:geocoder_ca</tt> (US and Canada only)
|
230
|
-
|
231
|
-
Note that the result objects returned by different geocoding services all implement the methods listed above. Beyond that, however, you must be familiar with your particular subclass of <tt>Geocoder::Result</tt> and the geocoding service's result structure:
|
232
225
|
|
233
|
-
|
234
|
-
|
235
|
-
* Geocoder.ca: (???)
|
236
|
-
* FreeGeoIP: http://github.com/fiorix/freegeoip/blob/master/README.rst
|
237
|
-
|
238
|
-
=== API Keys
|
239
|
-
|
240
|
-
To use your Google API key or Yahoo app ID:
|
226
|
+
# geocoding service (see below for supported options):
|
227
|
+
Geocoder::Configuration.lookup = :yahoo
|
241
228
|
|
229
|
+
# to use an API key:
|
242
230
|
Geocoder::Configuration.api_key = "..."
|
243
231
|
|
244
|
-
|
245
|
-
|
246
|
-
* Yahoo: https://developer.apps.yahoo.com/wsregapp
|
247
|
-
* Google: http://code.google.com/apis/maps/signup.html
|
248
|
-
|
249
|
-
=== Timeout
|
250
|
-
|
251
|
-
You can set the timeout used for connections to the geocoding service. The default is 3 seconds but if you want to set it to 5, for example, put the following in an initializer:
|
252
|
-
|
232
|
+
# geocoding service request timeout, in seconds (default 3):
|
253
233
|
Geocoder::Configuration.timeout = 5
|
254
234
|
|
255
|
-
|
256
|
-
|
257
|
-
You can set the language used for reverse geocoding results to German, for example, by setting the following:
|
235
|
+
# use HTTPS for geocoding service connections:
|
236
|
+
Geocoder::Configuration.use_https = true
|
258
237
|
|
238
|
+
# language to use (for search queries and reverse geocoding):
|
259
239
|
Geocoder::Configuration.language = :de
|
260
240
|
|
261
|
-
|
262
|
-
|
263
|
-
|
241
|
+
# use a proxy to access the service:
|
242
|
+
Geocoder::Configuration.http_proxy = "127.4.4.1"
|
243
|
+
Geocoder::Configuration.https_proxy = "127.4.4.2" # only if HTTPS is needed
|
264
244
|
|
265
|
-
|
266
|
-
|
267
|
-
Geocoder::Configuration.
|
268
|
-
|
269
|
-
Note that currently the only service that supports HTTPS is Google.
|
245
|
+
# caching (see below for details)
|
246
|
+
Geocoder::Configuration.cache = Redis.new
|
247
|
+
Geocoder::Configuration.cache_prefix = "..."
|
270
248
|
|
271
249
|
|
272
|
-
|
250
|
+
=== Listing and Comparison
|
251
|
+
|
252
|
+
The following is a comparison of the supported geocoding APIs. The "Limitations" listed for each are a very brief and incomplete summary of some special limitations beyond basic data source attribution. Please read the official Terms of Service for a service before using it.
|
253
|
+
|
254
|
+
==== Google (<tt>:google</tt>)
|
255
|
+
|
256
|
+
API key:: optional (required for Premier)
|
257
|
+
Key signup:: http://code.google.com/apis/maps/signup.html
|
258
|
+
Quota:: 2,500 requests/day, 100,000 with Google Maps API Premier
|
259
|
+
Region:: world
|
260
|
+
SSL support:: yes
|
261
|
+
Languages:: ar, eu, bg, bn, ca, cs, da, de, el, en, en-AU, en-GB, es, eu, fa, fi, fil, fr, gl, gu, hi, hr, hu, id, it, iw, ja, kn, ko, lt, lv, ml, mr, nl, no, pl, pt, pt-BR, pt-PT, ro, ru, sk, sl, sr, sv, tl, ta, te, th, tr, uk, vi, zh-CN, zh-TW (see http://spreadsheets.google.com/pub?key=p9pdwsai2hDMsLkXsoM05KQ&gid=1)
|
262
|
+
Documentation:: http://code.google.com/apis/maps/documentation/geocoding/#JSON
|
263
|
+
Terms of Service:: http://code.google.com/apis/maps/terms.html#section_10_12
|
264
|
+
Limitations:: "You must not use or display the Content without a corresponding Google map, unless you are explicitly permitted to do so in the Maps APIs Documentation, or through written permission from Google." "You must not pre-fetch, cache, or store any Content, except that you may store: (i) limited amounts of Content for the purpose of improving the performance of your Maps API Implementation..."
|
265
|
+
|
266
|
+
==== Yahoo (<tt>:yahoo</tt>)
|
267
|
+
|
268
|
+
API key:: optional in development (required for production apps)
|
269
|
+
Key signup:: https://developer.apps.yahoo.com/wsregapp
|
270
|
+
Quota:: 50,000 requests/day, more available by special arrangement
|
271
|
+
Region:: world
|
272
|
+
SSL support:: no
|
273
|
+
Languages:: ?
|
274
|
+
Documentation:: http://developer.yahoo.com/geo/placefinder/guide/responses.html
|
275
|
+
Terms of Service:: http://info.yahoo.com/legal/us/yahoo/maps/mapsapi/mapsapi-2141.html
|
276
|
+
Limitations:: "YOU SHALL NOT... (viii) store or allow end users to store map imagery, map data or geocoded location information from the Yahoo! Maps APIs for any future use; (ix) use the stand-alone geocoder for any use other than displaying Yahoo! Maps or displaying points on Yahoo! Maps;"
|
277
|
+
|
278
|
+
==== Bing (<tt>:bing</tt>)
|
279
|
+
|
280
|
+
API key:: required
|
281
|
+
Key signup:: http://www.bingmapsportal.com
|
282
|
+
Quota:: 50,000 requests/24 hrs
|
283
|
+
Region:: world
|
284
|
+
SSL support:: no
|
285
|
+
Languages:: ?
|
286
|
+
Documentation:: http://msdn.microsoft.com/en-us/library/ff701715.aspx
|
287
|
+
Terms of Service:: http://www.microsoft.com/maps/product/terms.html
|
288
|
+
Limitations:: No country codes or state names. Must be used on "public-facing, non-password protected web sites," "in conjunction with Bing Maps or an application that integrates Bing Maps."
|
289
|
+
|
290
|
+
==== Yandex (<tt>:yandex</tt>)
|
291
|
+
|
292
|
+
API key:: required
|
293
|
+
Key signup:: http://api.yandex.ru/maps/intro/concepts/intro.xml#apikey
|
294
|
+
Quota:: ?
|
295
|
+
Region:: Russia
|
296
|
+
SSL support:: no
|
297
|
+
Languages:: Russian, Belarusian, and Ukrainian
|
298
|
+
Documentation:: http://api.yandex.ru/maps/geocoder/doc/desc/concepts/response_structure.xml
|
299
|
+
Terms of Service:: http://api.yandex.com/direct/eula.xml?ncrnd=8453
|
300
|
+
Limitations:: ?
|
301
|
+
|
302
|
+
==== Geocoder.ca (<tt>:geocoder_ca</tt>)
|
303
|
+
|
304
|
+
API key:: none
|
305
|
+
Quota:: ?
|
306
|
+
Region:: US and Canada
|
307
|
+
SSL support:: no
|
308
|
+
Languages:: English
|
309
|
+
Documentation:: ?
|
310
|
+
Terms of Service:: http://geocoder.ca/?terms=1
|
311
|
+
Limitations:: "Under no circumstances can our data be re-distributed or re-sold by anyone to other parties without our written permission."
|
312
|
+
|
313
|
+
==== FreeGeoIP
|
314
|
+
|
315
|
+
API key:: none
|
316
|
+
Quota:: ?
|
317
|
+
Region:: world
|
318
|
+
SSL support:: no
|
319
|
+
Languages:: English
|
320
|
+
Documentation:: http://github.com/fiorix/freegeoip/blob/master/README.rst
|
321
|
+
Terms of Service:: ?
|
322
|
+
Limitations:: ?
|
323
|
+
|
324
|
+
|
325
|
+
== Caching
|
273
326
|
|
274
327
|
It's a good idea, when relying on any external service, to cache retrieved data. When implemented correctly it improves your app's response time and stability. It's easy to cache geocoding results with Geocoder, just configure a cache store:
|
275
328
|
|
@@ -296,6 +349,8 @@ If you need to expire cached content:
|
|
296
349
|
|
297
350
|
Do *not* include the prefix when passing a URL to be expired. Expiring <tt>:all</tt> will only expire keys with the configured prefix (won't kill every entry in your key/value store).
|
298
351
|
|
352
|
+
<i>Before you implement caching in your app please be sure that doing so does not violate the Terms of Service for your geocoding service.</i>
|
353
|
+
|
299
354
|
|
300
355
|
== Forward and Reverse Geocoding in the Same Model
|
301
356
|
|
@@ -338,6 +393,23 @@ You can use Geocoder outside of Rails by calling the <tt>Geocoder.search</tt> me
|
|
338
393
|
This returns an array of <tt>Geocoder::Result</tt> objects with all information provided by the geocoding service. Please see above and in the code for details.
|
339
394
|
|
340
395
|
|
396
|
+
== Command Line Interface
|
397
|
+
|
398
|
+
When you install the Geocoder gem it adds a +geocode+ command to your shell. You can search for a street address, IP address, postal code, coordinates, etc just like you can with the Geocoder.search method for example:
|
399
|
+
|
400
|
+
$ geocode 29.951,-90.081
|
401
|
+
Latitude: 29.952211
|
402
|
+
Longitude: -90.080563
|
403
|
+
Full address: 1500 Sugar Bowl Dr, New Orleans, LA 70112, USA
|
404
|
+
City: New Orleans
|
405
|
+
State/province: Louisiana
|
406
|
+
Postal code: 70112
|
407
|
+
Country: United States
|
408
|
+
Google map: http://maps.google.com/maps?q=29.952211,-90.080563
|
409
|
+
|
410
|
+
There are also a number of options for setting the geocoding API, key, and language, viewing the raw JSON reponse, and more. Please run <tt>geocode -h</tt> for details.
|
411
|
+
|
412
|
+
|
341
413
|
== Notes on Mongoid
|
342
414
|
|
343
415
|
=== The Near Method
|
@@ -346,7 +418,7 @@ Mongoid document classes have a built-in +near+ scope, but since it only works t
|
|
346
418
|
|
347
419
|
=== Latitude/Longitude Order
|
348
420
|
|
349
|
-
Coordinates are generally printed and spoken as latitude, then logitude ([lat,lon]). Geocoder respects this convention and always expects method arguments to be given in [lat,lon] order. However, MongoDB requires that coordinates be stored in [lon,lat] order as per the GeoJSON spec (http://geojson.org/geojson-spec.html#positions), so internally they are stored "backwards." However, this does not affect order of arguments to methods when using Mongoid.
|
421
|
+
Coordinates are generally printed and spoken as latitude, then logitude ([lat,lon]). Geocoder respects this convention and always expects method arguments to be given in [lat,lon] order. However, MongoDB requires that coordinates be stored in [lon,lat] order as per the GeoJSON spec (http://geojson.org/geojson-spec.html#positions), so internally they are stored "backwards." However, this does not affect order of arguments to methods when using Mongoid.
|
350
422
|
|
351
423
|
|
352
424
|
== Distance Queries in SQLite
|
@@ -376,19 +448,12 @@ http://github.com/alexreisner/geocoder_test
|
|
376
448
|
|
377
449
|
== Known Issue
|
378
450
|
|
379
|
-
You cannot use the +near+ scope with another scope that provides an +includes+ option because the +SELECT+ clause generated by +near+ will overwrite it (or vice versa). Instead, try using +joins+ and pass a <tt>:select</tt> option to the +near+ scope to get the columns you want. For example
|
451
|
+
You cannot use the +near+ scope with another scope that provides an +includes+ option because the +SELECT+ clause generated by +near+ will overwrite it (or vice versa). Instead, try using +joins+ and pass a <tt>:select</tt> option to the +near+ scope to get the columns you want. For example:
|
380
452
|
|
381
|
-
# instead of
|
382
|
-
City.near("Omaha, NE", 20, :select => "venues.*").
|
453
|
+
# instead of City.near(...).includes(:venues)
|
454
|
+
City.near("Omaha, NE", 20, :select => "cities.*, venues.*").joins(:venues)
|
383
455
|
|
384
456
|
If anyone has a more elegant solution to this problem I am very interested in seeing it.
|
385
457
|
|
386
458
|
|
387
|
-
== Roadmap
|
388
|
-
|
389
|
-
* add support for more ORMs (Mongoid, DataMapper)
|
390
|
-
* add support for more geocoding services
|
391
|
-
* maintain the same simple interface
|
392
|
-
|
393
|
-
|
394
459
|
Copyright (c) 2009-11 Alex Reisner, released under the MIT license
|
data/bin/geocode
ADDED
data/lib/geocoder.rb
CHANGED
@@ -11,32 +11,8 @@ module Geocoder
|
|
11
11
|
##
|
12
12
|
# Search for information about an address or a set of coordinates.
|
13
13
|
#
|
14
|
-
def search(query
|
15
|
-
|
16
|
-
if query.is_a?(Numeric) and args.first.is_a?(Numeric)
|
17
|
-
warn "DEPRECATION WARNING: Instead of passing latitude/longitude as separate arguments to the search method, please pass an array: [#{query},#{args.first}]. The old argument format will not be supported in Geocoder v.1.0."
|
18
|
-
query = [query, args.first]
|
19
|
-
end
|
20
|
-
if blank_query?(query)
|
21
|
-
results = []
|
22
|
-
else
|
23
|
-
results = lookup(ip_address?(query)).search(query)
|
24
|
-
end
|
25
|
-
results.instance_eval do
|
26
|
-
def warn_search_deprecation(attr)
|
27
|
-
warn "DEPRECATION WARNING: Geocoder.search now returns an array of Geocoder::Result objects. " +
|
28
|
-
"Calling '%s' directly on the returned array will cause an exception in Geocoder v1.0." % attr
|
29
|
-
end
|
30
|
-
|
31
|
-
def coordinates; warn_search_deprecation('coordinates'); first.coordinates if first; end
|
32
|
-
def latitude; warn_search_deprecation('latitude'); first.latitude if first; end
|
33
|
-
def longitude; warn_search_deprecation('longitude'); first.longitude if first; end
|
34
|
-
def address; warn_search_deprecation('address'); first.address if first; end
|
35
|
-
def city; warn_search_deprecation('city'); first.city if first; end
|
36
|
-
def country; warn_search_deprecation('country'); first.country if first; end
|
37
|
-
def country_code; warn_search_deprecation('country_code'); first.country_code if first; end
|
38
|
-
end
|
39
|
-
return results
|
14
|
+
def search(query)
|
15
|
+
blank_query?(query) ? [] : lookup(query).search(query)
|
40
16
|
end
|
41
17
|
|
42
18
|
##
|
@@ -52,11 +28,7 @@ module Geocoder
|
|
52
28
|
# Look up the address of the given coordinates ([lat,lon])
|
53
29
|
# or IP address (string).
|
54
30
|
#
|
55
|
-
def address(query
|
56
|
-
if lon = args.first
|
57
|
-
warn "DEPRECATION WARNING: Instead of passing latitude/longitude as separate arguments to the address method, please pass an array: [#{query},#{args.first}]. The old argument format will not be supported in Geocoder v.1.0."
|
58
|
-
query = [query, lon]
|
59
|
-
end
|
31
|
+
def address(query)
|
60
32
|
if (results = search(query)).size > 0
|
61
33
|
results.first.address
|
62
34
|
end
|
@@ -72,6 +44,27 @@ module Geocoder
|
|
72
44
|
@cache
|
73
45
|
end
|
74
46
|
|
47
|
+
##
|
48
|
+
# Array of valid Lookup names.
|
49
|
+
#
|
50
|
+
def valid_lookups
|
51
|
+
street_lookups + ip_lookups
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# All street address lookups, default first.
|
56
|
+
#
|
57
|
+
def street_lookups
|
58
|
+
[:google, :yahoo, :bing, :geocoder_ca, :yandex]
|
59
|
+
end
|
60
|
+
|
61
|
+
##
|
62
|
+
# All IP address lookups, default first.
|
63
|
+
#
|
64
|
+
def ip_lookups
|
65
|
+
[:freegeoip]
|
66
|
+
end
|
67
|
+
|
75
68
|
|
76
69
|
# exception classes
|
77
70
|
class Error < StandardError; end
|
@@ -82,13 +75,14 @@ module Geocoder
|
|
82
75
|
|
83
76
|
##
|
84
77
|
# Get a Lookup object (which communicates with the remote geocoding API).
|
85
|
-
#
|
78
|
+
# Takes a search query and returns an IP or street address Lookup
|
79
|
+
# depending on the query contents.
|
86
80
|
#
|
87
|
-
def lookup(
|
88
|
-
if
|
89
|
-
get_lookup
|
81
|
+
def lookup(query)
|
82
|
+
if ip_address?(query)
|
83
|
+
get_lookup(ip_lookups.first)
|
90
84
|
else
|
91
|
-
get_lookup
|
85
|
+
get_lookup(Configuration.lookup || street_lookups.first)
|
92
86
|
end
|
93
87
|
end
|
94
88
|
|
@@ -121,13 +115,6 @@ module Geocoder
|
|
121
115
|
end
|
122
116
|
end
|
123
117
|
|
124
|
-
##
|
125
|
-
# Array of valid Lookup names.
|
126
|
-
#
|
127
|
-
def valid_lookups
|
128
|
-
[:google, :yahoo, :geocoder_ca, :freegeoip]
|
129
|
-
end
|
130
|
-
|
131
118
|
##
|
132
119
|
# Does the given value look like an IP address?
|
133
120
|
#
|
@@ -51,13 +51,7 @@ module Geocoder
|
|
51
51
|
#
|
52
52
|
# * <tt>:units</tt> - <tt>:mi</tt> (default) or <tt>:km</tt>
|
53
53
|
#
|
54
|
-
def distance_between(point1, point2, options = {}
|
55
|
-
if args.size > 0
|
56
|
-
warn "DEPRECATION WARNING: Instead of passing lat1/lon1/lat2/lon2 as separate arguments to the distance_between method, please pass two two-element arrays: [#{point1},#{point2}], [#{options}, #{args.first}]. The old argument format will not be supported in Geocoder v.1.0."
|
57
|
-
point1 = [point1, point2]
|
58
|
-
point2 = [options, args.shift]
|
59
|
-
options = args.shift || {}
|
60
|
-
end
|
54
|
+
def distance_between(point1, point2, options = {})
|
61
55
|
|
62
56
|
# set default options
|
63
57
|
options[:units] ||= :mi
|
@@ -95,14 +89,9 @@ module Geocoder
|
|
95
89
|
#
|
96
90
|
# Based on: http://www.movable-type.co.uk/scripts/latlong.html
|
97
91
|
#
|
98
|
-
def bearing_between(point1, point2, options = {}
|
99
|
-
if args.size > 0
|
100
|
-
warn "DEPRECATION WARNING: Instead of passing lat1/lon1/lat2/lon2 as separate arguments to the bearing_between method, please pass two two-element arrays: [#{point1},#{point2}], [#{options}, #{args.first}]. The old argument format will not be supported in Geocoder v.1.0."
|
101
|
-
point1 = [point1, point2]
|
102
|
-
point2 = [options, args.shift]
|
103
|
-
options = args.shift || {}
|
104
|
-
end
|
92
|
+
def bearing_between(point1, point2, options = {})
|
105
93
|
|
94
|
+
# set default options
|
106
95
|
options[:method] = :linear unless options[:method] == :spherical
|
107
96
|
|
108
97
|
# convert to coordinate arrays
|
@@ -190,13 +179,7 @@ module Geocoder
|
|
190
179
|
#
|
191
180
|
# * <tt>:units</tt> - <tt>:mi</tt> (default) or <tt>:km</tt>
|
192
181
|
#
|
193
|
-
def bounding_box(point, radius, options = {}
|
194
|
-
if point.is_a?(Numeric)
|
195
|
-
warn "DEPRECATION WARNING: Instead of passing latitude/longitude as separate arguments to the bounding_box method, please pass an array [#{point},#{radius}], a geocoded object, or a geocodable address (string). The old argument format will not be supported in Geocoder v.1.0."
|
196
|
-
point = [point, radius]
|
197
|
-
radius = options
|
198
|
-
options = args.first || {}
|
199
|
-
end
|
182
|
+
def bounding_box(point, radius, options = {})
|
200
183
|
lat,lon = extract_coordinates(point)
|
201
184
|
radius = radius.to_f
|
202
185
|
units = options[:units] || :mi
|
data/lib/geocoder/cli.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'geocoder'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
module Geocoder
|
5
|
+
class Cli
|
6
|
+
|
7
|
+
def self.run(args, out = STDOUT)
|
8
|
+
show_url = false
|
9
|
+
show_json = false
|
10
|
+
|
11
|
+
OptionParser.new{ |opts|
|
12
|
+
opts.banner = "Usage:\n geocode [options] <location>"
|
13
|
+
opts.separator "\nOptions: "
|
14
|
+
|
15
|
+
opts.on("-k <key>", "--key <key>",
|
16
|
+
"Key for geocoding API (optional for most)") do |key|
|
17
|
+
Geocoder::Configuration.api_key = key
|
18
|
+
end
|
19
|
+
|
20
|
+
opts.on("-l <language>", "--language <language>",
|
21
|
+
"Language of output (see API docs for valid choices)") do |language|
|
22
|
+
Geocoder::Configuration.language = language
|
23
|
+
end
|
24
|
+
|
25
|
+
opts.on("-p <proxy>", "--proxy <proxy>",
|
26
|
+
"HTTP proxy server to use (user:pass@host:port)") do |proxy|
|
27
|
+
Geocoder::Configuration.http_proxy = proxy
|
28
|
+
end
|
29
|
+
|
30
|
+
opts.on("-s <service>", Geocoder.street_lookups, "--service <service>",
|
31
|
+
"Geocoding service: #{Geocoder.street_lookups * ', '}") do |service|
|
32
|
+
Geocoder::Configuration.lookup = service.to_sym
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on("-t <seconds>", "--timeout <seconds>",
|
36
|
+
"Maximum number of seconds to wait for API response") do |timeout|
|
37
|
+
Geocoder::Configuration.timeout = timeout.to_i
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("-j", "--json", "Print API's raw JSON response") do
|
41
|
+
show_json = true
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on("-u", "--url", "Print URL for API query instead of result") do
|
45
|
+
show_url = true
|
46
|
+
end
|
47
|
+
|
48
|
+
opts.on_tail("-v", "--version", "Print version number") do
|
49
|
+
require "geocoder/version"
|
50
|
+
out << "Geocoder #{Geocoder::VERSION}\n"
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
|
54
|
+
opts.on_tail("-h", "--help", "Print this help") do
|
55
|
+
out << "Look up geographic information about a location.\n\n"
|
56
|
+
out << opts
|
57
|
+
out << "\nCreated and maintained by Alex Reisner, available under the MIT License.\n"
|
58
|
+
out << "Report bugs and contribute at http://github.com/alexreisner/geocoder\n"
|
59
|
+
exit
|
60
|
+
end
|
61
|
+
}.parse!(args)
|
62
|
+
|
63
|
+
query = args.join(" ")
|
64
|
+
|
65
|
+
if query == ""
|
66
|
+
out << "Please specify a location (run `geocode -h` for more info).\n"
|
67
|
+
exit 1
|
68
|
+
end
|
69
|
+
|
70
|
+
if show_url and show_json
|
71
|
+
out << "You can only specify one of -j and -u.\n"
|
72
|
+
exit 2
|
73
|
+
end
|
74
|
+
|
75
|
+
if show_url
|
76
|
+
lookup = Geocoder.send(:lookup, query)
|
77
|
+
reverse = lookup.send(:coordinates?, query)
|
78
|
+
out << lookup.send(:query_url, query, reverse) + "\n"
|
79
|
+
exit 0
|
80
|
+
end
|
81
|
+
|
82
|
+
if show_json
|
83
|
+
lookup = Geocoder.send(:lookup, query)
|
84
|
+
reverse = lookup.send(:coordinates?, query)
|
85
|
+
out << lookup.send(:fetch_raw_data, query, reverse) + "\n"
|
86
|
+
exit 0
|
87
|
+
end
|
88
|
+
|
89
|
+
if (result = Geocoder.search(query).first)
|
90
|
+
lookup = Geocoder.send(:get_lookup, :google)
|
91
|
+
lines = [
|
92
|
+
["Latitude", result.latitude],
|
93
|
+
["Longitude", result.longitude],
|
94
|
+
["Full address", result.address],
|
95
|
+
["City", result.city],
|
96
|
+
["State/province", result.state],
|
97
|
+
["Postal code", result.postal_code],
|
98
|
+
["Country", result.country],
|
99
|
+
["Google map", lookup.map_link_url(result.coordinates)],
|
100
|
+
]
|
101
|
+
lines.each do |line|
|
102
|
+
out << (line[0] + ": ").ljust(18) + line[1].to_s + "\n"
|
103
|
+
end
|
104
|
+
exit 0
|
105
|
+
else
|
106
|
+
out << "Location '#{query}' not found.\n"
|
107
|
+
exit 1
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|