geocoder 1.4.4 → 1.4.5

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 7d93c7deeb30de425af22733c64e2a6297f610a4
4
- data.tar.gz: 46c3d2b77ddb91bee2156bebebf102b73c1fd328
3
+ metadata.gz: aafaf6b62b506a191b17fcdde0bb1b325769fc8a
4
+ data.tar.gz: 61f40f9ac0c89f3bcf25ff417515b60b2421f14c
5
5
  SHA512:
6
- metadata.gz: 327e8d5c40c31aa09be5b8e9d0b55ec18e74a8da166d0d65882fe31760182c4d96b36bfe3c0261cdeb2a5b91aefca204114d7bcc54dd46ea68e1cb7f0b7e3fd0
7
- data.tar.gz: 5ad20ece66d7117b6e0928dd19daf8f602496a9b033fcf6833f58a0f6d9efd87388289681adf3a96a7c4ad71e159d7b06c956aca2e3646cdf8087bd4a570aec7
6
+ metadata.gz: 0ee51c45355b969282a51fd79725e5fae1538dc56a5b60e659c0b2d3e072c72e83886f9d0d145928e977ed457d4753f5e0cbd424c0fe5c673d1f741a11a200d2
7
+ data.tar.gz: 6e4816464c910b0be21bc75d78c2290aabb44b1563af5bac86e6db48b6bae83a5b62c80b8c88c21240b0f8d45c75079e79557698e3aa8ebca4dccfbd99208eb3
@@ -3,6 +3,15 @@ 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.4.5 (2017 Nov 29)
7
+ -------------------
8
+ * Add support for :pickpoint lookup (thanks github.com/cylon-v).
9
+ * Add support for :db_ip_com lookup (thanks github.com/cv).
10
+ * Change FreeGeoIP host to freegeoip.net.
11
+ * Allow search radius to be a symbol representing a column in DB (thanks github.com/leonelgalan).
12
+ * Add support for new parameters and improved error handling for several lookups.
13
+ * Fix bug in SQL when searching for objects across 180th meridian.
14
+
6
15
  1.4.4 (2017 May 17)
7
16
  -------------------
8
17
  * Use HTTPS by default for :freegeoip (thanks github.com/mehanoid).
data/README.md CHANGED
@@ -114,6 +114,10 @@ Geocoder will print warnings if you exceed the rate limit for your geocoding ser
114
114
 
115
115
  rake geocode:all CLASS=YourModel SLEEP=0.25 BATCH=100
116
116
 
117
+ To avoid per-day limit issues (for example if you are trying to geocode thousands of objects and don't want to reach the limit), you can add a `LIMIT` option. Warning: This will ignore the `BATCH` value if provided.
118
+
119
+ rake geocode:all CLASS=YourModel LIMIT=1000
120
+
117
121
  ### Avoiding Unnecessary API Requests
118
122
 
119
123
  Geocoding only needs to be performed under certain conditions. To avoid unnecessary work (and quota usage) you will probably want to geocode an object only when:
@@ -176,11 +180,11 @@ Some utility methods are also available:
176
180
  # look up coordinates of some location (like searching Google Maps)
177
181
  Geocoder.coordinates("25 Main St, Cooperstown, NY")
178
182
  => [42.700149, -74.922767]
179
-
183
+
180
184
  # distance between Eiffel Tower and Empire State Building
181
185
  Geocoder::Calculations.distance_between([47.858205,2.294359], [40.748433,-73.985655])
182
186
  => 3619.77359999382 # in configured units (default miles)
183
-
187
+
184
188
  # find the geographic center (aka center of gravity) of objects or points
185
189
  Geocoder::Calculations.geographic_center([city1, city2, [40.22,-73.99], city4])
186
190
  => [35.14968, -90.048929]
@@ -333,29 +337,29 @@ Some common configuration options are:
333
337
 
334
338
  # config/initializers/geocoder.rb
335
339
  Geocoder.configure(
336
-
340
+
337
341
  # geocoding service (see below for supported options):
338
342
  :lookup => :yandex,
339
-
343
+
340
344
  # IP address geocoding service (see below for supported options):
341
345
  :ip_lookup => :maxmind,
342
-
346
+
343
347
  # to use an API key:
344
348
  :api_key => "...",
345
-
349
+
346
350
  # geocoding service request timeout, in seconds (default 3):
347
351
  :timeout => 5,
348
-
352
+
349
353
  # set default units to kilometers:
350
354
  :units => :km,
351
-
355
+
352
356
  # caching (see below for details):
353
357
  :cache => Redis.new,
354
358
  :cache_prefix => "..."
355
-
359
+
356
360
  )
357
361
 
358
- Please see `lib/geocoder/configuration.rb` for a complete list of configuration options. Additionally, some lookups have their own configuration options, some of which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter:
362
+ Please see [`lib/geocoder/configuration.rb`](https://github.com/alexreisner/geocoder/blob/master/lib/geocoder/configuration.rb) for a complete list of configuration options. Additionally, some lookups have their own configuration options, some of which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter:
359
363
 
360
364
  # with Google:
361
365
  Geocoder.search("Paris", :bounds => [[32.1,-95.9], [33.9,-94.3]])
@@ -369,27 +373,41 @@ Or, to search within a particular region with Google:
369
373
 
370
374
  Geocoder.search("...", :params => {:region => "..."})
371
375
 
372
- You can also configure multiple geocoding services at once, like this:
376
+ Or, to use parameters in your model:
377
+
378
+ class Venue
379
+
380
+ # build an address from street, city, and state attributes
381
+ geocoded_by :address_from_components, :params => {:region => "..."}
382
+
383
+ # store the fetched address in the full_address attribute
384
+ reverse_geocoded_by :latitude, :longitude, :address => :full_address, :params => {:region => "..."}
385
+ end
386
+
387
+
388
+ ### Configure Multiple Services
389
+
390
+ You can configure multiple geocoding services at once, like this:
373
391
 
374
392
  Geocoder.configure(
375
393
 
376
394
  :timeout => 2,
377
395
  :cache => Redis.new,
378
-
396
+
379
397
  :yandex => {
380
398
  :api_key => "...",
381
399
  :timeout => 5
382
400
  },
383
-
401
+
384
402
  :baidu => {
385
403
  :api_key => "..."
386
404
  },
387
-
405
+
388
406
  :maxmind => {
389
407
  :api_key => "...",
390
408
  :service => :omni
391
409
  }
392
-
410
+
393
411
  )
394
412
 
395
413
  The above combines global and service-specific options and could be useful if you specify different geocoding services for different models or under different conditions. Lookup-specific settings override global settings. In the above example, the timeout for all lookups would be 2 seconds, except for Yandex which would be 5.
@@ -407,7 +425,9 @@ The following is a comparison of the supported geocoding APIs. The "Limitations"
407
425
  * **Region**: world
408
426
  * **SSL support**: yes (required if key is used)
409
427
  * **Languages**: see https://developers.google.com/maps/faq#languagesupport
410
- * **Extra options**: `:bounds` - pass SW and NE coordinates as an array of two arrays to bias results towards a viewport
428
+ * **Extra params**:
429
+ * `:bounds` - pass SW and NE coordinates as an array of two arrays to bias results towards a viewport
430
+ * `:google_place_id` - pass `true` if search query is a Google Place ID
411
431
  * **Documentation**: https://developers.google.com/maps/documentation/geocoding/intro
412
432
  * **Terms of Service**: http://code.google.com/apis/maps/terms.html#section_10_12
413
433
  * **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..."
@@ -463,22 +483,34 @@ The [Google Places Search API](https://developers.google.com/places/web-service/
463
483
  * **Terms of Service**: http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
464
484
  * **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)
465
485
 
486
+ #### PickPoint (`:pickpoint`)
487
+
488
+ * **API key**: required
489
+ * **Key signup**: [https://pickpoint.io](https://pickpoint.io)
490
+ * **Quota**: 2500 requests / day for free non-commercial usage, commercial plans are [available](https://pickpoint.io/#pricing). No rate limit.
491
+ * **Region**: world
492
+ * **SSL support**: required
493
+ * **Languages**: worldwide
494
+ * **Documentation**: [https://pickpoint.io/api-reference](https://pickpoint.io/api-reference)
495
+ * **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
496
+
497
+
466
498
  #### LocationIQ (`:location_iq`)
467
499
 
468
500
  * **API key**: required
469
- * **Quota**: 6 request/second (30k req/day), then ability to purchase more
501
+ * **Quota**: 60 requests/minute (2 req/sec, 10k req/day), then [ability to purchase more](http://locationiq.org/#pricing)
470
502
  * **Region**: world
471
503
  * **SSL support**: yes
472
504
  * **Languages**: ?
473
- * **Documentation**: http://locationiq.org/#docs
505
+ * **Documentation**: https://locationiq.org/#docs
474
506
  * **Terms of Service**: https://unwiredlabs.com/tos
475
- * **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
507
+ * **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](https://www.openstreetmap.org/copyright)
476
508
 
477
509
  #### OpenCageData (`:opencagedata`)
478
510
 
479
511
  * **API key**: required
480
512
  * **Key signup**: http://geocoder.opencagedata.com
481
- * **Quota**: 2500 requests / day, then ability to purchase more (free during beta)
513
+ * **Quota**: 2500 requests / day, then [ability to purchase more](https://geocoder.opencagedata.com/pricing)
482
514
  * **Region**: world
483
515
  * **SSL support**: yes
484
516
  * **Languages**: worldwide
@@ -507,18 +539,6 @@ The [Google Places Search API](https://developers.google.com/places/web-service/
507
539
  * **Terms of Service**: http://geocoder.ca/?terms=1
508
540
  * **Limitations**: "Under no circumstances can our data be re-distributed or re-sold by anyone to other parties without our written permission."
509
541
 
510
- #### Geocoder.us (`:geocoder_us`)
511
-
512
- * **API key**: HTTP Basic Auth
513
- * **Sign up**: http://geocoder.us/user/signup
514
- * **Quota**: You can purchase 20,000 credits at a time for $50
515
- * **Region**: US
516
- * **SSL support**: no
517
- * **Languages**: English
518
- * **Documentation**: http://geocoder.us/help/
519
- * **Terms of Service**: http://geocoder.us/terms.shtml
520
- * **Limitations**: ?
521
-
522
542
  #### Mapbox (`:mapbox`)
523
543
 
524
544
  * **API key**: required
@@ -528,6 +548,12 @@ The [Google Places Search API](https://developers.google.com/places/web-service/
528
548
  * **Region**: complete coverage of US and Canada, partial coverage elsewhere (see for details: https://www.mapbox.com/developers/api/geocoding/#coverage)
529
549
  * **SSL support**: yes
530
550
  * **Languages**: English
551
+ * **Extra params** (see Mapbox docs for more):
552
+ * `:country` - restrict results to a specific country, e.g., `us` or `ca`
553
+ * `:types` - restrict results to categories such as `address`,
554
+ `neighborhood`, `postcode`
555
+ * `:proximity` - bias results toward a `lng,lat`, e.g.,
556
+ `params: { proximity: "-84.0,42.5" }`
531
557
  * **Documentation**: https://www.mapbox.com/developers/api/geocoding/
532
558
  * **Terms of Service**: https://www.mapbox.com/tos/
533
559
  * **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.
@@ -585,24 +611,24 @@ The [Google Places Search API](https://developers.google.com/places/web-service/
585
611
  #### Mapzen (`:mapzen`)
586
612
 
587
613
  * **API key**: required
588
- * **Quota**: 6/sec, up to 30k per day, paid plan info at https://mapzen.com/documentation/search/api-keys-rate-limits/#rate-limits
614
+ * **Quota**: 25,000 free requests/month and [ability to purchase more](https://mapzen.com/pricing/)
589
615
  * **Region**: world
590
616
  * **SSL support**: yes
591
- * **Languages**: en
617
+ * **Languages**: en; see https://mapzen.com/documentation/search/language-codes/
592
618
  * **Documentation**: https://mapzen.com/documentation/search/search/
593
619
  * **Terms of Service**: http://mapzen.com/terms
594
- * **Limitations**: ?
620
+ * **Limitations**: [You must provide attribution](https://mapzen.com/rights/)
595
621
  * **Notes**: Mapzen is the primary author of Pelias and offers Pelias-as-a-service in free and paid versions https://mapzen.com/pelias.
596
622
 
597
623
  #### Pelias (`:pelias`)
598
624
 
599
- * **API key**: required
625
+ * **API key**: configurable (self-hosted service)
600
626
  * **Quota**: none (self-hosted service)
601
627
  * **Region**: world
602
628
  * **SSL support**: yes
603
- * **Languages**: en
604
- * **Documentation**: https://mapzen.com/documentation/search/search/
605
- * **Terms of Service**: http://mapzen.com/terms
629
+ * **Languages**: en; see https://mapzen.com/documentation/search/language-codes/
630
+ * **Documentation**: http://pelias.io/
631
+ * **Terms of Service**: http://pelias.io/data_licenses.html
606
632
  * **Limitations**: See terms
607
633
  * **Notes**: Configure your self-hosted pelias with the `endpoint` option: `Geocoder.configure(:lookup => :pelias, :api_key => 'your_api_key', :pelias => {:endpoint => 'self.hosted/pelias'})`. Defaults to `localhost`.
608
634
 
@@ -611,7 +637,7 @@ The [Google Places Search API](https://developers.google.com/places/web-service/
611
637
  Data Science Toolkit provides an API whose response format is like Google's but which can be set up as a privately hosted service.
612
638
 
613
639
  * **API key**: none
614
- * **Quota**: None quota if you are self-hosting the service.
640
+ * **Quota**: No quota if you are self-hosting the service.
615
641
  * **Region**: world
616
642
  * **SSL support**: ?
617
643
  * **Languages**: en
@@ -635,7 +661,7 @@ Data Science Toolkit provides an API whose response format is like Google's but
635
661
  #### Geocodio (`:geocodio`)
636
662
 
637
663
  * **API key**: required
638
- * **Quota**: 2,500 free requests/day then purchase $.001 for each, also has volume pricing and plans
664
+ * **Quota**: 2,500 free requests/day then purchase $0.0005 for each, also has volume pricing and plans.
639
665
  * **Region**: US
640
666
  * **SSL support**: yes
641
667
  * **Languages**: en
@@ -646,7 +672,7 @@ Data Science Toolkit provides an API whose response format is like Google's but
646
672
  #### SmartyStreets (`:smarty_streets`)
647
673
 
648
674
  * **API key**: requires auth_id and auth_token (set `Geocoder.configure(:api_key => [id, token])`)
649
- * **Quota**: 10,000 free, 250/month then purchase at sliding scale.
675
+ * **Quota**: 250/month then purchase at sliding scale.
650
676
  * **Region**: US
651
677
  * **SSL support**: yes (required)
652
678
  * **Languages**: en
@@ -730,7 +756,7 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
730
756
  #### FreeGeoIP (`:freegeoip`)
731
757
 
732
758
  * **API key**: none
733
- * **Quota**: 10000 requests per hour. After reaching the hourly quota, all of your requests will result in HTTP 403 (Forbidden) until it clears up on the next roll over.
759
+ * **Quota**: 15,000 requests per hour. After reaching the hourly quota, all of your requests will result in HTTP 403 (Forbidden) until it clears up on the next roll over.
734
760
  * **Region**: world
735
761
  * **SSL support**: no
736
762
  * **Languages**: English
@@ -761,7 +787,8 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
761
787
  * **Documentation**: https://market.mashape.com/fcambus/telize
762
788
  * **Terms of Service**: ?
763
789
  * **Limitations**: ?
764
- * **Notes**: To use Telize set `Geocoder.configure(:ip_lookup => :telize, :api_key => "your_api_key")`.
790
+ * **Notes**: To use Telize set `Geocoder.configure(:ip_lookup => :telize, :api_key => "your_api_key")`. Or configure your self-hosted telize with the `host` option: `Geocoder.configure(:ip_lookup => :telize, :telize => {:host => "localhost"})`.
791
+
765
792
 
766
793
  #### MaxMind Legacy Web Services (`:maxmind`)
767
794
 
@@ -819,6 +846,16 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
819
846
  * **Documentation**: http://ip-api.com/docs/
820
847
  * **Terms of Service**: https://signup.ip-api.com/terms
821
848
 
849
+ #### DB-IP.com (`:db_ip_com`)
850
+
851
+ * **API key**: required
852
+ * **Quota**: 2,500/day (with free API Key, 50,000/day and up for paid API keys)
853
+ * **Region**: world
854
+ * **SSL support**: yes (with paid API keys - see https://db-ip.com/api/)
855
+ * **Languages**: English (English with free API key, multiple languages with paid API keys)
856
+ * **Documentation**: https://db-ip.com/api/doc.php
857
+ * **Terms of Service**: https://db-ip.com/tos.php
858
+
822
859
  ### IP Address Local Database Services
823
860
 
824
861
  #### MaxMind Local (`:maxmind_local`) - EXPERIMENTAL
@@ -847,7 +884,7 @@ You can generate ActiveRecord migrations and download and import data via provid
847
884
 
848
885
  # generate migration to create tables
849
886
  rails generate geocoder:maxmind:geolite_city
850
-
887
+
851
888
  # download, unpack, and import data
852
889
  rake geocoder:maxmind:geolite:load PACKAGE=city
853
890
 
@@ -936,7 +973,7 @@ For example:
936
973
 
937
974
  # build an address from street, city, and state attributes
938
975
  geocoded_by :address_from_components
939
-
976
+
940
977
  # store the fetched address in the full_address attribute
941
978
  reverse_geocoded_by :latitude, :longitude, :address => :full_address
942
979
  end
@@ -948,7 +985,7 @@ However, there can be only one set of latitude/longitude attributes, and whichev
948
985
  geocoded_by :address,
949
986
  :latitude => :fetched_latitude, # this will be overridden by the below
950
987
  :longitude => :fetched_longitude # same here
951
-
988
+
952
989
  reverse_geocoded_by :latitude, :longitude
953
990
  end
954
991
 
@@ -976,7 +1013,7 @@ For example:
976
1013
 
977
1014
  after_validation :reverse_geocode, :if => :has_coordinates
978
1015
  after_validation :geocode, :if => :has_location, :unless => :has_coordinates
979
-
1016
+
980
1017
  end
981
1018
 
982
1019
  Use Outside of Rails
@@ -999,8 +1036,7 @@ When writing tests for an app that uses Geocoder it may be useful to avoid netwo
999
1036
  Geocoder::Lookup::Test.add_stub(
1000
1037
  "New York, NY", [
1001
1038
  {
1002
- 'latitude' => 40.7143528,
1003
- 'longitude' => -74.0059731,
1039
+ 'coordinates' => [40.7143528, -74.0059731],
1004
1040
  'address' => 'New York, NY, USA',
1005
1041
  'state' => 'New York',
1006
1042
  'state_code' => 'NY',
@@ -1010,15 +1046,14 @@ When writing tests for an app that uses Geocoder it may be useful to avoid netwo
1010
1046
  ]
1011
1047
  )
1012
1048
 
1013
- Now, any time Geocoder looks up "New York, NY" its results array will contain one result with the above attributes. You can also set a default stub, to be returned when no other stub is found for a given query:
1049
+ Now, any time Geocoder looks up "New York, NY" its results array will contain one result with the above attributes. Note each lookup requires an exact match to the text you provide as the first argument. The above example would, therefore, not match a request for "New York, NY, USA" and a second stub would need to be created to match that particular request. You can also set a default stub, to be returned when no other stub is found for a given query:
1014
1050
 
1015
1051
  Geocoder.configure(:lookup => :test)
1016
1052
 
1017
1053
  Geocoder::Lookup::Test.set_default_stub(
1018
1054
  [
1019
1055
  {
1020
- 'latitude' => 40.7143528,
1021
- 'longitude' => -74.0059731,
1056
+ 'coordinates' => [40.7143528, -74.0059731],
1022
1057
  'address' => 'New York, NY, USA',
1023
1058
  'state' => 'New York',
1024
1059
  'state_code' => 'NY',
@@ -1197,7 +1232,9 @@ When reporting an issue, please list the version of Geocoder you are using and a
1197
1232
  Please DO NOT use GitHub issues to ask questions about how to use Geocoder. Sites like [StackOverflow](http://www.stackoverflow.com/) are a better forum for such discussions.
1198
1233
 
1199
1234
 
1200
- ### Known Issue
1235
+ ### Known Issues
1236
+
1237
+ #### Using `near` with `includes`
1201
1238
 
1202
1239
  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).
1203
1240
 
@@ -1206,7 +1243,7 @@ Instead of using `includes` to reduce the number of database queries, try using
1206
1243
  # Pass a :select option to the near scope to get the columns you want.
1207
1244
  # Instead of City.near(...).includes(:venues), try:
1208
1245
  City.near("Omaha, NE", 20, :select => "cities.*, venues.*").joins(:venues)
1209
-
1246
+
1210
1247
  # This preload call will normally trigger two queries regardless of the
1211
1248
  # number of results; one query on hotels, and one query on administrators.
1212
1249
  # Instead of Hotel.near(...).includes(:administrator), try:
@@ -1214,6 +1251,10 @@ Instead of using `includes` to reduce the number of database queries, try using
1214
1251
 
1215
1252
  If anyone has a more elegant solution to this problem I am very interested in seeing it.
1216
1253
 
1254
+ #### Using `near` with objects close to the 180th meridian
1255
+
1256
+ The `near` method will not look across the 180th meridian to find objects close to a given point. In practice this is rarely an issue outside of New Zealand and certain surrounding islands. This problem does not exist with the zero-meridian. The problem is due to a shortcoming of the Haversine formula which Geocoder uses to calculate distances.
1257
+
1217
1258
 
1218
1259
  Contributing
1219
1260
  ------------
@@ -1,10 +1,12 @@
1
1
  require 'rails/generators/migration'
2
+ require 'generators/geocoder/migration_version'
2
3
 
3
4
  module Geocoder
4
5
  module Generators
5
6
  module Maxmind
6
7
  class GeoliteCityGenerator < Rails::Generators::Base
7
8
  include Rails::Generators::Migration
9
+ include Generators::MigrationVersion
8
10
 
9
11
  source_root File.expand_path('../templates', __FILE__)
10
12
 
@@ -1,10 +1,12 @@
1
1
  require 'rails/generators/migration'
2
+ require 'generators/geocoder/migration_version'
2
3
 
3
4
  module Geocoder
4
5
  module Generators
5
6
  module Maxmind
6
7
  class GeoliteCountryGenerator < Rails::Generators::Base
7
8
  include Rails::Generators::Migration
9
+ include Generators::MigrationVersion
8
10
 
9
11
  source_root File.expand_path('../templates', __FILE__)
10
12
 
@@ -1,4 +1,4 @@
1
- class GeocoderMaxmindGeoliteCity < ActiveRecord::Migration
1
+ class GeocoderMaxmindGeoliteCity < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
3
  create_table :maxmind_geolite_city_blocks, id: false do |t|
4
4
  t.column :start_ip_num, :bigint, null: false
@@ -1,4 +1,4 @@
1
- class GeocoderMaxmindGeoliteCountry < ActiveRecord::Migration
1
+ class GeocoderMaxmindGeoliteCountry < ActiveRecord::Migration<%= migration_version %>
2
2
  def self.up
3
3
  create_table :maxmind_geolite_country, id: false do |t|
4
4
  t.column :start_ip, :string
@@ -0,0 +1,15 @@
1
+ module Geocoder
2
+ module Generators
3
+ module MigrationVersion
4
+ def rails_5?
5
+ Rails::VERSION::MAJOR == 5
6
+ end
7
+
8
+ def migration_version
9
+ if rails_5?
10
+ "[#{Rails::VERSION::MAJOR}.#{Rails::VERSION::MINOR}]"
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -41,6 +41,7 @@ module Geocoder
41
41
  :opencagedata,
42
42
  :ovi,
43
43
  :pelias,
44
+ :pickpoint,
44
45
  :here,
45
46
  :baidu,
46
47
  :geocodio,
@@ -69,7 +70,8 @@ module Geocoder
69
70
  :pointpin,
70
71
  :maxmind_geoip2,
71
72
  :ipinfo_io,
72
- :ipapi_com
73
+ :ipapi_com,
74
+ :db_ip_com
73
75
  ]
74
76
  end
75
77
 
@@ -286,7 +286,7 @@ module Geocoder
286
286
  end
287
287
  rescue Timeout::Error
288
288
  raise Geocoder::LookupTimeout
289
- rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH
289
+ rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH, Errno::ECONNRESET
290
290
  raise Geocoder::NetworkError
291
291
  end
292
292
 
@@ -0,0 +1,49 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/db_ip_com'
3
+
4
+ module Geocoder::Lookup
5
+ class DbIpCom < Base
6
+
7
+ def name
8
+ 'DB-IP.com'
9
+ end
10
+
11
+ def supported_protocols
12
+ [:https, :http]
13
+ end
14
+
15
+ def required_api_key_parts
16
+ ['api_key']
17
+ end
18
+
19
+ def query_url(query)
20
+ query_params = if query.options[:params]
21
+ "?#{url_query_string(query)}"
22
+ end
23
+
24
+ "#{protocol}://api.db-ip.com/v2/#{configuration.api_key}/#{query.sanitized_text}#{query_params}"
25
+ end
26
+
27
+ private
28
+
29
+ def results(query)
30
+ return [] unless (doc = fetch_data(query))
31
+
32
+ case doc['error']
33
+ when 'maximum number of queries per day exceeded'
34
+ raise_error Geocoder::OverQueryLimitError ||
35
+ Geocoder.log(:warn, 'DB-API query limit exceeded.')
36
+
37
+ when 'invalid API key'
38
+ raise_error Geocoder::InvalidApiKey ||
39
+ Geocoder.log(:warn, 'Invalid DB-IP API key.')
40
+ when nil
41
+ [doc]
42
+
43
+ else
44
+ raise_error Geocoder::Error ||
45
+ Geocoder.log(:warn, "Request failed: #{doc['error']}")
46
+ end
47
+ end
48
+ end
49
+ end
@@ -50,7 +50,7 @@ module Geocoder::Lookup
50
50
  end
51
51
 
52
52
  def host
53
- configuration[:host] || "freegeoip.io"
53
+ configuration[:host] || "freegeoip.net"
54
54
  end
55
55
  end
56
56
  end
@@ -63,10 +63,14 @@ module Geocoder::Lookup
63
63
 
64
64
  def query_url_google_params(query)
65
65
  params = {
66
- (query.reverse_geocode? ? :latlng : :address) => query.sanitized_text,
67
66
  :sensor => "false",
68
67
  :language => (query.language || configuration.language)
69
68
  }
69
+ if query.options[:google_place_id]
70
+ params[:place_id] = query.sanitized_text
71
+ else
72
+ params[(query.reverse_geocode? ? :latlng : :address)] = query.sanitized_text
73
+ end
70
74
  unless (bounds = query.options[:bounds]).nil?
71
75
  params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join('|')
72
76
  end
@@ -12,9 +12,8 @@ module Geocoder::Lookup
12
12
  end
13
13
 
14
14
  def query_url(query)
15
- method = query.reverse_geocode? ? "reverse.php" : "search.php"
16
- host = configuration[:host] || "locationiq.org/v1"
17
- "#{protocol}://#{host}/#{method}?key=#{configuration.api_key}&" + url_query_string(query)
15
+ method = query.reverse_geocode? ? "reverse" : "search"
16
+ "#{protocol}://locationiq.org/v1/#{method}.php?key=#{configuration.api_key}&" + url_query_string(query)
18
17
  end
19
18
 
20
19
  private
@@ -22,8 +21,17 @@ module Geocoder::Lookup
22
21
  def results(query)
23
22
  return [] unless doc = fetch_data(query)
24
23
 
25
- if !doc.is_a?(Array) && doc['error'] =~ /Invalid\skey/
26
- raise_error(Geocoder::InvalidApiKey, doc['error'])
24
+ if !doc.is_a?(Array)
25
+ case doc['error']
26
+ when "Invalid key"
27
+ raise_error(Geocoder::InvalidApiKey, doc['error'])
28
+ when "Key not active - Please write to contact@unwiredlabs.com"
29
+ raise_error(Geocoder::RequestDenied, doc['error'])
30
+ when "Rate Limited"
31
+ raise_error(Geocoder::OverQueryLimitError, doc['error'])
32
+ when "Unknown error - Please try again after some time"
33
+ raise_error(Geocoder::InvalidRequest, doc['error'])
34
+ end
27
35
  end
28
36
 
29
37
  doc.is_a?(Array) ? doc : [doc]
@@ -9,7 +9,8 @@ module Geocoder::Lookup
9
9
  end
10
10
 
11
11
  def query_url(query)
12
- "#{protocol}://api.mapbox.com/geocoding/v5/#{dataset}/#{url_query_string(query)}.json?access_token=#{configuration.api_key}"
12
+ path = "#{mapbox_search_term(query)}.json?#{url_query_string(query)}"
13
+ "#{protocol}://api.mapbox.com/geocoding/v5/#{dataset}/#{path}"
13
14
  end
14
15
 
15
16
  private # ---------------------------------------------------------------
@@ -25,7 +26,11 @@ module Geocoder::Lookup
25
26
  end
26
27
  end
27
28
 
28
- def url_query_string(query)
29
+ def query_url_params(query)
30
+ {access_token: configuration.api_key}.merge(super(query))
31
+ end
32
+
33
+ def mapbox_search_term(query)
29
34
  require 'cgi' unless defined?(CGI) && defined?(CGI.escape)
30
35
  if query.reverse_geocode?
31
36
  lat,lon = query.coordinates
@@ -47,7 +47,7 @@ module Geocoder::Lookup
47
47
  :language => (query.language || configuration.language)
48
48
  }.merge(super)
49
49
 
50
- [:countrycode, :min_confidence, :no_dedupe, :no_annotations, :no_record, :limit].each do |option|
50
+ [:abbrv, :countrycode, :min_confidence, :no_dedupe, :no_annotations, :no_record, :limit].each do |option|
51
51
  unless (option_value = query.options[option]).nil?
52
52
  params[option] = option_value
53
53
  end
@@ -0,0 +1,35 @@
1
+ require "geocoder/lookups/nominatim"
2
+ require "geocoder/results/pickpoint"
3
+
4
+ module Geocoder::Lookup
5
+ class Pickpoint < Nominatim
6
+ def name
7
+ "Pickpoint"
8
+ end
9
+
10
+ def supported_protocols
11
+ [:https]
12
+ end
13
+
14
+ def required_api_key_parts
15
+ ["api_key"]
16
+ end
17
+
18
+ def query_url(query)
19
+ method = query.reverse_geocode? ? "reverse" : "forward"
20
+ "#{protocol}://api.pickpoint.io/v1/#{method}?key=#{configuration.api_key}&" + url_query_string(query)
21
+ end
22
+
23
+ private
24
+
25
+ def results(query)
26
+ return [] unless doc = fetch_data(query)
27
+
28
+ if !doc.is_a?(Array) && doc['message'] == 'Unauthorized'
29
+ raise_error(Geocoder::InvalidApiKey, 'Unauthorized')
30
+ end
31
+
32
+ doc.is_a?(Array) ? doc : [doc]
33
+ end
34
+ end
35
+ end
@@ -47,12 +47,16 @@ module Geocoder::Lookup
47
47
  else
48
48
  q = query.sanitized_text
49
49
  end
50
- {
50
+ params = {
51
51
  :geocode => q,
52
52
  :format => "json",
53
53
  :plng => "#{query.language || configuration.language}", # supports ru, uk, be
54
54
  :key => configuration.api_key
55
- }.merge(super)
55
+ }
56
+ unless (bounds = query.options[:bounds]).nil?
57
+ params[:bbox] = bounds.map{ |point| "%f,%f" % point }.join('~')
58
+ end
59
+ params.merge(super)
56
60
  end
57
61
  end
58
62
  end
@@ -18,7 +18,8 @@ module Geocoder
18
18
  :units => options[:units],
19
19
  :method => options[:method],
20
20
  :lookup => options[:lookup],
21
- :language => options[:language]
21
+ :language => options[:language],
22
+ :params => options[:params]
22
23
  )
23
24
  end
24
25
 
@@ -35,7 +36,8 @@ module Geocoder
35
36
  :units => options[:units],
36
37
  :method => options[:method],
37
38
  :lookup => options[:lookup],
38
- :language => options[:language]
39
+ :language => options[:language],
40
+ :params => options[:params]
39
41
  )
40
42
  end
41
43
 
@@ -47,4 +49,3 @@ module Geocoder
47
49
  end
48
50
  end
49
51
  end
50
-
@@ -0,0 +1,63 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class DbIpCom < Base
5
+
6
+ def coordinates
7
+ ['latitude', 'longitude'].map{ |coordinate_name| @data[coordinate_name] }
8
+ end
9
+
10
+ def address(format = :full)
11
+ s = state_code.to_s == "" ? "" : ", #{state_code}"
12
+ "#{city}#{s} #{zip_code}, #{country_name}".sub(/^[ ,]*/, "")
13
+ end
14
+
15
+ def city
16
+ @data['city']
17
+ end
18
+
19
+ def district
20
+ @data['district']
21
+ end
22
+
23
+ def state_code
24
+ @data['stateProv']
25
+ end
26
+ alias_method :state, :state_code
27
+
28
+ def zip_code
29
+ @data['zipCode']
30
+ end
31
+ alias_method :postal_code, :zip_code
32
+
33
+ def country_name
34
+ @data['countryName']
35
+ end
36
+ alias_method :country, :country_name
37
+
38
+ def country_code
39
+ @data['countryCode']
40
+ end
41
+
42
+ def continent_name
43
+ @data['continentName']
44
+ end
45
+ alias_method :continent, :continent_name
46
+
47
+ def continent_code
48
+ @data['continentCode']
49
+ end
50
+
51
+ def time_zone
52
+ @data['timeZone']
53
+ end
54
+
55
+ def gmt_offset
56
+ @data['gmtOffset']
57
+ end
58
+
59
+ def currency_code
60
+ @data['currencyCode']
61
+ end
62
+ end
63
+ end
@@ -64,6 +64,18 @@ module Geocoder::Result
64
64
  @data['address']['suburb']
65
65
  end
66
66
 
67
+ def city_district
68
+ @data['address']['city_district']
69
+ end
70
+
71
+ def state_district
72
+ @data['address']['state_district']
73
+ end
74
+
75
+ def neighbourhood
76
+ @data['address']['neighbourhood']
77
+ end
78
+
67
79
  def coordinates
68
80
  [@data['lat'].to_f, @data['lon'].to_f]
69
81
  end
@@ -75,6 +75,15 @@ module Geocoder::Result
75
75
  [south, west, north, east]
76
76
  end
77
77
 
78
+ def time_zone
79
+ # The OpenCage API documentation states that `annotations` is available
80
+ # "when possible" https://geocoder.opencagedata.com/api#annotations
81
+ @data
82
+ .fetch('annotations', {})
83
+ .fetch('timezone', {})
84
+ .fetch('name', nil)
85
+ end
86
+
78
87
  def self.response_attributes
79
88
  %w[boundingbox license
80
89
  formatted stadium]
@@ -0,0 +1,6 @@
1
+ require 'geocoder/results/nominatim'
2
+
3
+ module Geocoder::Result
4
+ class Pickpoint < Nominatim
5
+ end
6
+ end
@@ -47,8 +47,8 @@ module Geocoder
47
47
  spans = "#{lat_attr} BETWEEN #{sw_lat} AND #{ne_lat} AND "
48
48
  # handle box that spans 180 longitude
49
49
  if sw_lng.to_f > ne_lng.to_f
50
- spans + "#{lon_attr} BETWEEN #{sw_lng} AND 180 OR " +
51
- "#{lon_attr} BETWEEN -180 AND #{ne_lng}"
50
+ spans + "(#{lon_attr} BETWEEN #{sw_lng} AND 180 OR " +
51
+ "#{lon_attr} BETWEEN -180 AND #{ne_lng})"
52
52
  else
53
53
  spans + "#{lon_attr} BETWEEN #{sw_lng} AND #{ne_lng}"
54
54
  end
@@ -131,7 +131,11 @@ module Geocoder::Store
131
131
  distance_column = options.fetch(:distance_column) { 'distance' }
132
132
  bearing_column = options.fetch(:bearing_column) { 'bearing' }
133
133
 
134
- b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options)
134
+ # If radius is a DB column name, bounding box should include
135
+ # all rows within the maximum radius appearing in that column.
136
+ # Note: performance is dependent on variability of radii.
137
+ bb_radius = radius.is_a?(Symbol) ? maximum(radius) : radius
138
+ b = Geocoder::Calculations.bounding_box([latitude, longitude], bb_radius, options)
135
139
  args = b + [
136
140
  full_column_name(latitude_attribute),
137
141
  full_column_name(longitude_attribute)
@@ -142,7 +146,16 @@ module Geocoder::Store
142
146
  conditions = bounding_box_conditions
143
147
  else
144
148
  min_radius = options.fetch(:min_radius, 0).to_f
145
- conditions = [bounding_box_conditions + " AND (#{distance}) BETWEEN ? AND ?", min_radius, radius]
149
+ # if radius is a DB column name,
150
+ # find rows between min_radius and value in column
151
+ if radius.is_a?(Symbol)
152
+ c = "BETWEEN ? AND #{radius}"
153
+ a = [min_radius]
154
+ else
155
+ c = "BETWEEN ? AND ?"
156
+ a = [min_radius, radius]
157
+ end
158
+ conditions = [bounding_box_conditions + " AND (#{distance}) " + c] + a
146
159
  end
147
160
  {
148
161
  :select => select_clause(options[:select],
@@ -113,4 +113,3 @@ module Geocoder
113
113
  end
114
114
  end
115
115
  end
116
-
@@ -1,3 +1,3 @@
1
1
  module Geocoder
2
- VERSION = "1.4.4"
2
+ VERSION = "1.4.5"
3
3
  end
@@ -1,4 +1,4 @@
1
- require "geocoder/models/mongoid"
1
+ require "geocoder/models/mongoid"
2
2
 
3
3
  namespace :geocode do
4
4
  desc "Geocode all objects without coordinates."
@@ -7,6 +7,7 @@ namespace :geocode do
7
7
  sleep_timer = ENV['SLEEP'] || ENV['sleep']
8
8
  batch = ENV['BATCH'] || ENV['batch']
9
9
  reverse = ENV['REVERSE'] || ENV['reverse']
10
+ limit = ENV['LIMIT'] || ENV['limit']
10
11
  raise "Please specify a CLASS (model)" unless class_name
11
12
  klass = class_from_string(class_name)
12
13
  batch = (batch.to_i unless batch.nil?) || 1000
@@ -20,13 +21,20 @@ namespace :geocode do
20
21
  }
21
22
 
22
23
  scope = reverse ? klass.not_reverse_geocoded : klass.not_geocoded
24
+ scope = scope.limit(limit) if limit
23
25
  if orm == 'mongoid'
24
26
  scope.each do |obj|
25
27
  geocode_record.call(obj)
26
28
  end
27
29
  elsif orm == 'active_record'
28
- scope.find_each(batch_size: batch) do |obj|
29
- geocode_record.call(obj)
30
+ if limit
31
+ scope.each do |obj|
32
+ geocode_record.call(obj)
33
+ end
34
+ else
35
+ scope.find_each(batch_size: batch) do |obj|
36
+ geocode_record.call(obj)
37
+ end
30
38
  end
31
39
  end
32
40
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geocoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.4
4
+ version: 1.4.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Reisner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-17 00:00:00.000000000 Z
11
+ date: 2017-11-29 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Provides object geocoding (by street or IP address), reverse geocoding
14
14
  (coordinates to street address), distance queries for ActiveRecord and Mongoid,
@@ -35,6 +35,7 @@ files:
35
35
  - lib/generators/geocoder/maxmind/geolite_country_generator.rb
36
36
  - lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb
37
37
  - lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb
38
+ - lib/generators/geocoder/migration_version.rb
38
39
  - lib/geocoder.rb
39
40
  - lib/geocoder/cache.rb
40
41
  - lib/geocoder/calculations.rb
@@ -53,6 +54,7 @@ files:
53
54
  - lib/geocoder/lookups/ban_data_gouv_fr.rb
54
55
  - lib/geocoder/lookups/base.rb
55
56
  - lib/geocoder/lookups/bing.rb
57
+ - lib/geocoder/lookups/db_ip_com.rb
56
58
  - lib/geocoder/lookups/dstk.rb
57
59
  - lib/geocoder/lookups/esri.rb
58
60
  - lib/geocoder/lookups/freegeoip.rb
@@ -81,6 +83,7 @@ files:
81
83
  - lib/geocoder/lookups/opencagedata.rb
82
84
  - lib/geocoder/lookups/ovi.rb
83
85
  - lib/geocoder/lookups/pelias.rb
86
+ - lib/geocoder/lookups/pickpoint.rb
84
87
  - lib/geocoder/lookups/pointpin.rb
85
88
  - lib/geocoder/lookups/postcode_anywhere_uk.rb
86
89
  - lib/geocoder/lookups/smarty_streets.rb
@@ -101,6 +104,7 @@ files:
101
104
  - lib/geocoder/results/ban_data_gouv_fr.rb
102
105
  - lib/geocoder/results/base.rb
103
106
  - lib/geocoder/results/bing.rb
107
+ - lib/geocoder/results/db_ip_com.rb
104
108
  - lib/geocoder/results/dstk.rb
105
109
  - lib/geocoder/results/esri.rb
106
110
  - lib/geocoder/results/freegeoip.rb
@@ -129,6 +133,7 @@ files:
129
133
  - lib/geocoder/results/opencagedata.rb
130
134
  - lib/geocoder/results/ovi.rb
131
135
  - lib/geocoder/results/pelias.rb
136
+ - lib/geocoder/results/pickpoint.rb
132
137
  - lib/geocoder/results/pointpin.rb
133
138
  - lib/geocoder/results/postcode_anywhere_uk.rb
134
139
  - lib/geocoder/results/smarty_streets.rb
@@ -149,7 +154,9 @@ files:
149
154
  homepage: http://www.rubygeocoder.com
150
155
  licenses:
151
156
  - MIT
152
- metadata: {}
157
+ metadata:
158
+ source_code_uri: https://github.com/alexreisner/geocoder
159
+ changelog_uri: https://github.com/alexreisner/geocoder/blob/master/CHANGELOG.md
153
160
  post_install_message:
154
161
  rdoc_options: []
155
162
  require_paths: