geokit 1.8.5 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
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