geocoder 1.3.1 → 1.3.2

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: d18d22b519d25e7d3214aa1e52f39d1578a15aa4
4
- data.tar.gz: 82e49a050c93eeb2033f27d961bb354706e9208f
3
+ metadata.gz: 586633875af5786e76c1f815ca613d2dbe658298
4
+ data.tar.gz: 1aae8533ea6744c231c912c767dcf56e12ff087a
5
5
  SHA512:
6
- metadata.gz: 6bee51b01c6fe33f9c2acfd174802908f311724684643de8831414a437015219cfa4ea33266062e09564afa7cff2f54778c02a8f8fa43287692568ce86662fbc
7
- data.tar.gz: df0f94753763aa06902bd1bf25182e6b468595a4ed2f0d77767b2130af08c06b60a8b1fdffc5e0bccd1bdddae83ed305d3f6e9c914e87eb69e1142fc5f8e689e
6
+ metadata.gz: f0a636c5d6b2f40b72c0af679a9fe246ef484b99b6be301f9102d202f0bc5d71f51000b3ae714299c5575b3812b3eae00c787b221fbe7baa23ce6d4c9b1a8f65
7
+ data.tar.gz: e5598a6dd62abe28f60307104a483e3c67e9e161d56a382c37009a89c83a6912ebf526bb94dfcecbcfcba154e7f8b2dd33cb352997b7b3752e694ecd56ce2a91
@@ -3,6 +3,13 @@ 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.2 (2016 Apr 1)
7
+ ------------------
8
+ * Remove :yahoo lookup (service was discontinued Mar 31) (thanks github.com/galiat).
9
+ * Add support for LatLon.io service (thanks github.com/evanmarks).
10
+ * Add support for IpInfo.io service (thanks github.com/rehan, akostyuk).
11
+ * Add support for Pelias/Mapzen service (thanks github.com/RealScout).
12
+
6
13
  1.3.1 (2016 Feb 20)
7
14
  -------------------
8
15
  * Warn about upcoming discontinuation of :yahoo lookup (thanks github.com/galiat).
data/README.md CHANGED
@@ -434,19 +434,6 @@ The [Google Places Details API](https://developers.google.com/places/documentati
434
434
  * **Terms of Service**: https://developers.google.com/places/policies
435
435
  * **Limitations**: "If your application displays Places API data on a page or view that does not also display a Google Map, you must show a "Powered by Google" logo with that data."
436
436
 
437
- #### Yahoo BOSS (`:yahoo`)
438
- **Warning - [this API will be discontinued on March 31.](https://developer.yahoo.com/boss/placefinder/)**
439
-
440
- * **API key**: requires OAuth consumer key and secret (set `Geocoder.configure(:api_key => [key, secret])`)
441
- * **Key signup**: http://developer.yahoo.com/boss/geo/
442
- * **Quota**: unlimited, but subject to usage fees
443
- * **Region**: world
444
- * **SSL support**: no
445
- * **Languages**: en, fr, de, it, es, pt, nl, zh, ja, ko
446
- * **Documentation**: http://developer.yahoo.com/boss/geo/docs/index.html
447
- * **Terms of Service**: http://info.yahoo.com/legal/us/yahoo/boss/tou/?pir=ucJPcJ1ibUn.h.d.lVmlcbcEkoHjwJ_PvxG9SLK9VIbIQAw1XFrnDqY-
448
- * **Limitations**: No mass downloads, no commercial map production based on the data, no storage of data except for caching.
449
-
450
437
  #### Bing (`:bing`)
451
438
 
452
439
  * **API key**: required (set `Geocoder.configure(:lookup => :bing, :api_key => key)`)
@@ -578,6 +565,31 @@ The [Google Places Details API](https://developers.google.com/places/documentati
578
565
  * **Limitations**: ?
579
566
  * **Notes**: You can specify which projection you want to use by setting, for example: `Geocoder.configure(:esri => {:outSR => 102100})`.
580
567
 
568
+ #### Mapzen (`:mapzen`)
569
+
570
+ * **About**: Mapzen is the primary author of pelias and offers Pelias-as-a-service in free and paid versions https://mapzen.com/pelias.
571
+ * **API key**: required
572
+ * **Quota**: 6/sec, up to 30k per day, paid plan info at https://mapzen.com/documentation/search/api-keys-rate-limits/#rate-limits
573
+ * **Region**: World
574
+ * **SSL support**: yes
575
+ * **Languages**: en
576
+ * **Documentation**: https://mapzen.com/documentation/search/search/
577
+ * **Terms of Service**: http://mapzen.com/terms
578
+ * **Limitations**: See terms
579
+
580
+ #### Pelias (`:pelias`)
581
+
582
+ * **About**: Pelias is a modular open-source geocoder using ElasticSearch for fast geocoding https://github.com/pelias/pelias.
583
+ * **API key**: required
584
+ * **Quota**: None, self-hosted service.
585
+ * **Region**: World
586
+ * **SSL support**: yes
587
+ * **Languages**: en
588
+ * **Documentation**: https://mapzen.com/documentation/search/search/
589
+ * **Terms of Service**: http://mapzen.com/terms
590
+ * **Limitations**: See terms
591
+ * **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`.
592
+
581
593
  #### Data Science Toolkit (`:dstk`)
582
594
 
583
595
  Data Science Toolkit provides an API whose reponse format is like Google's but which can be set up as a privately hosted service.
@@ -663,6 +675,17 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
663
675
  * **Limitations**: ?
664
676
  * **Notes**: To use PostcodeAnywhere you must include an API key: `Geocoder.configure(:lookup => :postcode_anywhere_uk, :api_key => 'your_api_key')`.
665
677
 
678
+ #### LatLon.io (`:latlon`)
679
+
680
+ * **API key**: required
681
+ * **Quota**: Depends on the user's plan (free and paid plans available)
682
+ * **Region**: US
683
+ * **SSL support**: yes
684
+ * **Languages**: en
685
+ * **Documentation**: https://latlon.io/documentation
686
+ * **Terms of Service**: ?
687
+ * **Limitations**: No restrictions on use
688
+
666
689
 
667
690
  ### IP Address Services
668
691
 
@@ -726,6 +749,27 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
726
749
  * **Limitations**: Only good for non-commercial use. For commercial usage please check http://developer.baidu.com/map/question.htm#qa0013
727
750
  * **Notes**: To use Baidu set `Geocoder.configure(:lookup => :baidu_ip, :api_key => "your_api_key")`.
728
751
 
752
+ #### MaxMind GeoIP2 Precision Web Services (`:maxmind_geoip2`)
753
+
754
+ * **API key**: required
755
+ * **Quota**: Request Packs can be purchased
756
+ * **Region**: world
757
+ * **SSL support**: yes
758
+ * **Languages**: English
759
+ * **Documentation**: http://dev.maxmind.com/geoip/geoip2/web-services/
760
+ * **Terms of Service**: ?
761
+ * **Limitations**: ?
762
+ * **Notes**: You must specify which MaxMind service you are using in your configuration, and also basic authentication. For example: `Geocoder.configure(:maxmind_geoip2 => {:service => :country, :basic_auth => {:user => '', :password => ''}})`.
763
+
764
+ #### IPInfo.io (`:ipinfo_io`)
765
+
766
+ * **API key**: optional - see http://ipinfo.io/pricing
767
+ * **Quota**: 1,000/day - more with api key
768
+ * **Region**: world
769
+ * **SSL support**: no (not without access key - see http://ipinfo.io/pricing)
770
+ * **Languages**: English
771
+ * **Documentation**: http://ipinfo.io/developers
772
+ * **Terms of Service**: http://ipinfo.io/developers
729
773
 
730
774
  ### IP Address Local Database Services
731
775
 
@@ -1033,7 +1077,7 @@ Error Handling
1033
1077
 
1034
1078
  By default Geocoder will rescue any exceptions raised by calls to a geocoding service and return an empty array. You can override this on a per-exception basis, and also have Geocoder raise its own exceptions for certain events (eg: API quota exceeded) by using the `:always_raise` option:
1035
1079
 
1036
- Geocoder.configure(:always_raise => [SocketError, TimeoutError])
1080
+ Geocoder.configure(:always_raise => [SocketError, Timeout::Error])
1037
1081
 
1038
1082
  You can also do this to raise all exceptions:
1039
1083
 
@@ -1042,14 +1086,14 @@ You can also do this to raise all exceptions:
1042
1086
  The raise-able exceptions are:
1043
1087
 
1044
1088
  SocketError
1045
- TimeoutError
1089
+ Timeout::Error
1046
1090
  Geocoder::OverQueryLimitError
1047
1091
  Geocoder::RequestDenied
1048
1092
  Geocoder::InvalidRequest
1049
1093
  Geocoder::InvalidApiKey
1050
1094
  Geocoder::ServiceUnavailable
1051
1095
 
1052
- Note that only a few of the above exceptions are raised by any given lookup, so there's no guarantee if you configure Geocoder to raise `ServiceUnavailable` that it will actually be raised under those conditions (because most APIs don't return 503 when they should; you may get a `TimeoutError` instead). Please see the source code for your particular lookup for details.
1096
+ Note that only a few of the above exceptions are raised by any given lookup, so there's no guarantee if you configure Geocoder to raise `ServiceUnavailable` that it will actually be raised under those conditions (because most APIs don't return 503 when they should; you may get a `Timeout::Error` instead). Please see the source code for your particular lookup for details.
1053
1097
 
1054
1098
 
1055
1099
  Troubleshooting
@@ -1071,6 +1115,16 @@ A lot of debugging time can be saved by understanding how Geocoder works with Ac
1071
1115
  * using the `pluck` method (selects only a single column)
1072
1116
  * specifying another model through `includes` (selects columns from other tables)
1073
1117
 
1118
+ ### Geocoding is Slow
1119
+
1120
+ With most lookups, addresses are translated into coordinates via an API that must be accessed through the Internet. These requests are subject to the same bandwidth constraints as every other HTTP request, and will vary in speed depending on network conditions. Furthermore, many of the services supported by Geocoder are free and thus very popular. Often they cannot keep up with demand and their response times become quite bad.
1121
+
1122
+ If your application requires quick geocoding responses you will probably need to pay for a non-free service, or--if you're doing IP address geocoding--use a lookup that doesn't require an external (network-accessed) service.
1123
+
1124
+ For IP address lookups in Rails applications, it is generally NOT a good idea to run `request.location` during a synchronous page load without understanding the speed/behavior of your configured lookup. If the lookup becomes slow, so will your website.
1125
+
1126
+ For the most part, the speed of geocoding requests has little to do with the Geocoder gem. Please take the time to learn about your configured lookup (links to documentation are provided above) before posting performance-related issues.
1127
+
1074
1128
  ### Unexpected Responses from Geocoding Services
1075
1129
 
1076
1130
  Take a look at the server's raw response. You can do this by getting the request URL in an app console:
@@ -35,6 +35,6 @@ class ReverseGeocodeJob < ActiveJob::Base
35
35
  end
36
36
 
37
37
  def retryable?(exception)
38
- exception.is_a?(TimeoutError) || exception.is_a?(SocketError)
38
+ exception.is_a?(Timeout::Error) || exception.is_a?(SocketError)
39
39
  end
40
40
  end
@@ -12,7 +12,7 @@ Geocoder.configure(
12
12
 
13
13
  # Exceptions that should not be rescued by default
14
14
  # (if you want to implement custom error handling);
15
- # supports SocketError and TimeoutError
15
+ # supports SocketError and Timeout::Error
16
16
  # always_raise: [],
17
17
 
18
18
  # Calculation options
@@ -17,10 +17,6 @@ module Geocoder
17
17
  if !options.nil?
18
18
  Configuration.instance.configure(options)
19
19
  end
20
-
21
- if config.lookup == :yahoo
22
- Geocoder.log(:warn, "Yahoo BOSS Placefinder API will be discontinued March 31, 2016.")
23
- end
24
20
  end
25
21
 
26
22
  ##
@@ -109,7 +105,7 @@ module Geocoder
109
105
 
110
106
  # exceptions that should not be rescued by default
111
107
  # (if you want to implement custom error handling);
112
- # supports SocketError and TimeoutError
108
+ # supports SocketError and Timeout::Error
113
109
  @data[:always_raise] = []
114
110
 
115
111
  # calculation options
@@ -28,7 +28,6 @@ module Geocoder
28
28
  :google,
29
29
  :google_premier,
30
30
  :google_places_details,
31
- :yahoo,
32
31
  :bing,
33
32
  :geocoder_ca,
34
33
  :geocoder_us,
@@ -36,8 +35,10 @@ module Geocoder
36
35
  :nominatim,
37
36
  :mapbox,
38
37
  :mapquest,
38
+ :mapzen,
39
39
  :opencagedata,
40
40
  :ovi,
41
+ :pelias,
41
42
  :here,
42
43
  :baidu,
43
44
  :geocodio,
@@ -45,7 +46,8 @@ module Geocoder
45
46
  :okf,
46
47
  :postcode_anywhere_uk,
47
48
  :geoportail_lu,
48
- :test
49
+ :test,
50
+ :latlon
49
51
  ]
50
52
  end
51
53
 
@@ -61,7 +63,8 @@ module Geocoder
61
63
  :maxmind_local,
62
64
  :telize,
63
65
  :pointpin,
64
- :maxmind_geoip2
66
+ :maxmind_geoip2,
67
+ :ipinfo_io
65
68
  ]
66
69
  end
67
70
 
@@ -179,7 +179,7 @@ module Geocoder
179
179
  raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
180
180
  rescue Errno::ECONNREFUSED => err
181
181
  raise_error(err) or Geocoder.log(:warn, "Geocoding API connection refused.")
182
- rescue TimeoutError => err
182
+ rescue Timeout::Error => err
183
183
  raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
184
184
  "(use Geocoder.configure(:timeout => ...) to set limit).")
185
185
  end
@@ -7,6 +7,10 @@ module Geocoder::Lookup
7
7
  def name
8
8
  "FreeGeoIP"
9
9
  end
10
+
11
+ def supported_protocols
12
+ [:http]
13
+ end
10
14
 
11
15
  def query_url(query)
12
16
  "#{protocol}://#{host}/json/#{query.sanitized_text}"
@@ -0,0 +1,55 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/ipinfo_io'
3
+
4
+ module Geocoder::Lookup
5
+ class IpinfoIo < Base
6
+
7
+ def name
8
+ "Ipinfo.io"
9
+ end
10
+
11
+ def query_url(query)
12
+ if configuration.api_key
13
+ "#{protocol}://ipinfo.io/#{query.sanitized_text}/geo?" + url_query_string(query)
14
+ else
15
+ "#{protocol}://ipinfo.io/#{query.sanitized_text}/geo"
16
+ end
17
+ end
18
+
19
+ # HTTPS available only for paid plans
20
+ def supported_protocols
21
+ if configuration.api_key
22
+ [:http, :https]
23
+ else
24
+ [:http]
25
+ end
26
+ end
27
+
28
+ private # ---------------------------------------------------------------
29
+
30
+ def results(query)
31
+ # don't look up a loopback address, just return the stored result
32
+ return [reserved_result(query.text)] if query.loopback_ip_address?
33
+ if (doc = fetch_data(query)).nil? or doc['code'] == 401 or empty_result?(doc)
34
+ []
35
+ else
36
+ [doc]
37
+ end
38
+ end
39
+
40
+ def empty_result?(doc)
41
+ !doc.is_a?(Hash) or doc.keys == ["ip"]
42
+ end
43
+
44
+ def reserved_result(ip)
45
+ {"message" => "Input string is not a valid IP address", "code" => 401}
46
+ end
47
+
48
+ def query_url_params(query)
49
+ {
50
+ token: configuration.api_key
51
+ }.merge(super)
52
+ end
53
+
54
+ end
55
+ end
@@ -0,0 +1,59 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/latlon'
3
+
4
+ module Geocoder::Lookup
5
+ class Latlon < Base
6
+
7
+ def name
8
+ "LatLon.io"
9
+ end
10
+
11
+ def required_api_key_parts
12
+ ["api_key"]
13
+ end
14
+
15
+ def query_url(query)
16
+ "#{protocol}://latlon.io/api/v1/#{'reverse_' if query.reverse_geocode?}geocode?#{url_query_string(query)}"
17
+ end
18
+
19
+ private # ---------------------------------------------------------------
20
+
21
+ def results(query)
22
+ return [] unless doc = fetch_data(query)
23
+ if doc['error'].nil?
24
+ [doc]
25
+ # The API returned a 404 response, which indicates no results found
26
+ elsif doc['error']['type'] == 'api_error'
27
+ []
28
+ elsif
29
+ doc['error']['type'] == 'authentication_error'
30
+ raise_error(Geocoder::InvalidApiKey) ||
31
+ Geocoder.log(:warn, "LatLon.io service error: invalid API key.")
32
+ else
33
+ []
34
+ end
35
+ end
36
+
37
+ def supported_protocols
38
+ [:https]
39
+ end
40
+
41
+ private # ---------------------------------------------------------------
42
+
43
+ def query_url_params(query)
44
+ if query.reverse_geocode?
45
+ {
46
+ :token => configuration.api_key,
47
+ :lat => query.coordinates[0],
48
+ :lon => query.coordinates[1]
49
+ }.merge(super)
50
+ else
51
+ {
52
+ :token => configuration.api_key,
53
+ :address => query.sanitized_text
54
+ }.merge(super)
55
+ end
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,15 @@
1
+ require 'geocoder/lookups/pelias'
2
+ require 'geocoder/results/mapzen'
3
+
4
+ # https://mapzen.com/documentation/search/search/ for more information
5
+ module Geocoder::Lookup
6
+ class Mapzen < Pelias
7
+ def name
8
+ 'Mapzen'
9
+ end
10
+
11
+ def endpoint
12
+ configuration[:endpoint] || 'search.mapzen.com'
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,56 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/pelias'
3
+
4
+ module Geocoder::Lookup
5
+ class Pelias < Base
6
+ def name
7
+ 'Pelias'
8
+ end
9
+
10
+ def endpoint
11
+ configuration[:endpoint] || 'localhost'
12
+ end
13
+
14
+ def query_url(query)
15
+ query_type = query.reverse_geocode? ? 'reverse' : 'search'
16
+ "#{protocol}://#{endpoint}/v1/#{query_type}?" + url_query_string(query)
17
+ end
18
+
19
+ def required_api_key_parts
20
+ ['search-XXXX']
21
+ end
22
+
23
+ private
24
+
25
+ def query_url_params(query)
26
+ {
27
+ api_key: configuration.api_key,
28
+ text: query.text,
29
+ size: 1
30
+ }.merge(super(query))
31
+ end
32
+
33
+ def results(query)
34
+ return [] unless doc = fetch_data(query)
35
+
36
+ # not all responses include a meta
37
+ if doc['meta']
38
+ error = doc.fetch('results', {}).fetch('error', {})
39
+ message = error.fetch('type', 'Unknown Error') + ': ' + error.fetch('message', 'No message')
40
+ log_message = 'Pelias Geocoding API error - ' + message
41
+ case doc['meta']['status_code']
42
+ when '200'
43
+ # nothing to see here
44
+ when '403'
45
+ raise_error(Geocoder::RequestDenied, message) || Geocoder.log(:warn, log_message)
46
+ when '429'
47
+ raise_error(Geocoder::OverQueryLimitError, message) || Geocoder.log(:warn, log_message)
48
+ else
49
+ raise_error(Geocoder::Error, message) || Geocoder.log(:warn, log_message)
50
+ end
51
+ end
52
+
53
+ doc['features'] || []
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,56 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class IpinfoIo < Base
5
+
6
+ def address(format = :full)
7
+ "#{city} #{postal_code}, #{country}".sub(/^[ ,]*/, "")
8
+ end
9
+
10
+ def latitude
11
+ @data['loc'].split(',')[0].to_f
12
+ end
13
+
14
+ def longitude
15
+ @data['loc'].split(',')[1].to_f
16
+ end
17
+
18
+ def coordinates
19
+ [@data['loc'].split(',')[0].to_f, @data['loc'].split(',')[1].to_f]
20
+ end
21
+
22
+ def city
23
+ @data['city']
24
+ end
25
+
26
+ def state
27
+ @data['region']
28
+ end
29
+
30
+ def country
31
+ @data['country']
32
+ end
33
+
34
+ def postal_code
35
+ @data['postal']
36
+ end
37
+
38
+ def country_code
39
+ @data.fetch('country', '')
40
+ end
41
+
42
+ def state_code
43
+ @data.fetch('region_code', '')
44
+ end
45
+
46
+ def self.response_attributes
47
+ %w['ip', 'city', 'region', 'country', 'latitude', 'longitude', 'postal_code']
48
+ end
49
+
50
+ response_attributes.each do |a|
51
+ define_method a do
52
+ @data[a]
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,71 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Latlon < Base
5
+
6
+ def city
7
+ address_components["city"]
8
+ end
9
+
10
+ def coordinates
11
+ [@data['lat'].to_f, @data['lon'].to_f]
12
+ end
13
+
14
+ def country
15
+ "United States" # LatLon.io only supports the US
16
+ end
17
+
18
+ def country_code
19
+ "US" # LatLon.io only supports the US
20
+ end
21
+
22
+ def formatted_address(format = :full)
23
+ address_components["address"]
24
+ end
25
+ alias_method :address, :formatted_address
26
+
27
+ def number
28
+ address_components["number"]
29
+ end
30
+
31
+ def prefix
32
+ address_components["prefix"]
33
+ end
34
+
35
+ def state
36
+ address_components["state"]
37
+ end
38
+ alias_method :state_code, :state
39
+
40
+ def street
41
+ [street_name, street_type].compact.join(' ')
42
+ end
43
+
44
+ def street_name
45
+ address_components["street_name"]
46
+ end
47
+
48
+ def street_type
49
+ address_components["street_type"]
50
+ end
51
+
52
+ def suffix
53
+ address_components["suffix"]
54
+ end
55
+
56
+ def unit
57
+ address_components["unit"]
58
+ end
59
+
60
+ def zip
61
+ address_components["zip"]
62
+ end
63
+ alias_method :postal_code, :zip
64
+
65
+ private
66
+
67
+ def address_components
68
+ @data["address"] || {}
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,5 @@
1
+ require 'geocoder/results/pelias'
2
+
3
+ module Geocoder::Result
4
+ class Mapzen < Pelias; end
5
+ end
@@ -0,0 +1,58 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Pelias < Base
5
+ def address(format = :full)
6
+ properties['label']
7
+ end
8
+
9
+ def city
10
+ locality
11
+ end
12
+
13
+ def coordinates
14
+ geometry['coordinates'].reverse
15
+ end
16
+
17
+ def country_code
18
+ properties['country_a']
19
+ end
20
+
21
+ def postal_code
22
+ properties['postalcode'].to_s
23
+ end
24
+
25
+ def province
26
+ state
27
+ end
28
+
29
+ def state
30
+ properties['region']
31
+ end
32
+
33
+ def state_code
34
+ properties['region_a']
35
+ end
36
+
37
+ def self.response_attributes
38
+ %w[county confidence country gid id layer localadmin locality neighborhood]
39
+ end
40
+
41
+ response_attributes.each do |a|
42
+ define_method a do
43
+ properties[a]
44
+ end
45
+ end
46
+
47
+ private
48
+
49
+ def geometry
50
+ @data.fetch('geometry', {})
51
+ end
52
+
53
+ def properties
54
+ @data.fetch('properties', {})
55
+ end
56
+ end
57
+ end
58
+
@@ -1,3 +1,3 @@
1
1
  module Geocoder
2
- VERSION = "1.3.1"
2
+ VERSION = "1.3.2"
3
3
  end
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.3.1
4
+ version: 1.3.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Reisner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-20 00:00:00.000000000 Z
11
+ date: 2016-04-01 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,
@@ -62,8 +62,11 @@ files:
62
62
  - lib/geocoder/lookups/google_places_details.rb
63
63
  - lib/geocoder/lookups/google_premier.rb
64
64
  - lib/geocoder/lookups/here.rb
65
+ - lib/geocoder/lookups/ipinfo_io.rb
66
+ - lib/geocoder/lookups/latlon.rb
65
67
  - lib/geocoder/lookups/mapbox.rb
66
68
  - lib/geocoder/lookups/mapquest.rb
69
+ - lib/geocoder/lookups/mapzen.rb
67
70
  - lib/geocoder/lookups/maxmind.rb
68
71
  - lib/geocoder/lookups/maxmind_geoip2.rb
69
72
  - lib/geocoder/lookups/maxmind_local.rb
@@ -71,12 +74,12 @@ files:
71
74
  - lib/geocoder/lookups/okf.rb
72
75
  - lib/geocoder/lookups/opencagedata.rb
73
76
  - lib/geocoder/lookups/ovi.rb
77
+ - lib/geocoder/lookups/pelias.rb
74
78
  - lib/geocoder/lookups/pointpin.rb
75
79
  - lib/geocoder/lookups/postcode_anywhere_uk.rb
76
80
  - lib/geocoder/lookups/smarty_streets.rb
77
81
  - lib/geocoder/lookups/telize.rb
78
82
  - lib/geocoder/lookups/test.rb
79
- - lib/geocoder/lookups/yahoo.rb
80
83
  - lib/geocoder/lookups/yandex.rb
81
84
  - lib/geocoder/models/active_record.rb
82
85
  - lib/geocoder/models/base.rb
@@ -102,8 +105,11 @@ files:
102
105
  - lib/geocoder/results/google_places_details.rb
103
106
  - lib/geocoder/results/google_premier.rb
104
107
  - lib/geocoder/results/here.rb
108
+ - lib/geocoder/results/ipinfo_io.rb
109
+ - lib/geocoder/results/latlon.rb
105
110
  - lib/geocoder/results/mapbox.rb
106
111
  - lib/geocoder/results/mapquest.rb
112
+ - lib/geocoder/results/mapzen.rb
107
113
  - lib/geocoder/results/maxmind.rb
108
114
  - lib/geocoder/results/maxmind_geoip2.rb
109
115
  - lib/geocoder/results/maxmind_local.rb
@@ -111,12 +117,12 @@ files:
111
117
  - lib/geocoder/results/okf.rb
112
118
  - lib/geocoder/results/opencagedata.rb
113
119
  - lib/geocoder/results/ovi.rb
120
+ - lib/geocoder/results/pelias.rb
114
121
  - lib/geocoder/results/pointpin.rb
115
122
  - lib/geocoder/results/postcode_anywhere_uk.rb
116
123
  - lib/geocoder/results/smarty_streets.rb
117
124
  - lib/geocoder/results/telize.rb
118
125
  - lib/geocoder/results/test.rb
119
- - lib/geocoder/results/yahoo.rb
120
126
  - lib/geocoder/results/yandex.rb
121
127
  - lib/geocoder/sql.rb
122
128
  - lib/geocoder/stores/active_record.rb
@@ -127,7 +133,6 @@ files:
127
133
  - lib/geocoder/version.rb
128
134
  - lib/hash_recursive_merge.rb
129
135
  - lib/maxmind_database.rb
130
- - lib/oauth_util.rb
131
136
  - lib/tasks/geocoder.rake
132
137
  - lib/tasks/maxmind.rake
133
138
  homepage: http://www.rubygeocoder.com
@@ -150,7 +155,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
150
155
  version: '0'
151
156
  requirements: []
152
157
  rubyforge_project:
153
- rubygems_version: 2.5.1
158
+ rubygems_version: 2.4.5
154
159
  signing_key:
155
160
  specification_version: 4
156
161
  summary: Complete geocoding solution for Ruby.
@@ -1,89 +0,0 @@
1
- require 'geocoder/lookups/base'
2
- require "geocoder/results/yahoo"
3
- require 'oauth_util'
4
-
5
- module Geocoder::Lookup
6
- class Yahoo < Base
7
-
8
- def name
9
- "Yahoo BOSS"
10
- end
11
-
12
- def map_link_url(coordinates)
13
- "http://maps.yahoo.com/#lat=#{coordinates[0]}&lon=#{coordinates[1]}"
14
- end
15
-
16
- def required_api_key_parts
17
- ["consumer key", "consumer secret"]
18
- end
19
-
20
- def query_url(query)
21
- parsed_url = URI.parse(raw_url(query))
22
- o = OauthUtil.new
23
- o.consumer_key = configuration.api_key[0]
24
- o.consumer_secret = configuration.api_key[1]
25
- base_url + o.sign(parsed_url).query_string
26
- end
27
-
28
- private # ---------------------------------------------------------------
29
-
30
- def results(query)
31
- Geocoder.log(:warn, "Yahoo BOSS Placefinder API will be discontinued March 31, 2016.")
32
- return [] unless doc = fetch_data(query)
33
- doc = doc['bossresponse']
34
- if doc['responsecode'].to_i == 200
35
- if doc['placefinder']['count'].to_i > 0
36
- return doc['placefinder']['results']
37
- else
38
- return []
39
- end
40
- else
41
- Geocoder.log(:warn, "Yahoo Geocoding API error: #{doc['responsecode']} (#{doc['reason']}).")
42
- return []
43
- end
44
- end
45
-
46
- ##
47
- # Yahoo returns errors as XML even when JSON format is specified.
48
- # Handle that here, without parsing the XML
49
- # (which would add unnecessary complexity).
50
- # Yahoo auth errors can also be cryptic, so add raw error desc
51
- # to warning message.
52
- #
53
- def parse_raw_data(raw_data)
54
- if raw_data.match(/^<\?xml/)
55
- if raw_data.include?("Rate Limit Exceeded")
56
- raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Over API query limit.")
57
- elsif raw_data =~ /<yahoo:description>(Please provide valid credentials.*)<\/yahoo:description>/i
58
- raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid API key. Error response: #{$1}")
59
- end
60
- else
61
- super(raw_data)
62
- end
63
- end
64
-
65
- def query_url_params(query)
66
- lang = (query.language || configuration.language).to_s
67
- lang += '_US' if lang == 'en'
68
- {
69
- :location => query.sanitized_text,
70
- :flags => "JXTSR",
71
- :gflags => "AC#{'R' if query.reverse_geocode?}",
72
- :locale => lang,
73
- :appid => configuration.api_key
74
- }.merge(super)
75
- end
76
-
77
- def cache_key(query)
78
- raw_url(query)
79
- end
80
-
81
- def base_url
82
- "#{protocol}://yboss.yahooapis.com/geo/placefinder?"
83
- end
84
-
85
- def raw_url(query)
86
- base_url + url_query_string(query)
87
- end
88
- end
89
- end
@@ -1,60 +0,0 @@
1
- require 'geocoder/results/base'
2
-
3
- module Geocoder::Result
4
- class Yahoo < Base
5
-
6
- def address(format = :full)
7
- (1..4).to_a.map{ |i| @data["line#{i}"] }.reject{ |i| i.nil? or i == "" }.join(", ")
8
- end
9
-
10
- def city
11
- @data['city']
12
- end
13
-
14
- def state
15
- @data['state']
16
- end
17
-
18
- def state_code
19
- @data['statecode']
20
- end
21
-
22
- def country
23
- @data['country']
24
- end
25
-
26
- def country_code
27
- @data['countrycode']
28
- end
29
-
30
- def postal_code
31
- @data['postal']
32
- end
33
-
34
- def address_hash
35
- @data['hash']
36
- end
37
-
38
- def viewport
39
- boundingbox = @data['boundingbox'] || fail
40
- %w(south west north east).map{ |i| boundingbox[i].to_f }
41
- end
42
-
43
- def self.response_attributes
44
- %w[quality offsetlat offsetlon radius boundingbox name
45
- line1 line2 line3 line4 cross house street xstreet unittype unit
46
- city state statecode country countrycode postal
47
- neighborhood county countycode
48
- level0 level1 level2 level3 level4 level0code level1code level2code
49
- timezone areacode uzip hash woeid woetype]
50
- end
51
-
52
- response_attributes.each do |a|
53
- unless method_defined?(a)
54
- define_method a do
55
- @data[a]
56
- end
57
- end
58
- end
59
- end
60
- end
@@ -1,112 +0,0 @@
1
- # A utility for signing an url using OAuth in a way that's convenient for debugging
2
- # Note: the standard Ruby OAuth lib is here http://github.com/mojodna/oauth
3
- # Source: http://gist.github.com/383159
4
- # License: http://gist.github.com/375593
5
- # Usage: see example.rb below
6
- #
7
- # NOTE: This file has been modified from the original Gist:
8
- #
9
- # 1. Fix to prevent param-array conversion, as mentioned in Gist comment.
10
- # 2. Query string escaping has been changed. See:
11
- # https://github.com/alexreisner/geocoder/pull/360
12
- #
13
-
14
- require 'uri'
15
- require 'cgi'
16
- require 'openssl'
17
- require 'base64'
18
-
19
- class OauthUtil
20
-
21
- attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method,
22
- :sig_method, :oauth_version, :callback_url, :params, :req_url, :base_str
23
-
24
- def initialize
25
- @consumer_key = ''
26
- @consumer_secret = ''
27
- @token = ''
28
- @token_secret = ''
29
- @req_method = 'GET'
30
- @sig_method = 'HMAC-SHA1'
31
- @oauth_version = '1.0'
32
- @callback_url = ''
33
- end
34
-
35
- # openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get length
36
- # ref http://snippets.dzone.com/posts/show/491
37
- def nonce
38
- Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
39
- end
40
-
41
- def percent_encode( string )
42
-
43
- # ref http://snippets.dzone.com/posts/show/1260
44
- return URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") ).gsub('*', '%2A')
45
- end
46
-
47
- # @ref http://oauth.net/core/1.0/#rfc.section.9.2
48
- def signature
49
- key = percent_encode( @consumer_secret ) + '&' + percent_encode( @token_secret )
50
-
51
- # ref: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks
52
- digest = OpenSSL::Digest.new( 'sha1' )
53
- hmac = OpenSSL::HMAC.digest( digest, key, @base_str )
54
-
55
- # ref http://groups.google.com/group/oauth-ruby/browse_thread/thread/9110ed8c8f3cae81
56
- Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
57
- end
58
-
59
- # sort (very important as it affects the signature), concat, and percent encode
60
- # @ref http://oauth.net/core/1.0/#rfc.section.9.1.1
61
- # @ref http://oauth.net/core/1.0/#9.2.1
62
- # @ref http://oauth.net/core/1.0/#rfc.section.A.5.1
63
- def query_string
64
- pairs = []
65
- @params.sort.each { | key, val |
66
- pairs.push( "#{ CGI.escape(key.to_s).gsub(/%(5B|5D)/n) { [$1].pack('H*') } }=#{ CGI.escape(val.to_s) }" )
67
- }
68
- pairs.join '&'
69
- end
70
-
71
- # organize params & create signature
72
- def sign( parsed_url )
73
-
74
- @params = {
75
- 'oauth_consumer_key' => @consumer_key,
76
- 'oauth_nonce' => nonce,
77
- 'oauth_signature_method' => @sig_method,
78
- 'oauth_timestamp' => Time.now.to_i.to_s,
79
- 'oauth_version' => @oauth_version
80
- }
81
-
82
- # if url has query, merge key/values into params obj overwriting defaults
83
- if parsed_url.query
84
- CGI.parse( parsed_url.query ).each do |k,v|
85
- if v.is_a?(Array) && v.count == 1
86
- @params[k] = v.first
87
- else
88
- @params[k] = v
89
- end
90
- end
91
- end
92
-
93
- # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
94
- @req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path
95
-
96
- # create base str. make it an object attr for ez debugging
97
- # ref http://oauth.net/core/1.0/#anchor14
98
- @base_str = [
99
- @req_method,
100
- percent_encode( req_url ),
101
-
102
- # normalization is just x-www-form-urlencoded
103
- percent_encode( query_string )
104
-
105
- ].join( '&' )
106
-
107
- # add signature
108
- @params[ 'oauth_signature' ] = signature
109
-
110
- return self
111
- end
112
- end