geocoder 1.2.9 → 1.3.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 +4 -4
- data/CHANGELOG.md +35 -0
- data/README.md +81 -25
- data/lib/generators/geocoder/config/templates/initializer.rb +15 -15
- data/lib/geocoder/calculations.rb +6 -3
- data/lib/geocoder/configuration.rb +3 -2
- data/lib/geocoder/exceptions.rb +5 -0
- data/lib/geocoder/kernel_logger.rb +25 -0
- data/lib/geocoder/logger.rb +13 -21
- data/lib/geocoder/lookup.rb +6 -4
- data/lib/geocoder/lookups/baidu.rb +1 -1
- data/lib/geocoder/lookups/baidu_ip.rb +1 -1
- data/lib/geocoder/lookups/base.rb +13 -13
- data/lib/geocoder/lookups/geocoder_us.rb +6 -2
- data/lib/geocoder/lookups/geoip2.rb +10 -5
- data/lib/geocoder/lookups/geoportail_lu.rb +65 -0
- data/lib/geocoder/lookups/google.rb +9 -0
- data/lib/geocoder/lookups/mapbox.rb +53 -0
- data/lib/geocoder/lookups/maxmind_local.rb +1 -1
- data/lib/geocoder/lookups/telize.rb +10 -3
- data/lib/geocoder/lookups/yandex.rb +4 -0
- data/lib/geocoder/request.rb +1 -1
- data/lib/geocoder/results/esri.rb +22 -6
- data/lib/geocoder/results/geoip2.rb +12 -8
- data/lib/geocoder/results/geoportail_lu.rb +69 -0
- data/lib/geocoder/results/google.rb +8 -0
- data/lib/geocoder/results/mapbox.rb +55 -0
- data/lib/geocoder/results/mapquest.rb +4 -0
- data/lib/geocoder/results/pointpin.rb +0 -4
- data/lib/geocoder/stores/active_record.rb +16 -0
- data/lib/geocoder/stores/base.rb +0 -11
- data/lib/geocoder/stores/mongo_base.rb +0 -31
- data/lib/geocoder/version.rb +1 -1
- data/lib/geocoder.rb +1 -0
- data/lib/maxmind_database.rb +1 -1
- data/lib/tasks/geocoder.rake +12 -3
- metadata +8 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: e7a2b3e33175d20be86a8eaf6c74d6178bc71991
|
|
4
|
+
data.tar.gz: d0dc03b689fbc43f16ae9395c7f743a3dd7876bd
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: cb9f5c459af278bd20438a714475dece555b72222c34eab8c8fb61f6ddfc695848d330e9b84f366c8d67e5f253bda7d5e61020ab46382f8fbb40c8b7a9a58e82
|
|
7
|
+
data.tar.gz: ca02902240f5287a570ee05b0bc3b0300708200108b09543763e761ad1f0a2371355ef651471cdf96ce5cdabf104a39aedb04ef684e4f02aa3023911c27d7c4a
|
data/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,41 @@ Changelog
|
|
|
3
3
|
|
|
4
4
|
Major changes to Geocoder for each release. Please see the Git log for complete list of changes.
|
|
5
5
|
|
|
6
|
+
1.3.0 (2016 Jan 31)
|
|
7
|
+
-------------------
|
|
8
|
+
* Lazy load lookups to reduce memory footprint (thanks github.com/TrangPham).
|
|
9
|
+
* Add :geoportail_lu lookup (Luxembourg only) (thanks github.com/mdebo).
|
|
10
|
+
* Maxmind local query performance improvement (thanks github.com/vojtad).
|
|
11
|
+
* Remove deprecated Mongo near query methods (please use Mongo-native methods instead).
|
|
12
|
+
|
|
13
|
+
1.2.14 (2015 Dec 27)
|
|
14
|
+
--------------------
|
|
15
|
+
* Fix bug in :geoip2 lookup (thanks github.com/mromulus).
|
|
16
|
+
|
|
17
|
+
1.2.13 (2015 Dec 15)
|
|
18
|
+
--------------------
|
|
19
|
+
* Update :telize IP lookup to reflect new URL (thanks github.com/jfredrickson).
|
|
20
|
+
* Add reverse geocode rake task (thanks github.com/FanaHOVA).
|
|
21
|
+
* Fix reversed coordinates array with Mapbox (thanks github.com/marcusat).
|
|
22
|
+
* Fix missing city name in some cases with ESRI (thanks github.com/roybotnik).
|
|
23
|
+
* Prevent re-opening of DB file on every read with :geoip2 (thanks github.com/oogali).
|
|
24
|
+
|
|
25
|
+
1.2.12 (2015 Oct 29)
|
|
26
|
+
--------------------
|
|
27
|
+
* Fix Ruby 1.9.3 incompatibility (remove non-existent timeout classes) (thanks github.com/roychri).
|
|
28
|
+
|
|
29
|
+
1.2.11 (2015 Sep 10)
|
|
30
|
+
--------------------
|
|
31
|
+
* Fix load issue on Ruby 1.9.3.
|
|
32
|
+
|
|
33
|
+
1.2.10 (2015 Sep 7)
|
|
34
|
+
-------------------
|
|
35
|
+
* Force Yandex to use HTTPS (thanks github.com/donbobka).
|
|
36
|
+
* Force :google to use HTTPS if API key set.
|
|
37
|
+
* Fix out-of-the-box verbosity issues (GH #881).
|
|
38
|
+
* Improve timeout mechanism and add exception Geocoder::LookupTimeout (thanks github.com/ankane).
|
|
39
|
+
* Deprecate .near and #nearbys for MongoDB-backed models.
|
|
40
|
+
|
|
6
41
|
1.2.9 (2015 Jun 12)
|
|
7
42
|
-------------------
|
|
8
43
|
* Don't cache unsuccessful responses from Bing (thanks github.com/peteb).
|
data/README.md
CHANGED
|
@@ -9,7 +9,7 @@ _Please note that this README is for the current `HEAD` and may document feature
|
|
|
9
9
|
Compatibility
|
|
10
10
|
-------------
|
|
11
11
|
|
|
12
|
-
* Supports multiple Ruby versions: Ruby 1.9.3, 2.
|
|
12
|
+
* Supports multiple Ruby versions: Ruby 1.9.3, 2.x, JRuby, and Rubinius.
|
|
13
13
|
* Supports multiple databases: MySQL, PostgreSQL, SQLite, and MongoDB (1.7.0 and higher).
|
|
14
14
|
* Supports Rails 3 and 4. If you need to use it with Rails 2 please see the `rails2` branch (no longer maintained, limited feature set).
|
|
15
15
|
* Works very well outside of Rails, you just need to install either the `json` (for MRI) or `json_pure` (for JRuby) gem.
|
|
@@ -47,7 +47,7 @@ Your model must have two attributes (database columns) for storing latitude and
|
|
|
47
47
|
rails generate migration AddLatitudeAndLongitudeToModel latitude:float longitude:float
|
|
48
48
|
rake db:migrate
|
|
49
49
|
|
|
50
|
-
For
|
|
50
|
+
For geocoding your model must provide a method that returns an address. This can be a single attribute, but it can also be a method that returns a string assembled from different attributes (eg: `city`, `state`, and `country`).
|
|
51
51
|
|
|
52
52
|
Next, your model must tell Geocoder which method returns your object's geocodable address:
|
|
53
53
|
|
|
@@ -106,6 +106,10 @@ If you have just added geocoding to an existing application with a lot of object
|
|
|
106
106
|
|
|
107
107
|
rake geocode:all CLASS=YourModel
|
|
108
108
|
|
|
109
|
+
If you need reverse geocoding instead, call the task with REVERSE=true:
|
|
110
|
+
|
|
111
|
+
rake geocode:all CLASS=YourModel REVERSE=true
|
|
112
|
+
|
|
109
113
|
Geocoder will print warnings if you exceed the rate limit for your geocoding service. Some services — Google notably — enforce a per-second limit in addition to a per-day limit. To avoid exceeding the per-second limit, you can add a `SLEEP` option to pause between requests for a given amount of time. You can also load objects in batches to save memory, for example:
|
|
110
114
|
|
|
111
115
|
rake geocode:all CLASS=YourModel SLEEP=0.25 BATCH=100
|
|
@@ -140,6 +144,12 @@ See _Advanced Geocoding_ below for more information about `Geocoder::Result` obj
|
|
|
140
144
|
Location-Aware Database Queries
|
|
141
145
|
-------------------------------
|
|
142
146
|
|
|
147
|
+
### For Mongo-backed models:
|
|
148
|
+
|
|
149
|
+
Please use MongoDB's [geospatial query language](https://docs.mongodb.org/manual/reference/command/geoNear/). Mongoid also provides [a DSL](http://mongoid.github.io/en/mongoid/docs/querying.html#geo_near) for doing near queries.
|
|
150
|
+
|
|
151
|
+
### For ActiveRecord models:
|
|
152
|
+
|
|
143
153
|
To find objects by location, use the following scopes:
|
|
144
154
|
|
|
145
155
|
Venue.near('Omaha, NE, US', 20) # venues within 20 miles of Omaha
|
|
@@ -149,6 +159,10 @@ To find objects by location, use the following scopes:
|
|
|
149
159
|
Venue.geocoded # venues with coordinates
|
|
150
160
|
Venue.not_geocoded # venues without coordinates
|
|
151
161
|
|
|
162
|
+
by default, objects are ordered by distance. To remove the ORDER BY clause use the following:
|
|
163
|
+
|
|
164
|
+
Venue.near('Omaha', 20, :order => false)
|
|
165
|
+
|
|
152
166
|
With geocoded objects you can do things like this:
|
|
153
167
|
|
|
154
168
|
if obj.geocoded?
|
|
@@ -294,7 +308,7 @@ Every `Geocoder::Result` object, `result`, provides the following data:
|
|
|
294
308
|
|
|
295
309
|
* `result.latitude` - float
|
|
296
310
|
* `result.longitude` - float
|
|
297
|
-
* `result.coordinates` - array of the above two
|
|
311
|
+
* `result.coordinates` - array of the above two in the form of `[lat,lon]`
|
|
298
312
|
* `result.address` - string
|
|
299
313
|
* `result.city` - string
|
|
300
314
|
* `result.state` - string
|
|
@@ -351,6 +365,10 @@ Please see the [source code for each lookup](https://github.com/alexreisner/geoc
|
|
|
351
365
|
# with Nominatim:
|
|
352
366
|
Geocoder.search("Paris", :params => {:countrycodes => "gb,de,fr,es,us"})
|
|
353
367
|
|
|
368
|
+
Or, to search within a particular region with Google:
|
|
369
|
+
|
|
370
|
+
Geocoder.search("...", :params => {:region => "..."})
|
|
371
|
+
|
|
354
372
|
You can also configure multiple geocoding services at once, like this:
|
|
355
373
|
|
|
356
374
|
Geocoder.configure(
|
|
@@ -381,19 +399,26 @@ The above combines global and service-specific options and could be useful if yo
|
|
|
381
399
|
|
|
382
400
|
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.
|
|
383
401
|
|
|
384
|
-
#### Google (`:google
|
|
402
|
+
#### Google (`:google`)
|
|
385
403
|
|
|
386
|
-
* **API key**:
|
|
387
|
-
* **Key signup**: https://developers.google.com/
|
|
388
|
-
* **Quota**: 2,500 requests/
|
|
404
|
+
* **API key**: optional, but quota is higher if key is used (use of key requires HTTPS so be sure to set: `:use_https => true` in `Geocoder.configure`)
|
|
405
|
+
* **Key signup**: https://console.developers.google.com//flows/enableapi?apiid=geocoding_backend&keyType=SERVER_SIDE
|
|
406
|
+
* **Quota**: 2,500 requests/24 hrs, 5 requests/second
|
|
389
407
|
* **Region**: world
|
|
390
|
-
* **SSL support**: yes
|
|
391
|
-
* **Languages**:
|
|
408
|
+
* **SSL support**: yes (required if key is used)
|
|
409
|
+
* **Languages**: see https://developers.google.com/maps/faq#languagesupport
|
|
392
410
|
* **Extra options**: `:bounds` - pass SW and NE coordinates as an array of two arrays to bias results towards a viewport
|
|
393
|
-
* **Documentation**:
|
|
411
|
+
* **Documentation**: https://developers.google.com/maps/documentation/geocoding/intro
|
|
394
412
|
* **Terms of Service**: http://code.google.com/apis/maps/terms.html#section_10_12
|
|
395
413
|
* **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..."
|
|
396
|
-
|
|
414
|
+
|
|
415
|
+
#### Google Maps API for Work (`:google_premier`)
|
|
416
|
+
|
|
417
|
+
Similar to `:google`, with the following differences:
|
|
418
|
+
|
|
419
|
+
* **API key**: required, plus client and channel (set `Geocoder.configure(:lookup => :google_premier, :api_key => [key, client, channel])`)
|
|
420
|
+
* **Key signup**: https://developers.google.com/maps/documentation/business/
|
|
421
|
+
* **Quota**: 100,000 requests/24 hrs, 10 requests/second
|
|
397
422
|
|
|
398
423
|
#### Google Places Details (`:google_places_details`)
|
|
399
424
|
|
|
@@ -442,7 +467,7 @@ The [Google Places Details API](https://developers.google.com/places/documentati
|
|
|
442
467
|
* **Languages**: ?
|
|
443
468
|
* **Documentation**: http://wiki.openstreetmap.org/wiki/Nominatim
|
|
444
469
|
* **Terms of Service**: http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
|
|
445
|
-
* **Limitations**: Please limit request rate to 1 per second and include your contact information in User-Agent headers (eg: `Geocoder.configure(:http_headers => { "User-Agent" => "your contact info" })`). Data licensed under
|
|
470
|
+
* **Limitations**: Please limit request rate to 1 per second and include your contact information in User-Agent headers (eg: `Geocoder.configure(:http_headers => { "User-Agent" => "your contact info" })`). [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
|
|
446
471
|
|
|
447
472
|
#### OpenCageData (`:opencagedata`)
|
|
448
473
|
|
|
@@ -453,14 +478,14 @@ The [Google Places Details API](https://developers.google.com/places/documentati
|
|
|
453
478
|
* **SSL support**: yes
|
|
454
479
|
* **Languages**: worldwide
|
|
455
480
|
* **Documentation**: http://geocoder.opencagedata.com/api.html
|
|
456
|
-
* **Limitations**: Data licensed under
|
|
481
|
+
* **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
|
|
457
482
|
|
|
458
483
|
#### Yandex (`:yandex`)
|
|
459
484
|
|
|
460
|
-
* **API key**:
|
|
485
|
+
* **API key**: optional, but without it lookup is territorially limited
|
|
461
486
|
* **Quota**: 25000 requests / day
|
|
462
|
-
* **Region**: world
|
|
463
|
-
* **SSL support**:
|
|
487
|
+
* **Region**: world with API key. Otherwise restricted to Russia, Ukraine, Belarus, Kazakhstan, Georgia, Abkhazia, South Ossetia, Armenia, Azerbaijan, Moldova, Turkmenistan, Tajikistan, Uzbekistan, Kyrgyzstan and Turkey
|
|
488
|
+
* **SSL support**: HTTPS only
|
|
464
489
|
* **Languages**: Russian, Belarusian, Ukrainian, English, Turkish (only for maps of Turkey)
|
|
465
490
|
* **Documentation**: http://api.yandex.com.tr/maps/doc/intro/concepts/intro.xml
|
|
466
491
|
* **Terms of Service**: http://api.yandex.com.tr/maps/doc/intro/concepts/intro.xml#rules
|
|
@@ -489,10 +514,24 @@ The [Google Places Details API](https://developers.google.com/places/documentati
|
|
|
489
514
|
* **Terms of Service**: http://geocoder.us/terms.shtml
|
|
490
515
|
* **Limitations**: ?
|
|
491
516
|
|
|
517
|
+
#### Mapbox (`:mapbox`)
|
|
518
|
+
|
|
519
|
+
* **API key**: required
|
|
520
|
+
* **Dataset**: Uses `mapbox.places` dataset by default. Specific the `mapbox.places-permanent` dataset by setting: `Geocoder.configure(:mapbox => {:dataset => "mapbox.places-permanent"})`
|
|
521
|
+
* **Key signup**: https://www.mapbox.com/pricing/
|
|
522
|
+
* **Quota**: depends on plan
|
|
523
|
+
* **Region**: complete coverage of US and Canada, partial coverage elsewhere (see for details: https://www.mapbox.com/developers/api/geocoding/#coverage)
|
|
524
|
+
* **SSL support**: yes
|
|
525
|
+
* **Languages**: English
|
|
526
|
+
* **Documentation**: https://www.mapbox.com/developers/api/geocoding/
|
|
527
|
+
* **Terms of Service**: https://www.mapbox.com/tos/
|
|
528
|
+
* **Limitations**: For `mapbox.places` dataset, must be displayed on a Mapbox map; Cache results for up to 30 days. For `mapbox.places-permanent` dataset, depends on plan.
|
|
529
|
+
* **Notes**: Currently in public beta.
|
|
530
|
+
|
|
492
531
|
#### Mapquest (`:mapquest`)
|
|
493
532
|
|
|
494
533
|
* **API key**: required
|
|
495
|
-
* **Key signup**:
|
|
534
|
+
* **Key signup**: https://developer.mapquest.com/plans
|
|
496
535
|
* **Quota**: ?
|
|
497
536
|
* **HTTP Headers**: when using the licensed API you can specify a referer like so:
|
|
498
537
|
`Geocoder.configure(:http_headers => { "Referer" => "http://foo.com" })`
|
|
@@ -567,13 +606,13 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w
|
|
|
567
606
|
#### Geocodio (`:geocodio`)
|
|
568
607
|
|
|
569
608
|
* **API key**: required
|
|
570
|
-
* **Quota**: 2,500 free requests/day then purchase $.001 for each
|
|
609
|
+
* **Quota**: 2,500 free requests/day then purchase $.001 for each, also has volume pricing and plans
|
|
571
610
|
* **Region**: US
|
|
572
|
-
* **SSL support**:
|
|
611
|
+
* **SSL support**: yes
|
|
573
612
|
* **Languages**: en
|
|
574
613
|
* **Documentation**: http://geocod.io/docs
|
|
575
614
|
* **Terms of Service**: http://geocod.io/terms-of-use
|
|
576
|
-
* **Limitations**:
|
|
615
|
+
* **Limitations**: No restrictions on use
|
|
577
616
|
|
|
578
617
|
#### SmartyStreets (`:smarty_streets`)
|
|
579
618
|
|
|
@@ -598,6 +637,16 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w
|
|
|
598
637
|
* **Terms of Service**: http://www.itella.fi/liitteet/palvelutjatuotteet/yhteystietopalvelut/Postinumeropalvelut-Palvelukuvausjakayttoehdot.pdf
|
|
599
638
|
* **Limitations**: ?
|
|
600
639
|
|
|
640
|
+
#### Geoportail.lu (`:geoportail_lu`)
|
|
641
|
+
|
|
642
|
+
* **API key**: none
|
|
643
|
+
* **Quota**: none
|
|
644
|
+
* **Region**: LU
|
|
645
|
+
* **SSL support**: yes
|
|
646
|
+
* **Languages**: en
|
|
647
|
+
* **Documentation**: http://wiki.geoportail.lu/doku.php?id=en:api
|
|
648
|
+
* **Terms of Service**: http://wiki.geoportail.lu/doku.php?id=en:mcg_1
|
|
649
|
+
* **Limitations**: ?
|
|
601
650
|
|
|
602
651
|
#### PostcodeAnywhere Uk (`:postcode_anywhere_uk`)
|
|
603
652
|
|
|
@@ -642,14 +691,15 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
|
|
|
642
691
|
|
|
643
692
|
#### Telize (`:telize`)
|
|
644
693
|
|
|
645
|
-
* **API key**:
|
|
646
|
-
* **Quota**:
|
|
694
|
+
* **API key**: required
|
|
695
|
+
* **Quota**: 1,000/day for $7/mo through 100,000/day for $100/mo
|
|
647
696
|
* **Region**: world
|
|
648
|
-
* **SSL support**:
|
|
697
|
+
* **SSL support**: yes
|
|
649
698
|
* **Languages**: English
|
|
650
|
-
* **Documentation**:
|
|
699
|
+
* **Documentation**: https://market.mashape.com/fcambus/telize
|
|
651
700
|
* **Terms of Service**: ?
|
|
652
701
|
* **Limitations**: ?
|
|
702
|
+
* **Notes**: To use Telize set `Geocoder.configure(:ip_lookup => :telize, :api_key => "your_api_key")`.
|
|
653
703
|
|
|
654
704
|
#### MaxMind Legacy Web Services (`:maxmind`)
|
|
655
705
|
|
|
@@ -884,6 +934,9 @@ Now, any time Geocoder looks up "New York, NY" its results array will contain on
|
|
|
884
934
|
]
|
|
885
935
|
)
|
|
886
936
|
|
|
937
|
+
Note:
|
|
938
|
+
Keys must be strings not symbols when calling `add_stub` or `set_default_stub`. For example `'latitude' =>` not `:latitude =>`.
|
|
939
|
+
|
|
887
940
|
|
|
888
941
|
Command Line Interface
|
|
889
942
|
----------------------
|
|
@@ -1059,7 +1112,9 @@ If anyone has a more elegant solution to this problem I am very interested in se
|
|
|
1059
1112
|
Contributing
|
|
1060
1113
|
------------
|
|
1061
1114
|
|
|
1062
|
-
Contributions are welcome via pull requests
|
|
1115
|
+
Contributions are welcome via Github pull requests. If you are new to the project and looking for a way to get involved, try picking up an issue with a "beginner-task" label. Hints about what needs to be done are usually provided.
|
|
1116
|
+
|
|
1117
|
+
For all contributions, please respect the following guidelines:
|
|
1063
1118
|
|
|
1064
1119
|
* Each pull request should implement ONE feature or bugfix. If you want to add or fix more than one thing, submit more than one pull request.
|
|
1065
1120
|
* Do not commit changes to files that are irrelevant to your feature or bugfix (eg: `.gitignore`).
|
|
@@ -1068,6 +1123,7 @@ Contributions are welcome via pull requests on Github. Please respect the follow
|
|
|
1068
1123
|
* Remember: Geocoder needs to run outside of Rails. Don't assume things like ActiveSupport are available.
|
|
1069
1124
|
* Be willing to accept criticism and work on improving your code; Geocoder is used by thousands of developers and care must be taken not to introduce bugs.
|
|
1070
1125
|
* Be aware that the pull request review process is not immediate, and is generally proportional to the size of the pull request.
|
|
1126
|
+
* If your pull request is merged, please do not ask for an immediate release of the gem. There are many factors contributing to when releases occur (remember that they affect thousands of apps with Geocoder in their Gemfiles). If necessary, please install from the Github source until the next official release.
|
|
1071
1127
|
|
|
1072
1128
|
|
|
1073
1129
|
Copyright (c) 2009-15 Alex Reisner, released under the MIT license
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
Geocoder.configure(
|
|
2
|
-
#
|
|
3
|
-
# :
|
|
4
|
-
# :
|
|
5
|
-
# :
|
|
6
|
-
# :
|
|
7
|
-
# :
|
|
8
|
-
# :
|
|
9
|
-
# :
|
|
10
|
-
# :
|
|
11
|
-
# :
|
|
2
|
+
# Geocoding options
|
|
3
|
+
# timeout: 3, # geocoding service timeout (secs)
|
|
4
|
+
# lookup: :google, # name of geocoding service (symbol)
|
|
5
|
+
# language: :en, # ISO-639 language code
|
|
6
|
+
# use_https: false, # use HTTPS for lookup requests? (if supported)
|
|
7
|
+
# http_proxy: nil, # HTTP proxy server (user:pass@host:port)
|
|
8
|
+
# https_proxy: nil, # HTTPS proxy server (user:pass@host:port)
|
|
9
|
+
# api_key: nil, # API key for geocoding service
|
|
10
|
+
# cache: nil, # cache object (must respond to #[], #[]=, and #keys)
|
|
11
|
+
# cache_prefix: 'geocoder:', # prefix (string) to use for all cache keys
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# Exceptions that should not be rescued by default
|
|
14
14
|
# (if you want to implement custom error handling);
|
|
15
15
|
# supports SocketError and TimeoutError
|
|
16
|
-
# :
|
|
16
|
+
# always_raise: [],
|
|
17
17
|
|
|
18
|
-
#
|
|
19
|
-
# :
|
|
20
|
-
# :
|
|
18
|
+
# Calculation options
|
|
19
|
+
# units: :mi, # :km for kilometers or :mi for miles
|
|
20
|
+
# distances: :linear # :spherical or :linear
|
|
21
21
|
)
|
|
@@ -237,11 +237,14 @@ module Geocoder
|
|
|
237
237
|
#
|
|
238
238
|
# * <tt>:units</tt> - <tt>:mi</tt> or <tt>:km</tt>
|
|
239
239
|
# Use Geocoder.configure(:units => ...) to configure default units.
|
|
240
|
+
# * <tt>:seed</tt> - The seed for the random number generator
|
|
240
241
|
def random_point_near(center, radius, options = {})
|
|
241
242
|
|
|
242
243
|
# set default options
|
|
243
244
|
options[:units] ||= Geocoder.config.units
|
|
244
245
|
|
|
246
|
+
random = Random.new(options[:seed] || Random.new_seed)
|
|
247
|
+
|
|
245
248
|
# convert to coordinate arrays
|
|
246
249
|
center = extract_coordinates(center)
|
|
247
250
|
|
|
@@ -249,18 +252,18 @@ module Geocoder
|
|
|
249
252
|
max_degree_delta = 360.0 * (radius / earth_circumference)
|
|
250
253
|
|
|
251
254
|
# random bearing in radians
|
|
252
|
-
theta = 2 * Math::PI * rand
|
|
255
|
+
theta = 2 * Math::PI * random.rand
|
|
253
256
|
|
|
254
257
|
# random radius, use the square root to ensure a uniform
|
|
255
258
|
# distribution of points over the circle
|
|
256
|
-
r = Math.sqrt(rand) * max_degree_delta
|
|
259
|
+
r = Math.sqrt(random.rand) * max_degree_delta
|
|
257
260
|
|
|
258
261
|
delta_lat, delta_long = [r * Math.cos(theta), r * Math.sin(theta)]
|
|
259
262
|
[center[0] + delta_lat, center[1] + delta_long]
|
|
260
263
|
end
|
|
261
264
|
|
|
262
265
|
##
|
|
263
|
-
# Given a start point,
|
|
266
|
+
# Given a start point, heading (in degrees), and distance, provides
|
|
264
267
|
# an endpoint.
|
|
265
268
|
# The starting point is given in the same way that points are given to all
|
|
266
269
|
# Geocoder methods that accept points as arguments. It can be:
|
|
@@ -57,7 +57,8 @@ module Geocoder
|
|
|
57
57
|
:units,
|
|
58
58
|
:distances,
|
|
59
59
|
:basic_auth,
|
|
60
|
-
:logger
|
|
60
|
+
:logger,
|
|
61
|
+
:kernel_logger_level
|
|
61
62
|
]
|
|
62
63
|
|
|
63
64
|
attr_accessor :data
|
|
@@ -100,6 +101,7 @@ module Geocoder
|
|
|
100
101
|
@data[:cache_prefix] = "geocoder:" # prefix (string) to use for all cache keys
|
|
101
102
|
@data[:basic_auth] = {} # user and password for basic auth ({:user => "user", :password => "password"})
|
|
102
103
|
@data[:logger] = :kernel # :kernel or Logger instance
|
|
104
|
+
@data[:kernel_logger_level] = ::Logger::WARN # log level, if kernel logger is used
|
|
103
105
|
|
|
104
106
|
# exceptions that should not be rescued by default
|
|
105
107
|
# (if you want to implement custom error handling);
|
|
@@ -123,6 +125,5 @@ module Geocoder
|
|
|
123
125
|
end
|
|
124
126
|
EOS
|
|
125
127
|
end.join("\n\n"))
|
|
126
|
-
|
|
127
128
|
end
|
|
128
129
|
end
|
data/lib/geocoder/exceptions.rb
CHANGED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
module Geocoder
|
|
2
|
+
class KernelLogger
|
|
3
|
+
include Singleton
|
|
4
|
+
|
|
5
|
+
def add(level, message)
|
|
6
|
+
return unless log_message_at_level?(level)
|
|
7
|
+
case level
|
|
8
|
+
when ::Logger::DEBUG, ::Logger::INFO
|
|
9
|
+
puts message
|
|
10
|
+
when ::Logger::WARN
|
|
11
|
+
warn message
|
|
12
|
+
when ::Logger::ERROR
|
|
13
|
+
raise message
|
|
14
|
+
when ::Logger::FATAL
|
|
15
|
+
fail message
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
private # ----------------------------------------------------------------
|
|
20
|
+
|
|
21
|
+
def log_message_at_level?(level)
|
|
22
|
+
level >= Geocoder.config.kernel_logger_level
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
data/lib/geocoder/logger.rb
CHANGED
|
@@ -18,14 +18,11 @@ module Geocoder
|
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
def log(level, message)
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
kernel_log(level, message)
|
|
27
|
-
elsif logger.kind_of? ::Logger
|
|
28
|
-
logger.add(SEVERITY[level], message)
|
|
21
|
+
unless valid_level?(level)
|
|
22
|
+
raise StandardError, "Geocoder tried to log a message with an invalid log level."
|
|
23
|
+
end
|
|
24
|
+
if current_logger.respond_to? :add
|
|
25
|
+
current_logger.add(SEVERITY[level], message)
|
|
29
26
|
else
|
|
30
27
|
raise Geocoder::ConfigurationError, "Please specify valid logger for Geocoder. " +
|
|
31
28
|
"Logger specified must be :kernel or must respond to `add(level, message)`."
|
|
@@ -33,23 +30,18 @@ module Geocoder
|
|
|
33
30
|
nil
|
|
34
31
|
end
|
|
35
32
|
|
|
36
|
-
private
|
|
37
|
-
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
when :warn
|
|
43
|
-
warn message
|
|
44
|
-
when :error
|
|
45
|
-
raise message
|
|
46
|
-
when :fatal
|
|
47
|
-
fail message
|
|
33
|
+
private # ----------------------------------------------------------------
|
|
34
|
+
|
|
35
|
+
def current_logger
|
|
36
|
+
logger = Geocoder.config[:logger]
|
|
37
|
+
if logger == :kernel
|
|
38
|
+
logger = Geocoder::KernelLogger.instance
|
|
48
39
|
end
|
|
40
|
+
logger
|
|
49
41
|
end
|
|
50
42
|
|
|
51
43
|
def valid_level?(level)
|
|
52
|
-
|
|
44
|
+
SEVERITY.keys.include?(level)
|
|
53
45
|
end
|
|
54
46
|
end
|
|
55
47
|
end
|
data/lib/geocoder/lookup.rb
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require "geocoder/lookups/test"
|
|
2
|
+
|
|
1
3
|
module Geocoder
|
|
2
4
|
module Lookup
|
|
3
5
|
extend self
|
|
@@ -32,6 +34,7 @@ module Geocoder
|
|
|
32
34
|
:geocoder_us,
|
|
33
35
|
:yandex,
|
|
34
36
|
:nominatim,
|
|
37
|
+
:mapbox,
|
|
35
38
|
:mapquest,
|
|
36
39
|
:opencagedata,
|
|
37
40
|
:ovi,
|
|
@@ -41,6 +44,7 @@ module Geocoder
|
|
|
41
44
|
:smarty_streets,
|
|
42
45
|
:okf,
|
|
43
46
|
:postcode_anywhere_uk,
|
|
47
|
+
:geoportail_lu,
|
|
44
48
|
:test
|
|
45
49
|
]
|
|
46
50
|
end
|
|
@@ -82,6 +86,8 @@ module Geocoder
|
|
|
82
86
|
#
|
|
83
87
|
def spawn(name)
|
|
84
88
|
if all_services.include?(name)
|
|
89
|
+
name = name.to_s
|
|
90
|
+
require "geocoder/lookups/#{name}"
|
|
85
91
|
Geocoder::Lookup.const_get(classify_name(name)).new
|
|
86
92
|
else
|
|
87
93
|
valids = all_services.map(&:inspect).join(", ")
|
|
@@ -98,7 +104,3 @@ module Geocoder
|
|
|
98
104
|
end
|
|
99
105
|
end
|
|
100
106
|
end
|
|
101
|
-
|
|
102
|
-
Geocoder::Lookup.all_services.each do |name|
|
|
103
|
-
require "geocoder/lookups/#{name}"
|
|
104
|
-
end
|
|
@@ -190,7 +190,7 @@ module Geocoder
|
|
|
190
190
|
else
|
|
191
191
|
JSON.parse(data)
|
|
192
192
|
end
|
|
193
|
-
rescue
|
|
193
|
+
rescue
|
|
194
194
|
raise_error(ResponseParseError.new(data)) or Geocoder.log(:warn, "Geocoding API's response was not valid JSON: #{data}")
|
|
195
195
|
end
|
|
196
196
|
|
|
@@ -271,20 +271,20 @@ module Geocoder
|
|
|
271
271
|
# return the response object.
|
|
272
272
|
#
|
|
273
273
|
def make_api_request(query)
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
)
|
|
284
|
-
end
|
|
285
|
-
client.request(req)
|
|
274
|
+
uri = URI.parse(query_url(query))
|
|
275
|
+
Geocoder.log(:debug, "Geocoder: HTTP request being made for #{uri.to_s}")
|
|
276
|
+
http_client.start(uri.host, uri.port, use_ssl: use_ssl?, open_timeout: configuration.timeout, read_timeout: configuration.timeout) do |client|
|
|
277
|
+
req = Net::HTTP::Get.new(uri.request_uri, configuration.http_headers)
|
|
278
|
+
if configuration.basic_auth[:user] and configuration.basic_auth[:password]
|
|
279
|
+
req.basic_auth(
|
|
280
|
+
configuration.basic_auth[:user],
|
|
281
|
+
configuration.basic_auth[:password]
|
|
282
|
+
)
|
|
286
283
|
end
|
|
284
|
+
client.request(req)
|
|
287
285
|
end
|
|
286
|
+
rescue Timeout::Error
|
|
287
|
+
raise Geocoder::LookupTimeout
|
|
288
288
|
end
|
|
289
289
|
|
|
290
290
|
def use_ssl?
|
|
@@ -8,11 +8,15 @@ module Geocoder::Lookup
|
|
|
8
8
|
"Geocoder.us"
|
|
9
9
|
end
|
|
10
10
|
|
|
11
|
+
def supported_protocols
|
|
12
|
+
[:http]
|
|
13
|
+
end
|
|
14
|
+
|
|
11
15
|
def query_url(query)
|
|
12
16
|
if configuration.api_key
|
|
13
|
-
"
|
|
17
|
+
"#{protocol}://#{configuration.api_key}@geocoder.us/member/service/csv/geocode?" + url_query_string(query)
|
|
14
18
|
else
|
|
15
|
-
"
|
|
19
|
+
"#{protocol}://geocoder.us/service/csv/geocode?" + url_query_string(query)
|
|
16
20
|
end
|
|
17
21
|
end
|
|
18
22
|
|
|
@@ -4,6 +4,8 @@ require 'geocoder/results/geoip2'
|
|
|
4
4
|
module Geocoder
|
|
5
5
|
module Lookup
|
|
6
6
|
class Geoip2 < Base
|
|
7
|
+
attr_reader :gem_name
|
|
8
|
+
|
|
7
9
|
def initialize
|
|
8
10
|
unless configuration[:file].nil?
|
|
9
11
|
begin
|
|
@@ -12,6 +14,8 @@ module Geocoder
|
|
|
12
14
|
rescue LoadError
|
|
13
15
|
raise "Could not load Maxmind DB dependency. To use the GeoIP2 lookup you must add the #{@gem_name} gem to your Gemfile or have it installed in your system."
|
|
14
16
|
end
|
|
17
|
+
|
|
18
|
+
@mmdb = db_class.new(configuration[:file].to_s)
|
|
15
19
|
end
|
|
16
20
|
super
|
|
17
21
|
end
|
|
@@ -26,13 +30,14 @@ module Geocoder
|
|
|
26
30
|
|
|
27
31
|
private
|
|
28
32
|
|
|
33
|
+
def db_class
|
|
34
|
+
gem_name == 'hive_geoip2' ? Hive::GeoIP2 : MaxMindDB
|
|
35
|
+
end
|
|
36
|
+
|
|
29
37
|
def results(query)
|
|
30
38
|
return [] unless configuration[:file]
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
else
|
|
34
|
-
result = MaxMindDB.new(configuration[:file].to_s).lookup(query.to_s)
|
|
35
|
-
end
|
|
39
|
+
|
|
40
|
+
result = @mmdb.lookup(query.to_s)
|
|
36
41
|
result.nil? ? [] : [result]
|
|
37
42
|
end
|
|
38
43
|
end
|