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
@@ -2,7 +2,6 @@ module Geokit
2
2
  module Geocoders
3
3
  # Open Street Map geocoder implementation.
4
4
  class OSMGeocoder < Geocoder
5
-
6
5
  private
7
6
 
8
7
  # Template method which does the geocode lookup.
@@ -11,10 +10,12 @@ module Geokit
11
10
  options_str << generate_param_for_option(:json_callback, options)
12
11
  options_str << generate_param_for_option(:countrycodes, options)
13
12
  options_str << generate_param_for_option(:viewbox, options)
13
+ options_str << generate_param_for_option(:'accept-language', options)
14
+ options_str << generate_param_for_option(:email, options)
14
15
 
15
16
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
16
17
 
17
- url = "http://nominatim.openstreetmap.org/search?format=json#{options_str}&addressdetails=1&q=#{Geokit::Inflector::url_escape(address_str)}"
18
+ url = "http://nominatim.openstreetmap.org/search?format=json#{options_str}&addressdetails=1&q=#{Geokit::Inflector.url_escape(address_str)}"
18
19
  process :json, url
19
20
  end
20
21
 
@@ -22,6 +23,8 @@ module Geokit
22
23
  latlng = LatLng.normalize(latlng)
23
24
  options_str = generate_param_for(:lat, latlng.lat)
24
25
  options_str << generate_param_for(:lon, latlng.lng)
26
+ options_str << generate_param_for_option(:'accept-language', options)
27
+ options_str << generate_param_for_option(:email, options)
25
28
  options_str << generate_param_for_option(:zoom, options)
26
29
  options_str << generate_param_for_option(:osm_type, options)
27
30
  options_str << generate_param_for_option(:osm_id, options)
@@ -31,11 +34,11 @@ module Geokit
31
34
  end
32
35
 
33
36
  def self.generate_param_for(param, value)
34
- "&#{param}=#{Geokit::Inflector::url_escape(value.to_s)}"
37
+ "&#{param}=#{Geokit::Inflector.url_escape(value.to_s)}"
35
38
  end
36
39
 
37
40
  def self.generate_param_for_option(param, options)
38
- options[param] ? "&#{param}=#{Geokit::Inflector::url_escape(options[param])}" : ''
41
+ options[param] ? "&#{param}=#{Geokit::Inflector.url_escape(options[param])}" : ''
39
42
  end
40
43
 
41
44
  def self.generate_bool_param_for_option(param, options)
@@ -80,7 +83,7 @@ module Geokit
80
83
  return unless address_data
81
84
  loc.country = address_data['country']
82
85
  loc.country_code = address_data['country_code'].upcase if address_data['country_code']
83
- loc.state = address_data['state']
86
+ loc.state_name = address_data['state']
84
87
  loc.city = address_data['city']
85
88
  loc.city = address_data['county'] if loc.city.nil? && address_data['county']
86
89
  loc.zip = address_data['postcode']
@@ -93,7 +96,7 @@ module Geokit
93
96
 
94
97
  def self.set_precision(result_json, loc)
95
98
  # Todo accuracy does not work as Yahoo and Google maps on OSM
96
- #loc.accuracy = %w{unknown amenity building highway historic landuse leisure natural place railway shop tourism waterway man_made}.index(loc.precision)
99
+ # loc.accuracy = %w{unknown amenity building highway historic landuse leisure natural place railway shop tourism waterway man_made}.index(loc.precision)
97
100
  loc.precision = result_json['class']
98
101
  loc.accuracy = result_json['type']
99
102
  end
@@ -3,6 +3,7 @@ module Geokit
3
3
  # Provides geocoding based upon an IP address. The underlying web service is geoplugin.net
4
4
  class RipeGeocoder < BaseIpGeocoder
5
5
  self.secure = false # supports HTTPS, but Net::HTTPS doesn't like the server
6
+
6
7
  private
7
8
 
8
9
  def self.do_geocode(ip)
@@ -27,9 +28,9 @@ module Geokit
27
28
  end
28
29
 
29
30
  def self.set_address_components(data, loc)
30
- match = data['country'].match /([A-Z]+)(\(([A-Z]+)\))?/
31
+ match = data['country'].match(/([A-Z]+)(\(([A-Z]+)\))?/)
31
32
  if match[3]
32
- loc.state = match[1]
33
+ loc.state_code = match[1]
33
34
  loc.country_code = match[3]
34
35
  else
35
36
  loc.country_code = match[1]
@@ -38,6 +39,5 @@ module Geokit
38
39
  loc.city = data['city']
39
40
  end
40
41
  end
41
-
42
42
  end
43
43
  end
@@ -2,32 +2,33 @@
2
2
  # contain true or false based upon whether authentication is to occur. Conforms to the
3
3
  # interface set by the Geocoder class.
4
4
  module Geokit
5
- module Geocoders
5
+ module Geocoders
6
6
  class UsGeocoder < Geocoder
7
7
  config :key
8
8
 
9
9
  private
10
+
10
11
  def self.do_geocode(address)
11
12
  process :csv, submit_url(address)
12
13
  end
13
14
 
14
15
  def self.submit_url(address)
15
16
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
16
- query = (address_str =~ /^\d{5}(?:-\d{4})?$/ ? "zip" : "address") + "=#{Geokit::Inflector::url_escape(address_str)}"
17
- base = key ? "http://#{key}@geocoder.us/member" : "http://geocoder.us"
17
+ query = (address_str =~ /^\d{5}(?:-\d{4})?$/ ? 'zip' : 'address') + "=#{Geokit::Inflector.url_escape(address_str)}"
18
+ base = key ? "http://#{key}@geocoder.us/member" : 'http://geocoder.us'
18
19
  "#{base}/service/csv/geocode?#{query}"
19
20
  end
20
21
 
21
22
  def self.parse_csv(array)
22
23
  loc = GeoLoc.new
23
24
  if array.length == 5
24
- loc.lat,loc.lng,loc.city,loc.state,loc.zip=array
25
- loc.country_code='US'
26
- loc.success=true
25
+ loc.lat, loc.lng, loc.city, loc.state, loc.zip = array
26
+ loc.country_code = 'US'
27
+ loc.success = true
27
28
  elsif array.length == 6
28
- loc.lat,loc.lng,loc.street_address,loc.city,loc.state,loc.zip=array
29
- loc.country_code='US'
30
- loc.success=true
29
+ loc.lat, loc.lng, loc.street_address, loc.city, loc.state, loc.zip = array
30
+ loc.country_code = 'US'
31
+ loc.success = true
31
32
  end
32
33
  loc
33
34
  end
@@ -7,9 +7,10 @@ module Geokit
7
7
  self.secure = true
8
8
 
9
9
  private
10
+
10
11
  def self.submit_url(address)
11
12
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
12
- query_string = "?q=#{Geokit::Inflector::url_escape(address_str)}&flags=J"
13
+ query_string = "?q=#{Geokit::Inflector.url_escape(address_str)}&flags=J"
13
14
 
14
15
  o = OauthUtil.new
15
16
  o.consumer_key = key
@@ -59,15 +60,15 @@ module Geokit
59
60
 
60
61
  def self.set_precision(result_json, loc)
61
62
  loc.precision = case result_json['quality'].to_i
62
- when 9,10 then 'country'
63
+ when 9, 10 then 'country'
63
64
  when 19..30 then 'state'
64
- when 39,40 then 'city'
65
- when 49,50 then 'neighborhood'
66
- when 59,60,64 then 'zip'
67
- when 74,75 then 'zip+4'
65
+ when 39, 40 then 'city'
66
+ when 49, 50 then 'neighborhood'
67
+ when 59, 60, 64 then 'zip'
68
+ when 74, 75 then 'zip+4'
68
69
  when 70..72 then 'street'
69
70
  when 80..87 then 'address'
70
- when 62,63,90,99 then 'building'
71
+ when 62, 63, 90, 99 then 'building'
71
72
  else 'unknown'
72
73
  end
73
74
 
@@ -83,17 +84,16 @@ end
83
84
  # Note: the standard Ruby OAuth lib is here http://github.com/mojodna/oauth
84
85
  # License: http://gist.github.com/375593
85
86
  # Usage: see example.rb below
86
-
87
+
87
88
  require 'uri'
88
89
  require 'cgi'
89
90
  require 'openssl'
90
91
  require 'base64'
91
-
92
+
92
93
  class OauthUtil
93
-
94
- attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method,
94
+ attr_accessor :consumer_key, :consumer_secret, :token, :token_secret, :req_method,
95
95
  :sig_method, :oauth_version, :callback_url, :params, :req_url, :base_str
96
-
96
+
97
97
  def initialize
98
98
  @consumer_key = ''
99
99
  @consumer_secret = ''
@@ -104,37 +104,37 @@ class OauthUtil
104
104
  @oauth_version = '1.0'
105
105
  @callback_url = ''
106
106
  end
107
-
107
+
108
108
  # openssl::random_bytes returns non-word chars, which need to be removed. using alt method to get length
109
109
  # ref http://snippets.dzone.com/posts/show/491
110
110
  def nonce
111
111
  Array.new( 5 ) { rand(256) }.pack('C*').unpack('H*').first
112
112
  end
113
-
113
+
114
114
  def percent_encode( string )
115
115
  # ref http://snippets.dzone.com/posts/show/1260
116
116
  URI.escape( string, Regexp.new("[^#{URI::PATTERN::UNRESERVED}]") ).gsub('*', '%2A')
117
117
  end
118
-
118
+
119
119
  # @ref http://oauth.net/core/1.0/#rfc.section.9.2
120
120
  def signature
121
121
  key = percent_encode( @consumer_secret ) + '&' + percent_encode( @token_secret )
122
-
122
+
123
123
  # ref: http://blog.nathanielbibler.com/post/63031273/openssl-hmac-vs-ruby-hmac-benchmarks
124
- digest = OpenSSL::Digest::Digest.new( 'sha1' )
124
+ digest = OpenSSL::Digest.new( 'sha1' )
125
125
  hmac = OpenSSL::HMAC.digest( digest, key, @base_str )
126
-
126
+
127
127
  # ref http://groups.google.com/group/oauth-ruby/browse_thread/thread/9110ed8c8f3cae81
128
128
  Base64.encode64( hmac ).chomp.gsub( /\n/, '' )
129
129
  end
130
-
130
+
131
131
  # sort (very important as it affects the signature), concat, and percent encode
132
132
  # @ref http://oauth.net/core/1.0/#rfc.section.9.1.1
133
133
  # @ref http://oauth.net/core/1.0/#9.2.1
134
134
  # @ref http://oauth.net/core/1.0/#rfc.section.A.5.1
135
135
  def query_string
136
136
  pairs = []
137
- @params.sort.each { | key, val |
137
+ @params.sort.each { | key, val |
138
138
  pairs.push( "#{ percent_encode( key ) }=#{ percent_encode( val.to_s ) }" )
139
139
  }
140
140
  pairs.join '&'
@@ -143,10 +143,9 @@ class OauthUtil
143
143
  def timestamp
144
144
  Time.now.to_i.to_s
145
145
  end
146
-
146
+
147
147
  # organize params & create signature
148
148
  def sign( parsed_url )
149
-
150
149
  @params = {
151
150
  'oauth_consumer_key' => @consumer_key,
152
151
  'oauth_nonce' => nonce,
@@ -154,10 +153,10 @@ class OauthUtil
154
153
  'oauth_timestamp' => timestamp,
155
154
  'oauth_version' => @oauth_version
156
155
  }
157
-
156
+
158
157
  # if url has query, merge key/values into params obj overwriting defaults
159
158
  if parsed_url.query
160
- CGI.parse( parsed_url.query ).each do |k,v|
159
+ CGI.parse( parsed_url.query ).each do |k, v|
161
160
  if v.is_a?(Array) && v.count == 1
162
161
  @params[k] = v.first
163
162
  else
@@ -165,24 +164,24 @@ class OauthUtil
165
164
  end
166
165
  end
167
166
  end
168
-
167
+
169
168
  # @ref http://oauth.net/core/1.0/#rfc.section.9.1.2
170
169
  @req_url = parsed_url.scheme + '://' + parsed_url.host + parsed_url.path
171
-
170
+
172
171
  # create base str. make it an object attr for ez debugging
173
172
  # ref http://oauth.net/core/1.0/#anchor14
174
- @base_str = [
175
- @req_method,
176
- percent_encode( req_url ),
177
-
173
+ @base_str = [
174
+ @req_method,
175
+ percent_encode( req_url ),
176
+
178
177
  # normalization is just x-www-form-urlencoded
179
- percent_encode( query_string )
180
-
178
+ percent_encode( query_string )
179
+
181
180
  ].join( '&' )
182
-
181
+
183
182
  # add signature
184
183
  @params[ 'oauth_signature' ] = signature
185
-
184
+
186
185
  self
187
186
  end
188
187
  end
@@ -14,7 +14,7 @@ module Geokit
14
14
 
15
15
  def self.submit_url(address)
16
16
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
17
- url = "http://geocode-maps.yandex.ru/1.x/?geocode=#{Geokit::Inflector::url_escape(address_str)}&format=json"
17
+ url = "http://geocode-maps.yandex.ru/1.x/?geocode=#{Geokit::Inflector.url_escape(address_str)}&format=json"
18
18
  url += "&key=#{key}" if key
19
19
  url
20
20
  end
@@ -22,18 +22,18 @@ module Geokit
22
22
  def self.parse_json(result)
23
23
  loc = new_loc
24
24
 
25
- coll = result["response"]["GeoObjectCollection"]
26
- return loc unless coll["metaDataProperty"]["GeocoderResponseMetaData"]["found"].to_i > 0
25
+ coll = result['response']['GeoObjectCollection']
26
+ return loc unless coll['metaDataProperty']['GeocoderResponseMetaData']['found'].to_i > 0
27
27
 
28
- l = coll["featureMember"][0]["GeoObject"]
28
+ l = coll['featureMember'][0]['GeoObject']
29
29
 
30
30
  loc.success = true
31
- ll = l["Point"]["pos"].split(" ")
31
+ ll = l['Point']['pos'].split(' ')
32
32
  loc.lng = ll.first
33
33
  loc.lat = ll.last
34
34
 
35
- country = l["metaDataProperty"]["GeocoderMetaData"]["AddressDetails"]["Country"]
36
- locality = country["Locality"] || country["AdministrativeArea"]["Locality"] || country["AdministrativeArea"]["SubAdministrativeArea"]["Locality"] rescue nil
35
+ country = l['metaDataProperty']['GeocoderMetaData']['AddressDetails']['Country']
36
+ locality = country['Locality'] || country['AdministrativeArea']['Locality'] || country['AdministrativeArea']['SubAdministrativeArea']['Locality'] rescue nil
37
37
  set_address_components(loc, l, country, locality)
38
38
  set_precision(loc, l, locality)
39
39
 
@@ -41,19 +41,19 @@ module Geokit
41
41
  end
42
42
 
43
43
  def self.set_address_components(loc, l, country, locality)
44
- loc.country_code = country["CountryNameCode"]
45
- loc.full_address = country["AddressLine"]
46
- loc.street_address = l["name"]
47
- loc.street_number = locality["Thoroughfare"]["Premise"]["PremiseNumber"] rescue nil
48
- loc.street_name = locality["Thoroughfare"]["ThoroughfareName"] rescue nil
49
- loc.city = locality["LocalityName"] rescue nil
50
- loc.state = country["AdministrativeArea"]["AdministrativeAreaName"] rescue nil
51
- loc.state ||= country["Locality"]["LocalityName"] rescue nil
44
+ loc.country_code = country['CountryNameCode']
45
+ loc.full_address = country['AddressLine']
46
+ loc.street_address = l['name']
47
+ loc.street_number = locality['Thoroughfare']['Premise']['PremiseNumber'] rescue nil
48
+ loc.street_name = locality['Thoroughfare']['ThoroughfareName'] rescue nil
49
+ loc.city = locality['LocalityName'] rescue nil
50
+ loc.state_name = country['AdministrativeArea']['AdministrativeAreaName'] rescue nil
51
+ loc.state ||= country['Locality']['LocalityName'] rescue nil
52
52
  end
53
53
 
54
54
  def self.set_precision(loc, l, locality)
55
- loc.precision = l["metaDataProperty"]["GeocoderMetaData"]["precision"].sub(/exact/, "building").sub(/number|near/, "address").sub(/other/, "city")
56
- loc.precision = "country" unless locality
55
+ loc.precision = l['metaDataProperty']['GeocoderMetaData']['precision'].sub(/exact/, 'building').sub(/number|near/, 'address').sub(/other/, 'city')
56
+ loc.precision = 'country' unless locality
57
57
  end
58
58
  end
59
59
  end
@@ -10,20 +10,14 @@ module Geokit
10
10
 
11
11
  def underscore(camel_cased_word)
12
12
  camel_cased_word.to_s.gsub(/::/, '/').
13
- gsub(/([A-Z]+)([A-Z][a-z])/u,'\1_\2').
14
- gsub(/([a-z\d])([A-Z])/u,'\1_\2').
15
- tr("-", "_").
13
+ gsub(/([A-Z]+)([A-Z][a-z])/u, '\1_\2').
14
+ gsub(/([a-z\d])([A-Z])/u, '\1_\2').
15
+ tr('-', '_').
16
16
  downcase
17
17
  end
18
18
 
19
19
  def humanize(lower_case_and_underscored_word)
20
- lower_case_and_underscored_word.to_s.gsub(/_id$/, "").gsub(/_/, " ").capitalize
21
- end
22
-
23
- def snake_case(s)
24
- return s.downcase if s =~ /^[A-Z]+$/u
25
- s.gsub(/([A-Z]+)(?=[A-Z][a-z]?)|\B[A-Z]/u, '_\&') =~ /_*(.*)/
26
- $+.downcase
20
+ lower_case_and_underscored_word.to_s.gsub(/_id$/, '').gsub(/_/, ' ').capitalize
27
21
  end
28
22
 
29
23
  def url_escape(s)
@@ -4,9 +4,18 @@ module Geokit
4
4
 
5
5
  attr_accessor :lat, :lng
6
6
 
7
+ # Provide users with the ability to use :latitude and :longitude
8
+ # to access the lat/lng instance variables.
9
+ # Alias the attr_accessor :lat to :latitude
10
+ alias_method :latitude, :lat
11
+ alias_method :latitude=, :lat=
12
+ # Alias the attr_accessor :lng to :longitude
13
+ alias_method :longitude, :lng
14
+ alias_method :longitude=, :lng=
15
+
7
16
  # Accepts latitude and longitude or instantiates an empty instance
8
17
  # if lat and lng are not provided. Converted to floats if provided
9
- def initialize(lat=nil, lng=nil)
18
+ def initialize(lat = nil, lng = nil)
10
19
  lat = lat.to_f if lat && !lat.is_a?(Numeric)
11
20
  lng = lng.to_f if lng && !lng.is_a?(Numeric)
12
21
  @lat = lat
@@ -24,7 +33,7 @@ module Geokit
24
33
 
25
34
  # Longitude attribute setter; stored as a float;
26
35
  def lng=(lng)
27
- @lng=lng.to_f if lng
36
+ @lng = lng.to_f if lng
28
37
  end
29
38
 
30
39
  # Returns the lat and lng attributes as a comma-separated string.
@@ -42,17 +51,19 @@ module Geokit
42
51
  self.class.decimal_to_dms(lng)
43
52
  end
44
53
 
45
- #returns a string with comma-separated lat,lng values
54
+ # returns a string with comma-separated lat,lng values
46
55
  def to_s
47
56
  ll
48
57
  end
49
58
 
50
- #returns a two-element array
59
+ # returns a two-element array
51
60
  def to_a
52
- [lat,lng]
61
+ [lat, lng]
53
62
  end
54
- # Returns true if the candidate object is logically equal. Logical equivalence
55
- # is true if the lat and lng attributes are the same for both objects.
63
+
64
+ # Returns true if the candidate object is logically equal. Logical
65
+ # equivalence is true if the lat and lng attributes are the same for both
66
+ # objects.
56
67
  def ==(other)
57
68
  return false unless other.is_a?(LatLng)
58
69
  lat == other.lat && lng == other.lng
@@ -71,23 +82,26 @@ module Geokit
71
82
  lat && lng
72
83
  end
73
84
 
74
- # A *class* method to take anything which can be inferred as a point and generate
75
- # a LatLng from it. You should use this anything you're not sure what the input is,
76
- # and want to deal with it as a LatLng if at all possible. Can take:
85
+ # A *class* method to take anything which can be inferred as a point and
86
+ # generate a LatLng from it. You should use this anything you're not sure
87
+ # what the input is, and want to deal with it as a LatLng if at all
88
+ # possible. Can take:
77
89
  # 1) two arguments (lat,lng)
78
90
  # 2) a string in the format "37.1234,-129.1234" or "37.1234 -129.1234"
79
91
  # 3) a string which can be geocoded on the fly
80
92
  # 4) an array in the format [37.1234,-129.1234]
81
93
  # 5) a LatLng or GeoLoc (which is just passed through as-is)
82
- # 6) anything responding to to_lat_lng -- a LatLng will be extracted from it
83
- def self.normalize(thing, other=nil)
94
+ # 6) anything responding to to_lat_lng -- a LatLng will be extracted from
95
+ # it
96
+ def self.normalize(thing, other = nil)
84
97
  return Geokit::LatLng.new(thing, other) if other
85
98
 
86
99
  case thing
87
100
  when String
88
101
  from_string(thing)
89
102
  when Array
90
- thing.size == 2 or raise ArgumentError.new("Must initialize with an Array with both latitude and longitude")
103
+ thing.size == 2 or raise ArgumentError.new(
104
+ 'Must initialize with an Array with both latitude and longitude')
91
105
  Geokit::LatLng.new(thing[0], thing[1])
92
106
  when LatLng # will also be true for GeoLocs
93
107
  thing
@@ -95,14 +109,16 @@ module Geokit
95
109
  if thing.respond_to? :to_lat_lng
96
110
  thing.to_lat_lng
97
111
  else
98
- raise ArgumentError.new("#{thing} (#{thing.class}) cannot be normalized to a LatLng. We tried interpreting it as an array, string, etc., but no dice.")
112
+ raise ArgumentError.new(
113
+ "#{thing} (#{thing.class}) cannot be normalized to a LatLng. " +
114
+ "We tried interpreting it as an array, string, etc., but no dice.")
99
115
  end
100
116
  end
101
117
  end
102
118
 
103
119
  def self.from_string(thing)
104
120
  thing.strip!
105
- if match=thing.match(/(\-?\d+\.?\d*)[, ] ?(\-?\d+\.?\d*)$/)
121
+ if match = thing.match(/(\-?\d+\.?\d*)[, ] ?(\-?\d+\.?\d*)$/)
106
122
  Geokit::LatLng.new(match[1], match[2])
107
123
  else
108
124
  res = Geokit::Geocoders::MultiGeocoder.geocode(thing)
@@ -111,22 +127,30 @@ module Geokit
111
127
  end
112
128
  end
113
129
 
114
- # Reverse geocodes a LatLng object using the MultiGeocoder (default), or optionally
115
- # using a geocoder of your choosing. Returns a new Geokit::GeoLoc object
130
+ # Reverse geocodes a LatLng object using the MultiGeocoder (default), or
131
+ # optionally using a geocoder of your choosing. Returns a new Geokit::GeoLoc
132
+ # object
116
133
  #
117
134
  # ==== Options
118
- # * :using - Specifies the geocoder to use for reverse geocoding. Defaults to
119
- # MultiGeocoder. Can be either the geocoder class (or any class that
120
- # implements do_reverse_geocode for that matter), or the name of
121
- # the class without the "Geocoder" part (e.g. :google)
135
+ # * :using - Specifies the geocoder to use for reverse geocoding. Defaults
136
+ # to MultiGeocoder. Can be either the geocoder class (or any
137
+ # class that implements do_reverse_geocode for that matter), or
138
+ # the name of the class without the "Geocoder" part
139
+ # (e.g. :google)
122
140
  #
123
141
  # ==== Examples
124
- # LatLng.new(51.4578329, 7.0166848).reverse_geocode # => #<Geokit::GeoLoc:0x12dac20 @state...>
125
- # LatLng.new(51.4578329, 7.0166848).reverse_geocode(:using => :google) # => #<Geokit::GeoLoc:0x12dac20 @state...>
126
- # LatLng.new(51.4578329, 7.0166848).reverse_geocode(:using => Geokit::Geocoders::GoogleGeocoder) # => #<Geokit::GeoLoc:0x12dac20 @state...>
127
- def reverse_geocode(options = { :using => Geokit::Geocoders::MultiGeocoder })
142
+ # LatLng.new(51.4578329, 7.0166848).reverse_geocode
143
+ # => #<Geokit::GeoLoc:0x12dac20 @state...>
144
+ # LatLng.new(51.4578329, 7.0166848).reverse_geocode(:using => :google)
145
+ # => #<Geokit::GeoLoc:0x12dac20 @state...>
146
+ # LatLng.new(51.4578329, 7.0166848).reverse_geocode(:using =>
147
+ # Geokit::Geocoders::GoogleGeocoder)
148
+ # => #<Geokit::GeoLoc:0x12dac20 @state...>
149
+ def reverse_geocode(options = { using: Geokit::Geocoders::MultiGeocoder })
128
150
  if options[:using].is_a?(String) || options[:using].is_a?(Symbol)
129
- provider = Geokit::Geocoders.const_get("#{Geokit::Inflector::camelize(options[:using].to_s)}Geocoder")
151
+ class_name =
152
+ "#{Geokit::Inflector.camelize(options[:using].to_s)}Geocoder"
153
+ provider = Geokit::Geocoders.const_get(class_name)
130
154
  elsif options[:using].respond_to?(:do_reverse_geocode)
131
155
  provider = options[:using]
132
156
  else