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
@@ -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