geokit 1.8.5 → 1.9.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.
Files changed (76) hide show
  1. checksums.yaml +7 -0
  2. data/.travis.yml +0 -1
  3. data/CHANGELOG.md +7 -0
  4. data/README.markdown +31 -14
  5. data/fixtures/vcr_cassettes/geonames_geocode.yml +1 -1
  6. data/fixtures/vcr_cassettes/geonames_geocode_premium.yml +42 -0
  7. data/fixtures/vcr_cassettes/google_country_code_biased_result_orly.yml +160 -0
  8. data/fixtures/vcr_cassettes/google_country_code_biased_result_toledo.yml +111 -0
  9. data/fixtures/vcr_cassettes/google_result_toledo_default_bias.yml +275 -0
  10. data/fixtures/vcr_cassettes/google_sublocality.yml +126 -0
  11. data/fixtures/vcr_cassettes/mapbox_forward_geocode.yml +59 -0
  12. data/fixtures/vcr_cassettes/mapbox_reverse_geocode.yml +63 -0
  13. data/fixtures/vcr_cassettes/opencage_city.yml +51 -0
  14. data/fixtures/vcr_cassettes/opencage_full.yml +65 -0
  15. data/fixtures/vcr_cassettes/opencage_language_response_es.yml +66 -0
  16. data/fixtures/vcr_cassettes/opencage_reverse_madrid.yml +51 -0
  17. data/fixtures/vcr_cassettes/opencage_reverse_prilep.yml +53 -0
  18. data/geokit.gemspec +5 -3
  19. data/lib/geokit/bounds.rb +40 -31
  20. data/lib/geokit/core_ext.rb +1 -1
  21. data/lib/geokit/geo_loc.rb +63 -41
  22. data/lib/geokit/geocoders.rb +13 -13
  23. data/lib/geokit/geocoders/bing.rb +9 -9
  24. data/lib/geokit/geocoders/ca_geocoder.rb +29 -29
  25. data/lib/geokit/geocoders/fcc.rb +4 -4
  26. data/lib/geokit/geocoders/free_geo_ip.rb +6 -7
  27. data/lib/geokit/geocoders/geo_plugin.rb +5 -6
  28. data/lib/geokit/geocoders/geocodio.rb +2 -2
  29. data/lib/geokit/geocoders/geonames.rb +18 -12
  30. data/lib/geokit/geocoders/google.rb +31 -30
  31. data/lib/geokit/geocoders/ip.rb +3 -4
  32. data/lib/geokit/geocoders/mapbox.rb +94 -0
  33. data/lib/geokit/geocoders/mapquest.rb +5 -5
  34. data/lib/geokit/geocoders/opencage.rb +93 -0
  35. data/lib/geokit/geocoders/openstreetmap.rb +9 -6
  36. data/lib/geokit/geocoders/ripe.rb +3 -3
  37. data/lib/geokit/geocoders/us_geocoder.rb +10 -9
  38. data/lib/geokit/geocoders/yahoo.rb +33 -34
  39. data/lib/geokit/geocoders/yandex.rb +17 -17
  40. data/lib/geokit/inflectors.rb +4 -10
  41. data/lib/geokit/lat_lng.rb +50 -26
  42. data/lib/geokit/mappable.rb +83 -83
  43. data/lib/geokit/multi_geocoder.rb +25 -20
  44. data/lib/geokit/net_adapter/net_http.rb +7 -4
  45. data/lib/geokit/polygon.rb +36 -4
  46. data/lib/geokit/version.rb +1 -1
  47. data/test/helper.rb +15 -13
  48. data/test/test_base_geocoder.rb +6 -7
  49. data/test/test_bing_geocoder.rb +20 -21
  50. data/test/test_bounds.rb +26 -28
  51. data/test/test_ca_geocoder.rb +9 -10
  52. data/test/test_fcc_geocoder.rb +1 -1
  53. data/test/test_free_geo_ip_geocoder.rb +1 -1
  54. data/test/test_geo_plugin_geocoder.rb +9 -9
  55. data/test/test_geoloc.rb +7 -6
  56. data/test/test_geonames_geocoder.rb +28 -6
  57. data/test/test_google_geocoder.rb +210 -176
  58. data/test/test_inflector.rb +0 -1
  59. data/test/test_ipgeocoder.rb +17 -18
  60. data/test/test_latlng.rb +105 -85
  61. data/test/test_map_quest.rb +18 -21
  62. data/test/test_mapbox_geocoder.rb +31 -0
  63. data/test/test_mappable.rb +46 -0
  64. data/test/test_maxmind_geocoder.rb +1 -3
  65. data/test/test_multi_geocoder.rb +8 -9
  66. data/test/test_multi_ip_geocoder.rb +3 -5
  67. data/test/test_net_adapter.rb +4 -4
  68. data/test/test_opencage_geocoder.rb +108 -0
  69. data/test/test_openstreetmap_geocoder.rb +62 -44
  70. data/test/{test_polygon_contains.rb → test_polygon.rb} +30 -20
  71. data/test/test_ripe_geocoder.rb +2 -0
  72. data/test/test_us_geocoder.rb +7 -8
  73. data/test/test_yahoo_geocoder.rb +20 -21
  74. data/test/test_yandex_geocoder.rb +34 -35
  75. metadata +79 -56
  76. data/fixtures/vcr_cassettes/google_country_code_biased_result.yml +0 -401
@@ -1,5 +1,5 @@
1
1
  unless nil.respond_to?(:try)
2
- class Object
2
+ class Object
3
3
  def try(*a, &b)
4
4
  if a.empty? && block_given?
5
5
  yield self
@@ -5,8 +5,8 @@ module Geokit
5
5
  # the "full address" method for geocoders that do not provide a
6
6
  # full address in their results (for example, Yahoo), and the "is_us" method.
7
7
  #
8
- # Some geocoders can return multple results. Geoloc can capture multiple results through
9
- # its "all" method.
8
+ # Some geocoders can return multple results. Geoloc can capture multiple
9
+ # results through its "all" method.
10
10
  #
11
11
  # For the geocoder setting the results, it would look something like this:
12
12
  # geo=GeoLoc.new(first_result)
@@ -20,40 +20,50 @@ module Geokit
20
20
  # puts geo.all.first # all is just an array or additional geolocs,
21
21
  # so do what you want with it
22
22
  class GeoLoc < LatLng
23
-
24
- # Location attributes. Full address is a concatenation of all values. For example:
23
+ # Location attributes. Full address is a concatenation of all values.
24
+ # For example:
25
25
  # 100 Spear St, San Francisco, CA, 94101, US
26
- # Street number and street name are extracted from the street address attribute if they don't exist
27
- attr_accessor :street_number, :street_name, :street_address, :city, :state, :zip, :country_code, :country
28
- attr_accessor :full_address, :all, :district, :province, :sub_premise, :neighborhood
29
- # Attributes set upon return from geocoding. Success will be true for successful
30
- # geocode lookups. The provider will be set to the name of the providing geocoder.
31
- # Finally, precision is an indicator of the accuracy of the geocoding.
26
+ # Street number and street name are extracted from the street address
27
+ # attribute if they don't exist
28
+ attr_accessor :street_number, :street_name, :street_address, :city, :state,
29
+ :state_name, :state_code, :zip, :country_code, :country
30
+ attr_accessor :full_address, :all, :district, :province, :sub_premise,
31
+ :neighborhood
32
+ # Attributes set upon return from geocoding. Success will be true for
33
+ # successful geocode lookups. The provider will be set to the name of the
34
+ # providing geocoder. Finally, precision is an indicator of the accuracy of
35
+ # the geocoding.
32
36
  attr_accessor :success, :provider, :precision, :suggested_bounds
33
- # accuracy is set for Yahoo and Google geocoders, it is a numeric value of the
34
- # precision. see http://code.google.com/apis/maps/documentation/geocoding/#GeocodingAccuracy
37
+ # accuracy is set for Yahoo and Google geocoders, it is a numeric value of
38
+ # the precision. see
39
+ # http://code.google.com/apis/maps/documentation/geocoding/#GeocodingAccuracy
35
40
  attr_accessor :accuracy
36
41
  # FCC Attributes
37
42
  attr_accessor :district_fips, :state_fips, :block_fips
38
43
 
39
-
40
44
  # Constructor expects a hash of symbols to correspond with attributes.
41
- def initialize(h={})
45
+ def initialize(h = {})
42
46
  @all = [self]
43
47
 
44
- @street_address=h[:street_address]
45
- @sub_premise=nil
46
- @street_number=nil
47
- @street_name=nil
48
- @city=h[:city]
49
- @state=h[:state]
50
- @zip=h[:zip]
51
- @country_code=h[:country_code]
48
+ @street_address = h[:street_address]
49
+ @sub_premise = nil
50
+ @street_number = nil
51
+ @street_name = nil
52
+ @city = h[:city]
53
+ @state = h[:state]
54
+ @state_code = h[:state_code]
55
+ @state_name = h[:state_name]
56
+ @zip = h[:zip]
57
+ @country_code = h[:country_code]
52
58
  @province = h[:province]
53
- @success=false
54
- @precision='unknown'
55
- @full_address=nil
56
- super(h[:lat],h[:lng])
59
+ @success = false
60
+ @precision = 'unknown'
61
+ @full_address = nil
62
+ super(h[:lat], h[:lng])
63
+ end
64
+
65
+ def state
66
+ @state || @state_code || @state_name
57
67
  end
58
68
 
59
69
  # Returns true if geocoded to the United States.
@@ -65,9 +75,9 @@ module Geokit
65
75
  success == true
66
76
  end
67
77
 
68
- # full_address is provided by google but not by yahoo. It is intended that the google
69
- # geocoding method will provide the full address, whereas for yahoo it will be derived
70
- # from the parts of the address we do have.
78
+ # full_address is provided by google but not by yahoo. It is intended that
79
+ # the google geocoding method will provide the full address, whereas for
80
+ # yahoo it will be derived from the parts of the address we do have.
71
81
  def full_address
72
82
  @full_address ? @full_address : to_geocodeable_s
73
83
  end
@@ -80,38 +90,41 @@ module Geokit
80
90
 
81
91
  # Returns the street name portion of the street address where possible
82
92
  def street_name
83
- @street_name||=street_address[street_number.length, street_address.length].strip if street_address
93
+ @street_name ||= street_address[street_number.length, street_address.length].strip if street_address
84
94
  @street_name
85
95
  end
86
96
 
87
97
  # gives you all the important fields as key-value pairs
88
98
  def hash
89
- res={}
90
- [:success, :lat, :lng, :country_code, :city, :state, :zip, :street_address, :province,
91
- :district, :provider, :full_address, :is_us?, :ll, :precision, :district_fips, :state_fips,
92
- :block_fips, :sub_premise].each { |s| res[s] = self.send(s.to_s) }
99
+ res = {}
100
+ fields = [:success, :lat, :lng, :country_code, :city, :state, :zip,
101
+ :street_address, :province, :district, :provider, :full_address, :is_us?,
102
+ :ll, :precision, :district_fips, :state_fips, :block_fips, :sub_premise]
103
+ fields.each { |s| res[s] = send(s.to_s) }
93
104
  res
94
105
  end
95
106
  alias to_hash hash
96
107
 
97
108
  # Sets the city after capitalizing each word within the city name.
98
109
  def city=(city)
99
- @city = Geokit::Inflector::titleize(city) if city
110
+ @city = Geokit::Inflector.titleize(city) if city
100
111
  end
101
112
 
102
- # Sets the street address after capitalizing each word within the street address.
113
+ # Sets the street address after capitalizing each word within the street
114
+ # address.
103
115
  def street_address=(address)
104
116
  @street_address = if address && provider != 'google'
105
- Geokit::Inflector::titleize(address)
117
+ Geokit::Inflector.titleize(address)
106
118
  else
107
119
  address
108
120
  end
109
121
  end
110
122
 
111
- # Returns a comma-delimited string consisting of the street address, city, state,
112
- # zip, and country code. Only includes those attributes that are non-blank.
123
+ # Returns a comma-delimited string consisting of the street address, city,
124
+ # state, zip, and country code. Only includes those attributes that are
125
+ # non-blank.
113
126
  def to_geocodeable_s
114
- a=[street_address, district, city, province, state, zip, country_code].compact
127
+ a = [street_address, district, city, province, state, zip, country_code].compact
115
128
  a.delete_if { |e| !e || e == '' }
116
129
  a.join(', ')
117
130
  end
@@ -128,7 +141,16 @@ module Geokit
128
141
 
129
142
  # Returns a string representation of the instance.
130
143
  def to_s
131
- "Provider: #{provider}\nStreet: #{street_address}\nCity: #{city}\nState: #{state}\nZip: #{zip}\nLatitude: #{lat}\nLongitude: #{lng}\nCountry: #{country_code}\nSuccess: #{success}"
144
+ ["Provider: #{provider}",
145
+ "Street: #{street_address}",
146
+ "City: #{city}",
147
+ "State: #{state}",
148
+ "Zip: #{zip}",
149
+ "Latitude: #{lat}",
150
+ "Longitude: #{lng}",
151
+ "Country: #{country_code}",
152
+ "Success: #{success}"
153
+ ].join("\n")
132
154
  end
133
155
  end
134
156
  end
@@ -34,10 +34,10 @@ module Geokit
34
34
  module Geocoders
35
35
  @@proxy = nil
36
36
  @@request_timeout = nil
37
- @@provider_order = [:google,:us]
38
- @@ip_provider_order = [:geo_plugin,:ip]
39
- @@logger=Logger.new(STDOUT)
40
- @@logger.level=Logger::INFO
37
+ @@provider_order = [:google, :us]
38
+ @@ip_provider_order = [:geo_plugin, :ip]
39
+ @@logger = Logger.new(STDOUT)
40
+ @@logger.level = Logger::INFO
41
41
  @@domain = nil
42
42
  @@net_adapter = Geokit::NetAdapter::NetHttp
43
43
  @@secure = true
@@ -45,7 +45,7 @@ module Geokit
45
45
 
46
46
  def self.__define_accessors
47
47
  class_variables.each do |v|
48
- sym = v.to_s.delete("@").to_sym
48
+ sym = v.to_s.delete('@').to_sym
49
49
  unless self.respond_to? sym
50
50
  module_eval <<-EOS, __FILE__, __LINE__
51
51
  def self.#{sym}
@@ -105,7 +105,7 @@ module Geokit
105
105
  protected
106
106
 
107
107
  def self.logger
108
- Geokit::Geocoders::logger
108
+ Geokit::Geocoders.logger
109
109
  end
110
110
 
111
111
  private
@@ -136,8 +136,8 @@ module Geokit
136
136
 
137
137
  # Call the geocoder service using the timeout if configured.
138
138
  def self.call_geocoder_service(url)
139
- Timeout::timeout(Geokit::Geocoders::request_timeout) { return self.do_get(url) } if Geokit::Geocoders::request_timeout
140
- self.do_get(url)
139
+ Timeout.timeout(Geokit::Geocoders.request_timeout) { return do_get(url) } if Geokit::Geocoders.request_timeout
140
+ do_get(url)
141
141
  rescue TimeoutError
142
142
  nil
143
143
  end
@@ -150,7 +150,7 @@ module Geokit
150
150
  end
151
151
 
152
152
  def self.use_https?
153
- self.secure && Geokit::Geocoders.secure
153
+ secure && Geokit::Geocoders.secure
154
154
  end
155
155
 
156
156
  def self.protocol
@@ -163,7 +163,7 @@ module Geokit
163
163
  end
164
164
 
165
165
  def self.net_adapter
166
- Geokit::Geocoders::net_adapter
166
+ Geokit::Geocoders.net_adapter
167
167
  end
168
168
 
169
169
  def self.provider_name
@@ -175,7 +175,7 @@ module Geokit
175
175
  case format
176
176
  when :json then parse_json(MultiJson.load(body), *args)
177
177
  when :xml then parse_xml(REXML::Document.new(body), *args)
178
- when :yaml then parse_yaml(YAML::load(body), *args)
178
+ when :yaml then parse_yaml(YAML.load(body), *args)
179
179
  when :csv then parse_csv(body.chomp.split(','), *args)
180
180
  end
181
181
  end
@@ -195,7 +195,7 @@ module Geokit
195
195
  def self.transcode_to_utf8(body)
196
196
  require 'iconv' unless String.method_defined?(:encode)
197
197
  if String.method_defined?(:encode)
198
- body.encode!('UTF-8', 'UTF-8', :invalid => :replace)
198
+ body.encode!('UTF-8', 'UTF-8', invalid: :replace)
199
199
  else
200
200
  ic = Iconv.new('UTF-8', 'UTF-8//IGNORE')
201
201
  body = ic.iconv(body)
@@ -207,7 +207,7 @@ module Geokit
207
207
  # "Regular" Address geocoders
208
208
  # -------------------------------------------------------------------------------------------
209
209
  require File.join(File.dirname(__FILE__), 'geocoders/base_ip')
210
- Dir[File.join(File.dirname(__FILE__), "/geocoders/*.rb")].each {|f| require f}
210
+ Dir[File.join(File.dirname(__FILE__), '/geocoders/*.rb')].each {|f| require f}
211
211
 
212
212
  require File.join(File.dirname(__FILE__), 'multi_geocoder')
213
213
  end
@@ -47,15 +47,15 @@ module Geokit
47
47
  end
48
48
 
49
49
  XML_MAPPINGS = {
50
- :street_address => 'Address/AddressLine',
51
- :full_address => 'Address/FormattedAddress',
52
- :city => 'Address/Locality',
53
- :state => 'Address/AdminDistrict',
54
- :province => 'Address/AdminDistrict2',
55
- :zip => 'Address/PostalCode',
56
- :country => 'Address/CountryRegion',
57
- :lat => 'Point/Latitude',
58
- :lng => 'Point/Longitude'
50
+ street_address: 'Address/AddressLine',
51
+ full_address: 'Address/FormattedAddress',
52
+ city: 'Address/Locality',
53
+ state: 'Address/AdminDistrict',
54
+ province: 'Address/AdminDistrict2',
55
+ zip: 'Address/PostalCode',
56
+ country: 'Address/CountryRegion',
57
+ lat: 'Point/Latitude',
58
+ lng: 'Point/Longitude'
59
59
  }
60
60
 
61
61
  def self.set_address_components(loc, xml)
@@ -10,37 +10,37 @@
10
10
  # <longt>-123.153684</longt>
11
11
  # </geodata>
12
12
  module Geokit
13
- module Geocoders
14
- class CaGeocoder < Geocoder
15
- config :key
13
+ module Geocoders
14
+ class CaGeocoder < Geocoder
15
+ config :key
16
16
 
17
- private
17
+ private
18
18
 
19
- # Template method which does the geocode lookup.
20
- def self.do_geocode(loc)
21
- raise ArgumentError('Geocoder.ca requires a GeoLoc argument') unless loc.is_a?(GeoLoc)
22
- process :xml, submit_url(loc), loc
23
- end
19
+ # Template method which does the geocode lookup.
20
+ def self.do_geocode(loc)
21
+ raise ArgumentError('Geocoder.ca requires a GeoLoc argument') unless loc.is_a?(GeoLoc)
22
+ process :xml, submit_url(loc), loc
23
+ end
24
24
 
25
- def self.parse_xml(xml, loc)
26
- loc.lat = xml.elements['//latt'].text
27
- loc.lng = xml.elements['//longt'].text
28
- loc.success = true
29
- loc
30
- end
25
+ def self.parse_xml(xml, loc)
26
+ loc.lat = xml.elements['//latt'].text
27
+ loc.lng = xml.elements['//longt'].text
28
+ loc.success = true
29
+ loc
30
+ end
31
31
 
32
- # Formats the request in the format acceptable by the CA geocoder.
33
- def self.submit_url(loc)
34
- args = []
35
- args << "stno=#{loc.street_number}" if loc.street_address
36
- args << "addresst=#{Geokit::Inflector::url_escape(loc.street_name)}" if loc.street_address
37
- args << "city=#{Geokit::Inflector::url_escape(loc.city)}" if loc.city
38
- args << "prov=#{loc.state}" if loc.state
39
- args << "postal=#{loc.zip}" if loc.zip
40
- args << "auth=#{key}" if key
41
- args << "geoit=xml"
42
- 'http://geocoder.ca/?' + args.join('&')
43
- end
44
- end
45
- end
32
+ # Formats the request in the format acceptable by the CA geocoder.
33
+ def self.submit_url(loc)
34
+ args = []
35
+ args << "stno=#{loc.street_number}" if loc.street_address
36
+ args << "addresst=#{Geokit::Inflector.url_escape(loc.street_name)}" if loc.street_address
37
+ args << "city=#{Geokit::Inflector.url_escape(loc.city)}" if loc.city
38
+ args << "prov=#{loc.state}" if loc.state
39
+ args << "postal=#{loc.zip}" if loc.zip
40
+ args << "auth=#{key}" if key
41
+ args << 'geoit=xml'
42
+ 'http://geocoder.ca/?' + args.join('&')
43
+ end
44
+ end
45
+ end
46
46
  end
@@ -4,10 +4,11 @@ module Geokit
4
4
  self.secure = true
5
5
 
6
6
  private
7
+
7
8
  # Template method which does the reverse-geocode lookup.
8
9
  def self.do_reverse_geocode(latlng)
9
- latlng=LatLng.normalize(latlng)
10
- url = "#{protocol}://data.fcc.gov/api/block/find?format=json&latitude=#{Geokit::Inflector::url_escape(latlng.lat.to_s)}&longitude=#{Geokit::Inflector::url_escape(latlng.lng.to_s)}"
10
+ latlng = LatLng.normalize(latlng)
11
+ url = "#{protocol}://data.fcc.gov/api/block/find?format=json&latitude=#{Geokit::Inflector.url_escape(latlng.lat.to_s)}&longitude=#{Geokit::Inflector.url_escape(latlng.lng.to_s)}"
11
12
  process :json, url
12
13
  end
13
14
 
@@ -25,7 +26,7 @@ module Geokit
25
26
  # "status"=>"OK"}
26
27
 
27
28
  def self.parse_json(results)
28
- if results.has_key?('Err') && results['Err']["msg"] == 'There are no results for this location'
29
+ if results.has_key?('Err') && results['Err']['msg'] == 'There are no results for this location'
29
30
  return GeoLoc.new
30
31
  end
31
32
  # this should probably be smarter.
@@ -45,6 +46,5 @@ module Geokit
45
46
  loc
46
47
  end
47
48
  end
48
-
49
49
  end
50
50
  end
@@ -13,12 +13,12 @@ module Geokit
13
13
  end
14
14
 
15
15
  XML_MAPPINGS = {
16
- :city => 'City',
17
- :state => 'RegionCode',
18
- :zip => 'ZipCode',
19
- :country_code => 'CountryCode',
20
- :lat => 'Latitude',
21
- :lng => 'Longitude'
16
+ city: 'City',
17
+ state: 'RegionCode',
18
+ zip: 'ZipCode',
19
+ country_code: 'CountryCode',
20
+ lat: 'Latitude',
21
+ lng: 'Longitude'
22
22
  }
23
23
 
24
24
  def self.parse_xml(xml)
@@ -28,6 +28,5 @@ module Geokit
28
28
  loc
29
29
  end
30
30
  end
31
-
32
31
  end
33
32
  end
@@ -13,11 +13,11 @@ module Geokit
13
13
  end
14
14
 
15
15
  XML_MAPPINGS = {
16
- :city => 'geoplugin_city',
17
- :state => 'geoplugin_region',
18
- :country_code => 'geoplugin_countryCode',
19
- :lat => 'geoplugin_latitude',
20
- :lng => 'geoplugin_longitude'
16
+ city: 'geoplugin_city',
17
+ state: 'geoplugin_region',
18
+ country_code: 'geoplugin_countryCode',
19
+ lat: 'geoplugin_latitude',
20
+ lng: 'geoplugin_longitude'
21
21
  }
22
22
 
23
23
  def self.parse_xml(xml)
@@ -27,6 +27,5 @@ module Geokit
27
27
  loc
28
28
  end
29
29
  end
30
-
31
30
  end
32
31
  end
@@ -11,7 +11,7 @@ module Geokit
11
11
 
12
12
  def self.submit_url(address)
13
13
  params = [
14
- "q=#{Geokit::Inflector::url_escape(address)}",
14
+ "q=#{Geokit::Inflector.url_escape(address)}",
15
15
  "api_key=#{key}"
16
16
  ].join('&')
17
17
 
@@ -28,7 +28,7 @@ module Geokit
28
28
  loc.all.push(create_new_loc(address))
29
29
  end
30
30
  end
31
-
31
+ loc.success = true
32
32
  loc
33
33
  end
34
34