geokit 1.10.0 → 1.11.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 (82) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -0
  3. data/.hound.yml +2 -0
  4. data/.rubocop.yml +358 -0
  5. data/.travis.yml +4 -4
  6. data/CHANGELOG.md +16 -0
  7. data/Gemfile +3 -3
  8. data/README.markdown +19 -4
  9. data/Rakefile +11 -16
  10. data/fixtures/keys.yml +9 -0
  11. data/fixtures/vcr_cassettes/google_postal_town.yml +117 -0
  12. data/fixtures/vcr_cassettes/mapbox_forward_geocode.yml +30 -30
  13. data/fixtures/vcr_cassettes/mapbox_forward_geocode_city_only.yml +25 -25
  14. data/fixtures/vcr_cassettes/mapbox_forward_geocode_state_only.yml +71 -0
  15. data/fixtures/vcr_cassettes/mapbox_reverse_geocode.yml +25 -25
  16. data/fixtures/vcr_cassettes/test_component_filtering_off.yml +390 -0
  17. data/fixtures/vcr_cassettes/test_component_filtering_on.yml +164 -0
  18. data/fixtures/vcr_cassettes/test_component_filtering_on_without_filter.yml +404 -0
  19. data/geokit.gemspec +24 -23
  20. data/lib/geokit.rb +7 -7
  21. data/lib/geokit/core_ext.rb +1 -1
  22. data/lib/geokit/geo_loc.rb +25 -19
  23. data/lib/geokit/geocoders.rb +21 -30
  24. data/lib/geokit/geocoders/bing.rb +5 -4
  25. data/lib/geokit/geocoders/ca_geocoder.rb +10 -11
  26. data/lib/geokit/geocoders/fcc.rb +9 -9
  27. data/lib/geokit/geocoders/free_geo_ip.rb +8 -8
  28. data/lib/geokit/geocoders/geo_plugin.rb +7 -7
  29. data/lib/geokit/geocoders/geobytes.rb +10 -10
  30. data/lib/geokit/geocoders/geocodio.rb +14 -14
  31. data/lib/geokit/geocoders/geonames.rb +12 -12
  32. data/lib/geokit/geocoders/google.rb +89 -61
  33. data/lib/geokit/geocoders/ip.rb +9 -14
  34. data/lib/geokit/geocoders/mapbox.rb +30 -30
  35. data/lib/geokit/geocoders/mapquest.rb +12 -12
  36. data/lib/geokit/geocoders/maxmind.rb +1 -1
  37. data/lib/geokit/geocoders/opencage.rb +19 -19
  38. data/lib/geokit/geocoders/openstreetmap.rb +21 -19
  39. data/lib/geokit/geocoders/ripe.rb +7 -7
  40. data/lib/geokit/geocoders/us_geocoder.rb +5 -5
  41. data/lib/geokit/geocoders/yahoo.rb +46 -46
  42. data/lib/geokit/geocoders/yandex.rb +18 -17
  43. data/lib/geokit/inflectors.rb +5 -5
  44. data/lib/geokit/lat_lng.rb +5 -4
  45. data/lib/geokit/multi_geocoder.rb +4 -2
  46. data/lib/geokit/net_adapter/net_http.rb +3 -2
  47. data/lib/geokit/net_adapter/typhoeus.rb +2 -1
  48. data/lib/geokit/version.rb +1 -1
  49. data/test/coverage_loader.rb +25 -0
  50. data/test/helper.rb +18 -87
  51. data/test/test_base_geocoder.rb +44 -11
  52. data/test/test_bing_geocoder.rb +40 -48
  53. data/test/test_bounds.rb +1 -1
  54. data/test/test_ca_geocoder.rb +15 -15
  55. data/test/test_fcc_geocoder.rb +8 -9
  56. data/test/test_free_geo_ip_geocoder.rb +8 -10
  57. data/test/test_geo_plugin_geocoder.rb +21 -22
  58. data/test/test_geobytes_geocoder.rb +9 -11
  59. data/test/test_geocodio_geocoder.rb +12 -14
  60. data/test/test_geoloc.rb +48 -49
  61. data/test/test_geonames_geocoder.rb +19 -23
  62. data/test/test_google_geocoder.rb +197 -189
  63. data/test/test_inflector.rb +7 -7
  64. data/test/test_ipgeocoder.rb +32 -31
  65. data/test/test_latlng.rb +28 -28
  66. data/test/test_map_quest.rb +23 -27
  67. data/test/test_mapbox_geocoder.rb +38 -28
  68. data/test/test_mappable.rb +2 -2
  69. data/test/test_maxmind_geocoder.rb +16 -16
  70. data/test/test_multi_geocoder.rb +5 -5
  71. data/test/test_multi_ip_geocoder.rb +3 -3
  72. data/test/test_net_adapter.rb +4 -4
  73. data/test/test_opencage_geocoder.rb +58 -67
  74. data/test/test_openstreetmap_geocoder.rb +67 -65
  75. data/test/test_polygon.rb +4 -22
  76. data/test/test_ripe_geocoder.rb +21 -26
  77. data/test/test_us_geocoder.rb +21 -21
  78. data/test/test_useragent.rb +46 -0
  79. data/test/test_yahoo_geocoder.rb +35 -47
  80. data/test/test_yandex_geocoder.rb +29 -27
  81. data/test/vcr_loader.rb +18 -0
  82. metadata +20 -6
@@ -8,18 +8,18 @@ module Geokit
8
8
  private
9
9
 
10
10
  # Template method which does the geocode lookup.
11
- def self.do_geocode(address)
11
+ def self.do_geocode(address, _=nil)
12
12
  process :xml, submit_url(address)
13
13
  end
14
14
 
15
15
  def self.submit_url(address)
16
16
  if key.nil? || key.empty?
17
- raise(Geokit::Geocoders::GeocodeError, "Geonames requires a key to use their service.")
17
+ raise(Geokit::Geocoders::GeocodeError, 'Geonames requires a key to use their service.')
18
18
  end
19
19
 
20
20
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
21
21
  # geonames need a space seperated search string
22
- address_str.gsub!(/,/, " ")
22
+ address_str.gsub!(/,/, ' ')
23
23
  params = "/postalCodeSearch?placename=#{Geokit::Inflector.url_escape(address_str)}&maxRows=10"
24
24
 
25
25
  if premium
@@ -30,21 +30,21 @@ module Geokit
30
30
  end
31
31
 
32
32
  XML_MAPPINGS = {
33
- city: "name",
34
- state_name: "adminName1",
35
- state_code: "adminCode1",
36
- zip: "postalcode",
37
- country_code: "countryCode",
38
- lat: "lat",
39
- lng: "lng",
33
+ city: 'name',
34
+ state_name: 'adminName1',
35
+ state_code: 'adminCode1',
36
+ zip: 'postalcode',
37
+ country_code: 'countryCode',
38
+ lat: 'lat',
39
+ lng: 'lng',
40
40
  }
41
41
 
42
42
  def self.parse_xml(xml)
43
- count = xml.elements["geonames/totalResultsCount"]
43
+ count = xml.elements['geonames/totalResultsCount']
44
44
  return GeoLoc.new unless !count.nil? && count.text.to_i > 0
45
45
  loc = new_loc
46
46
  # only take the first result
47
- set_mappings(loc, xml.elements["geonames/code"], XML_MAPPINGS)
47
+ set_mappings(loc, xml.elements['geonames/code'], XML_MAPPINGS)
48
48
  loc.success = true
49
49
  loc
50
50
  end
@@ -8,9 +8,18 @@ module Geokit
8
8
 
9
9
  # ==== OPTIONS
10
10
  # * :language - See: https://developers.google.com/maps/documentation/geocoding
11
+ # * :result_type - This option allows restricting results by specific result types.
12
+ # See https://developers.google.com/maps/documentation/geocoding/intro#reverse-restricted
13
+ # Note: This parameter is available only for requests that include an API key or a client ID.
14
+ # * :location_type - This option allows restricting results by specific location type.
15
+ # See https://developers.google.com/maps/documentation/geocoding/intro#reverse-restricted
16
+ # Note: This parameter is available only for requests that include an API key or a client ID.
11
17
  def self.do_reverse_geocode(latlng, options = {})
12
18
  latlng = LatLng.normalize(latlng)
13
- url = submit_url("latlng=#{Geokit::Inflector.url_escape(latlng.ll)}", options)
19
+ latlng_str = "latlng=#{Geokit::Inflector.url_escape(latlng.ll)}"
20
+ result_type_str = options[:result_type] ? "&result_type=#{options[:result_type]}" : ''
21
+ location_type_str = options[:location_type] ? "&location_type=#{options[:location_type]}" : ''
22
+ url = submit_url("#{latlng_str}#{result_type_str}#{location_type_str}", options)
14
23
  process :json, url
15
24
  end
16
25
 
@@ -24,6 +33,9 @@ module Geokit
24
33
  #
25
34
  # If you'd like the Google Geocoder to prefer results within a given viewport,
26
35
  # you can pass a Geokit::Bounds object as the :bias value.
36
+ # * :components - This option allows restricting results by specific areas. See
37
+ # https://developers.google.com/maps/documentation/geocoding/intro#ComponentFiltering
38
+ # for details.
27
39
  #
28
40
  # ==== EXAMPLES
29
41
  # # By default, the geocoder will return Toledo, OH
@@ -36,31 +48,40 @@ module Geokit
36
48
  # # When biased to an bounding box around California, it will now return the Winnetka neighbourhood, CA
37
49
  # bounds = Geokit::Bounds.normalize([34.074081, -118.694401], [34.321129, -118.399487])
38
50
  # Geokit::Geocoders::GoogleGeocoder.geocode('Winnetka', :bias => bounds).state # => 'CA'
51
+ #
52
+ # # By default, the geocoder will return several matches for Austin with
53
+ # the first one being in Texas
54
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Austin').state # => 'TX'
55
+ # # Using Component Filtering the results can be restricted to a specific
56
+ # area, e.g. IL
57
+ # Geokit::Geocoders::GoogleGeocoder.geocode('Austin',
58
+ # :components => {administrative_area: 'IL', country: 'US'}).state # => 'IL'
39
59
  def self.do_geocode(address, options = {})
40
- bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ""
60
+ bias_str = options[:bias] ? construct_bias_string_from_options(options[:bias]) : ''
61
+ components_str = options[:components] ? construct_components_string_from_options(options[:components]) : ''
41
62
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
42
- url = submit_url("address=#{Geokit::Inflector.url_escape(address_str)}#{bias_str}", options)
63
+ url = submit_url("address=#{Geokit::Inflector.url_escape(address_str)}#{bias_str}#{components_str}", options)
43
64
  process :json, url
44
65
  end
45
66
 
46
67
  # This code comes from Googles Examples
47
68
  # http://gmaps-samples.googlecode.com/svn/trunk/urlsigning/urlsigner.rb
48
69
  def self.sign_gmap_bus_api_url(urlToSign, google_cryptographic_key)
49
- require "base64"
50
- require "openssl"
70
+ require 'base64'
71
+ require 'openssl'
51
72
  # Decode the private key
52
- rawKey = Base64.decode64(google_cryptographic_key.tr("-_", "+/"))
73
+ rawKey = Base64.decode64(google_cryptographic_key.tr('-_', '+/'))
53
74
  # create a signature using the private key and the URL
54
- rawSignature = OpenSSL::HMAC.digest("sha1", rawKey, urlToSign)
75
+ rawSignature = OpenSSL::HMAC.digest('sha1', rawKey, urlToSign)
55
76
  # encode the signature into base64 for url use form.
56
- Base64.encode64(rawSignature).tr("+/", "-_").gsub(/\n/, "")
77
+ Base64.encode64(rawSignature).tr('+/', '-_').gsub(/\n/, '')
57
78
  end
58
79
 
59
80
  def self.submit_url(query_string, options = {})
60
- language_str = options[:language] ? "&language=#{options[:language]}" : ""
81
+ language_str = options[:language] ? "&language=#{options[:language]}" : ''
61
82
  query_string = "/maps/api/geocode/json?sensor=false&#{query_string}#{language_str}"
62
83
  if client_id && cryptographic_key
63
- channel_string = channel ? "&channel=#{channel}" : ""
84
+ channel_string = channel ? "&channel=#{channel}" : ''
64
85
  urlToSign = query_string + "&client=#{client_id}" + channel_string
65
86
  signature = sign_gmap_bus_api_url(urlToSign, cryptographic_key)
66
87
  "#{protocol}://maps.googleapis.com" + urlToSign + "&signature=#{signature}"
@@ -84,21 +105,27 @@ module Geokit
84
105
  end
85
106
  end
86
107
 
108
+ def self.construct_components_string_from_options(components={})
109
+ unless components.empty?
110
+ "&components=#{components.to_a.map { |pair| pair.join(':').downcase }.join(CGI.escape('|'))}"
111
+ end
112
+ end
113
+
87
114
  def self.parse_json(results)
88
- case results["status"]
89
- when "OVER_QUERY_LIMIT"
90
- raise Geokit::Geocoders::TooManyQueriesError, results["error_message"]
91
- when "REQUEST_DENIED"
92
- raise Geokit::Geocoders::AccessDeniedError, results["error_message"]
93
- when "ZERO_RESULTS"
115
+ case results['status']
116
+ when 'OVER_QUERY_LIMIT'
117
+ raise Geokit::Geocoders::TooManyQueriesError, results['error_message']
118
+ when 'REQUEST_DENIED'
119
+ raise Geokit::Geocoders::AccessDeniedError, results['error_message']
120
+ when 'ZERO_RESULTS'
94
121
  return GeoLoc.new
95
- when "OK"
122
+ when 'OK'
96
123
  # all good
97
124
  else
98
- raise Geokit::Geocoders::GeocodeError, results["error_message"]
125
+ raise Geokit::Geocoders::GeocodeError, results['error_message']
99
126
  end
100
127
 
101
- unsorted = results["results"].map do |addr|
128
+ unsorted = results['results'].map do |addr|
102
129
  single_json_to_geoloc(addr)
103
130
  end
104
131
 
@@ -125,10 +152,10 @@ module Geokit
125
152
  # these do not map well. Perhaps we should guess better based on size
126
153
  # of bounding box where it exists? Does it really matter?
127
154
  ACCURACY = {
128
- "ROOFTOP" => 9,
129
- "RANGE_INTERPOLATED" => 8,
130
- "GEOMETRIC_CENTER" => 5,
131
- "APPROXIMATE" => 4,
155
+ 'ROOFTOP' => 9,
156
+ 'RANGE_INTERPOLATED' => 8,
157
+ 'GEOMETRIC_CENTER' => 5,
158
+ 'APPROXIMATE' => 4,
132
159
  }
133
160
 
134
161
  PRECISIONS = %w(unknown country state state city zip zip+4 street address building)
@@ -136,17 +163,17 @@ module Geokit
136
163
  def self.single_json_to_geoloc(addr)
137
164
  loc = new_loc
138
165
  loc.success = true
139
- loc.full_address = addr["formatted_address"]
166
+ loc.full_address = addr['formatted_address']
140
167
 
141
168
  set_address_components(loc, addr)
142
169
  set_precision(loc, addr)
143
170
  if loc.street_name
144
- loc.street_address = [loc.street_number, loc.street_name].join(" ").strip
171
+ loc.street_address = [loc.street_number, loc.street_name].join(' ').strip
145
172
  end
146
173
 
147
- ll = addr["geometry"]["location"]
148
- loc.lat = ll["lat"].to_f
149
- loc.lng = ll["lng"].to_f
174
+ ll = addr['geometry']['location']
175
+ loc.lat = ll['lat'].to_f
176
+ loc.lng = ll['lng'].to_f
150
177
 
151
178
  set_bounds(loc, addr)
152
179
 
@@ -157,59 +184,60 @@ module Geokit
157
184
  end
158
185
 
159
186
  def self.set_bounds(loc, addr)
160
- viewport = addr["geometry"]["viewport"]
161
- ne = Geokit::LatLng.from_json(viewport["northeast"])
162
- sw = Geokit::LatLng.from_json(viewport["southwest"])
187
+ viewport = addr['geometry']['viewport']
188
+ ne = Geokit::LatLng.from_json(viewport['northeast'])
189
+ sw = Geokit::LatLng.from_json(viewport['southwest'])
163
190
  loc.suggested_bounds = Geokit::Bounds.new(sw, ne)
164
191
  end
165
192
 
166
193
  def self.set_address_components(loc, addr)
167
- addr["address_components"].each do |comp|
168
- types = comp["types"]
194
+ addr['address_components'].each do |comp|
195
+ types = comp['types']
169
196
  case
170
- when types.include?("subpremise")
171
- loc.sub_premise = comp["short_name"]
172
- when types.include?("street_number")
173
- loc.street_number = comp["short_name"]
174
- when types.include?("route")
175
- loc.street_name = comp["long_name"]
176
- when types.include?("locality")
177
- loc.city = comp["long_name"]
178
- when types.include?("administrative_area_level_1")
179
- loc.state_code = comp["short_name"]
180
- loc.state_name = comp["long_name"]
181
- loc.province = comp["short_name"]
182
- when types.include?("postal_code")
183
- loc.zip = comp["long_name"]
184
- when types.include?("country")
185
- loc.country_code = comp["short_name"]
186
- loc.country = comp["long_name"]
187
- when types.include?("administrative_area_level_2")
188
- loc.district = comp["long_name"]
189
- when types.include?("neighborhood")
190
- loc.neighborhood = comp["short_name"]
197
+ when types.include?('subpremise')
198
+ loc.sub_premise = comp['short_name']
199
+ when types.include?('street_number')
200
+ loc.street_number = comp['short_name']
201
+ when types.include?('route')
202
+ loc.street_name = comp['long_name']
203
+ when types.include?('locality')
204
+ loc.city = comp['long_name']
205
+ when types.include?('administrative_area_level_1') # state
206
+ loc.state_code = comp['short_name']
207
+ loc.state_name = comp['long_name']
208
+ when types.include?('postal_town')
209
+ loc.city = comp['long_name']
210
+ when types.include?('postal_code')
211
+ loc.zip = comp['long_name']
212
+ when types.include?('country')
213
+ loc.country_code = comp['short_name']
214
+ loc.country = comp['long_name']
215
+ when types.include?('administrative_area_level_2')
216
+ loc.district = comp['long_name']
217
+ when types.include?('neighborhood')
218
+ loc.neighborhood = comp['short_name']
191
219
  # Use either sublocality or admin area level 3 if google does not return a city
192
- when types.include?("sublocality")
193
- loc.city = comp["long_name"] if loc.city.nil?
194
- when types.include?("administrative_area_level_3")
195
- loc.city = comp["long_name"] if loc.city.nil?
220
+ when types.include?('sublocality')
221
+ loc.city = comp['long_name'] if loc.city.nil?
222
+ when types.include?('administrative_area_level_3')
223
+ loc.city = comp['long_name'] if loc.city.nil?
196
224
  end
197
225
  end
198
226
  end
199
227
 
200
228
  def self.set_precision(loc, addr)
201
- loc.accuracy = ACCURACY[addr["geometry"]["location_type"]]
229
+ loc.accuracy = ACCURACY[addr['geometry']['location_type']]
202
230
  loc.precision = PRECISIONS[loc.accuracy]
203
231
  # try a few overrides where we can
204
232
  if loc.sub_premise
205
233
  loc.precision = PRECISIONS[9]
206
234
  loc.accuracy = 9
207
235
  end
208
- if loc.street_name && loc.precision == "city"
236
+ if loc.street_name && loc.precision == 'city'
209
237
  loc.precision = PRECISIONS[7]
210
238
  loc.accuracy = 7
211
239
  end
212
- if addr["types"].include?("postal_code")
240
+ if addr['types'].include?('postal_code')
213
241
  loc.precision = PRECISIONS[6]
214
242
  loc.accuracy = 6
215
243
  end
@@ -9,14 +9,14 @@ module Geokit
9
9
  # Given an IP address, returns a GeoLoc instance which contains latitude,
10
10
  # longitude, city, and country code. Sets the success attribute to false if the ip
11
11
  # parameter does not match an ip address.
12
- def self.do_geocode(ip)
12
+ def self.do_geocode(ip, _=nil)
13
13
  return GeoLoc.new unless valid_ip?(ip)
14
14
  url = submit_url(ip)
15
15
  res = call_geocoder_service(url)
16
16
  return GeoLoc.new unless net_adapter.success?(res)
17
17
  ensure_utf8_encoding(res)
18
18
  body = res.body
19
- body = body.encode("UTF-8") if body.respond_to? :encode
19
+ body = body.encode('UTF-8') if body.respond_to? :encode
20
20
  parse :yaml, body
21
21
  end
22
22
 
@@ -34,10 +34,10 @@ module Geokit
34
34
  # then instantiates a GeoLoc instance to populate with location data.
35
35
  def self.parse_yaml(yaml) # :nodoc:
36
36
  loc = new_loc
37
- loc.city, loc.state_code = yaml["City"].split(", ")
38
- loc.country, loc.country_code = yaml["Country"].split(" (")
39
- loc.lat = yaml["Latitude"]
40
- loc.lng = yaml["Longitude"]
37
+ loc.city, loc.state_code = yaml['City'].split(', ')
38
+ loc.country, loc.country_code = yaml['Country'].split(' (')
39
+ loc.lat = yaml['Latitude']
40
+ loc.lng = yaml['Longitude']
41
41
  loc.country_code.chop!
42
42
  loc.success = !(loc.city =~ /\(.+\)/)
43
43
  loc
@@ -49,19 +49,14 @@ module Geokit
49
49
  # thus extract encoding from headers and tell Rails about it by forcing it
50
50
  def self.ensure_utf8_encoding(res)
51
51
  if (enc_string = extract_charset(res))
52
- if defined?(Encoding) && Encoding.aliases.values.include?(enc_string.upcase)
53
- res.body.force_encoding(enc_string.upcase) if res.body.respond_to?(:force_encoding)
54
- res.body.encode("UTF-8")
55
- else
56
- require "iconv"
57
- res.body.replace Iconv.conv("UTF8", "iso88591", res.body)
58
- end
52
+ res.body.force_encoding(enc_string.upcase) if res.body.respond_to?(:force_encoding)
53
+ res.body.encode('UTF-8')
59
54
  end
60
55
  end
61
56
 
62
57
  # Extracts charset out of the response headers
63
58
  def self.extract_charset(res)
64
- if (content_type = res["content-type"])
59
+ if (content_type = res['content-type'])
65
60
  capture = content_type.match(/charset=(.+)/)
66
61
  capture && capture[1]
67
62
  end
@@ -9,7 +9,7 @@ module Geokit
9
9
  private
10
10
 
11
11
  # Template method which does the reverse-geocode lookup.
12
- def self.do_reverse_geocode(latlng, options = {})
12
+ def self.do_reverse_geocode(latlng, _options = nil)
13
13
  latlng = LatLng.normalize(latlng)
14
14
  url = "#{protocol}://api.tiles.mapbox.com/v4/geocode/mapbox.places-v1/"
15
15
  url += "#{latlng.lng},#{latlng.lat}.json?access_token=#{key}"
@@ -17,7 +17,7 @@ module Geokit
17
17
  end
18
18
 
19
19
  # Template method which does the geocode lookup.
20
- def self.do_geocode(address, options = {})
20
+ def self.do_geocode(address, _options = nil)
21
21
  address_str = address.is_a?(GeoLoc) ? address.to_geocodeable_s : address
22
22
  url = "#{protocol}://api.tiles.mapbox.com/v4/geocode/mapbox.places-v1/"
23
23
  url += "#{Geokit::Inflector.url_escape(address_str)}.json?access_token=#{key}"
@@ -25,9 +25,9 @@ module Geokit
25
25
  end
26
26
 
27
27
  def self.parse_json(results)
28
- return GeoLoc.new unless results["features"].count > 0
28
+ return GeoLoc.new unless results['features'].count > 0
29
29
  loc = nil
30
- results["features"].each do |feature|
30
+ results['features'].each do |feature|
31
31
  extracted_geoloc = extract_geoloc(feature)
32
32
  if loc.nil?
33
33
  loc = extracted_geoloc
@@ -40,52 +40,52 @@ module Geokit
40
40
 
41
41
  def self.extract_geoloc(result_json)
42
42
  loc = new_loc
43
- loc.lng = result_json["center"][0]
44
- loc.lat = result_json["center"][1]
43
+ loc.lng = result_json['center'][0]
44
+ loc.lat = result_json['center'][1]
45
45
  set_address_components(result_json, loc)
46
46
  set_precision(loc)
47
- set_bounds(result_json["bbox"], loc)
47
+ set_bounds(result_json['bbox'], loc)
48
48
  loc.success = true
49
49
  loc
50
50
  end
51
51
 
52
52
  def self.set_address_components(result_json, loc)
53
- if result_json["context"]
54
- result_json["context"].each do |context|
55
- if context["id"] =~ /^country\./
56
- loc.country = context["text"]
57
- elsif context["id"] =~ /^province\./
58
- loc.state = context["text"]
59
- elsif context["id"] =~ /^city\./
60
- loc.city = context["text"]
61
- elsif context["id"] =~ /^postcode/
62
- loc.zip = context["text"]
53
+ if result_json['context']
54
+ result_json['context'].each do |context|
55
+ if context['id'] =~ /^country\./
56
+ loc.country = context['text']
57
+ elsif context['id'] =~ /^province\./
58
+ loc.state = context['text']
59
+ elsif context['id'] =~ /^city\./
60
+ loc.city = context['text']
61
+ elsif context['id'] =~ /^postcode/
62
+ loc.zip = context['text']
63
63
  end
64
64
  end
65
65
  loc.country = loc.country_code if loc.country_code && !loc.country
66
66
  end
67
- if result_json["place_name"]
68
- loc.full_address = result_json["place_name"]
67
+ if result_json['place_name']
68
+ loc.full_address = result_json['place_name']
69
69
  end
70
- if !loc.city && result_json["id"] =~ /^city\./
71
- loc.city = result_json["text"]
70
+ if !loc.city && result_json['id'] =~ /^city\./
71
+ loc.city = result_json['text']
72
+ end
73
+ if !loc.state && result_json['id'] =~ /^province\./
74
+ loc.state = result_json['text']
72
75
  end
73
76
  end
74
77
 
75
- PRECISION_VALUES = %w(unknown country state city zip full_address)
78
+ PRECISION_VALUES = %w(country state city zip)
76
79
 
77
80
  def self.set_precision(loc)
78
- (1...PRECISION_VALUES.length - 1).each do |i|
79
- if loc.send(PRECISION_VALUES[i]) && loc.send(PRECISION_VALUES[i]).length
80
- loc.precision = PRECISION_VALUES[i]
81
- else
82
- break
83
- end
81
+ PRECISION_VALUES.each do |precision|
82
+ break unless loc.send(precision) && loc.send(precision).length
83
+ loc.precision = precision
84
84
  end
85
85
  end
86
86
 
87
- def self.set_bounds(result_json, loc)
88
- if bounds = result_json
87
+ def self.set_bounds(bounds, loc)
88
+ if bounds
89
89
  loc.suggested_bounds = Bounds.normalize([bounds[1], bounds[0]], [bounds[3], bounds[2]])
90
90
  end
91
91
  end