geocoder 1.4.3 → 1.6.1

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 (109) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +64 -0
  3. data/LICENSE +1 -1
  4. data/README.md +365 -883
  5. data/examples/autoexpire_cache_redis.rb +5 -3
  6. data/lib/generators/geocoder/config/templates/initializer.rb +3 -2
  7. data/lib/generators/geocoder/maxmind/geolite_city_generator.rb +2 -0
  8. data/lib/generators/geocoder/maxmind/geolite_country_generator.rb +2 -0
  9. data/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb +1 -1
  10. data/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb +1 -1
  11. data/lib/generators/geocoder/migration_version.rb +15 -0
  12. data/lib/geocoder/cache.rb +6 -2
  13. data/lib/geocoder/calculations.rb +1 -1
  14. data/lib/geocoder/cli.rb +2 -2
  15. data/lib/geocoder/configuration.rb +2 -2
  16. data/lib/geocoder/exceptions.rb +1 -1
  17. data/lib/geocoder/ip_address.rb +14 -1
  18. data/lib/geocoder/lookup.rb +13 -6
  19. data/lib/geocoder/lookups/amap.rb +63 -0
  20. data/lib/geocoder/lookups/baidu.rb +14 -10
  21. data/lib/geocoder/lookups/baidu_ip.rb +7 -36
  22. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +17 -4
  23. data/lib/geocoder/lookups/base.rb +28 -5
  24. data/lib/geocoder/lookups/bing.rb +15 -13
  25. data/lib/geocoder/lookups/db_ip_com.rb +52 -0
  26. data/lib/geocoder/lookups/dstk.rb +4 -2
  27. data/lib/geocoder/lookups/esri.rb +39 -29
  28. data/lib/geocoder/lookups/freegeoip.rb +16 -7
  29. data/lib/geocoder/lookups/geocoder_ca.rb +4 -4
  30. data/lib/geocoder/lookups/geocodio.rb +5 -5
  31. data/lib/geocoder/lookups/geoportail_lu.rb +7 -7
  32. data/lib/geocoder/lookups/google.rb +13 -9
  33. data/lib/geocoder/lookups/google_places_details.rb +4 -4
  34. data/lib/geocoder/lookups/google_places_search.rb +4 -4
  35. data/lib/geocoder/lookups/google_premier.rb +11 -1
  36. data/lib/geocoder/lookups/here.rb +29 -23
  37. data/lib/geocoder/lookups/ip2location.rb +67 -0
  38. data/lib/geocoder/lookups/ipapi_com.rb +9 -13
  39. data/lib/geocoder/lookups/ipdata_co.rb +62 -0
  40. data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  41. data/lib/geocoder/lookups/ipinfo_io.rb +11 -29
  42. data/lib/geocoder/lookups/ipregistry.rb +68 -0
  43. data/lib/geocoder/lookups/ipstack.rb +63 -0
  44. data/lib/geocoder/lookups/latlon.rb +4 -4
  45. data/lib/geocoder/lookups/location_iq.rb +26 -8
  46. data/lib/geocoder/lookups/mapbox.rb +12 -6
  47. data/lib/geocoder/lookups/mapquest.rb +4 -5
  48. data/lib/geocoder/lookups/maxmind.rb +6 -6
  49. data/lib/geocoder/lookups/maxmind_geoip2.rb +8 -7
  50. data/lib/geocoder/lookups/nominatim.rb +17 -5
  51. data/lib/geocoder/lookups/opencagedata.rb +7 -6
  52. data/lib/geocoder/lookups/osmnames.rb +57 -0
  53. data/lib/geocoder/lookups/pelias.rb +8 -9
  54. data/lib/geocoder/lookups/pickpoint.rb +41 -0
  55. data/lib/geocoder/lookups/pointpin.rb +10 -9
  56. data/lib/geocoder/lookups/postcode_anywhere_uk.rb +4 -5
  57. data/lib/geocoder/lookups/postcodes_io.rb +31 -0
  58. data/lib/geocoder/lookups/smarty_streets.rb +20 -10
  59. data/lib/geocoder/lookups/telize.rb +26 -6
  60. data/lib/geocoder/lookups/tencent.rb +59 -0
  61. data/lib/geocoder/lookups/yandex.rb +12 -8
  62. data/lib/geocoder/models/active_record.rb +4 -3
  63. data/lib/geocoder/query.rb +14 -0
  64. data/lib/geocoder/railtie.rb +1 -1
  65. data/lib/geocoder/request.rb +32 -0
  66. data/lib/geocoder/results/amap.rb +87 -0
  67. data/lib/geocoder/results/baidu.rb +10 -14
  68. data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
  69. data/lib/geocoder/results/base.rb +13 -1
  70. data/lib/geocoder/results/bing.rb +1 -1
  71. data/lib/geocoder/results/db_ip_com.rb +58 -0
  72. data/lib/geocoder/results/freegeoip.rb +0 -5
  73. data/lib/geocoder/results/geocoder_ca.rb +3 -3
  74. data/lib/geocoder/results/geoip2.rb +24 -10
  75. data/lib/geocoder/results/geoportail_lu.rb +5 -3
  76. data/lib/geocoder/results/google.rb +16 -5
  77. data/lib/geocoder/results/here.rb +12 -1
  78. data/lib/geocoder/results/ip2location.rb +22 -0
  79. data/lib/geocoder/results/ipdata_co.rb +40 -0
  80. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  81. data/lib/geocoder/results/ipregistry.rb +308 -0
  82. data/lib/geocoder/results/ipstack.rb +60 -0
  83. data/lib/geocoder/results/maxmind.rb +0 -5
  84. data/lib/geocoder/results/maxmind_local.rb +0 -5
  85. data/lib/geocoder/results/nominatim.rb +12 -0
  86. data/lib/geocoder/results/opencagedata.rb +12 -2
  87. data/lib/geocoder/results/osmnames.rb +56 -0
  88. data/lib/geocoder/results/pickpoint.rb +6 -0
  89. data/lib/geocoder/results/postcodes_io.rb +40 -0
  90. data/lib/geocoder/results/smarty_streets.rb +55 -19
  91. data/lib/geocoder/results/telize.rb +0 -5
  92. data/lib/geocoder/results/tencent.rb +72 -0
  93. data/lib/geocoder/results/test.rb +1 -1
  94. data/lib/geocoder/sql.rb +4 -4
  95. data/lib/geocoder/stores/active_record.rb +16 -5
  96. data/lib/geocoder/stores/base.rb +1 -2
  97. data/lib/geocoder/version.rb +1 -1
  98. data/lib/hash_recursive_merge.rb +1 -2
  99. data/lib/maxmind_database.rb +3 -3
  100. data/lib/tasks/geocoder.rake +11 -3
  101. metadata +30 -14
  102. data/lib/geocoder/lookups/geocoder_us.rb +0 -43
  103. data/lib/geocoder/lookups/mapzen.rb +0 -15
  104. data/lib/geocoder/lookups/okf.rb +0 -44
  105. data/lib/geocoder/lookups/ovi.rb +0 -62
  106. data/lib/geocoder/results/geocoder_us.rb +0 -39
  107. data/lib/geocoder/results/mapzen.rb +0 -5
  108. data/lib/geocoder/results/okf.rb +0 -106
  109. data/lib/geocoder/results/ovi.rb +0 -71
@@ -4,7 +4,6 @@ require 'uri'
4
4
 
5
5
  unless defined?(ActiveSupport::JSON)
6
6
  begin
7
- require 'rubygems' # for Ruby 1.8
8
7
  require 'json'
9
8
  rescue LoadError
10
9
  raise LoadError, "Please install the 'json' or 'json_pure' gem to parse geocoder results."
@@ -72,8 +71,12 @@ module Geocoder
72
71
  ##
73
72
  # URL to use for querying the geocoding engine.
74
73
  #
74
+ # Subclasses should not modify this method. Instead they should define
75
+ # base_query_url and url_query_string. If absolutely necessary to
76
+ # subclss this method, they must also subclass #cache_key.
77
+ #
75
78
  def query_url(query)
76
- fail
79
+ base_query_url(query) + url_query_string(query)
77
80
  end
78
81
 
79
82
  ##
@@ -97,6 +100,14 @@ module Geocoder
97
100
 
98
101
  private # -------------------------------------------------------------
99
102
 
103
+ ##
104
+ # String which, when concatenated with url_query_string(query)
105
+ # produces the full query URL. Should include the "?" a the end.
106
+ #
107
+ def base_query_url(query)
108
+ fail
109
+ end
110
+
100
111
  ##
101
112
  # An object with configuration data for this particular lookup.
102
113
  #
@@ -147,7 +158,14 @@ module Geocoder
147
158
  # something else (like the URL before OAuth encoding).
148
159
  #
149
160
  def cache_key(query)
150
- query_url(query)
161
+ base_query_url(query) + hash_to_query(cache_key_params(query))
162
+ end
163
+
164
+ def cache_key_params(query)
165
+ # omit api_key and token because they may vary among requests
166
+ query_url_params(query).reject do |key,value|
167
+ key.to_s.match(/(key|token)/)
168
+ end
151
169
  end
152
170
 
153
171
  ##
@@ -179,6 +197,8 @@ module Geocoder
179
197
  raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
180
198
  rescue Errno::ECONNREFUSED => err
181
199
  raise_error(err) or Geocoder.log(:warn, "Geocoding API connection refused.")
200
+ rescue Geocoder::NetworkError => err
201
+ raise_error(err) or Geocoder.log(:warn, "Geocoding API connection is either unreacheable or reset by the peer")
182
202
  rescue Timeout::Error => err
183
203
  raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
184
204
  "(use Geocoder.configure(:timeout => ...) to set limit).")
@@ -191,7 +211,10 @@ module Geocoder
191
211
  JSON.parse(data)
192
212
  end
193
213
  rescue
194
- raise_error(ResponseParseError.new(data)) or Geocoder.log(:warn, "Geocoding API's response was not valid JSON: #{data}")
214
+ unless raise_error(ResponseParseError.new(data))
215
+ Geocoder.log(:warn, "Geocoding API's response was not valid JSON")
216
+ Geocoder.log(:debug, "Raw response: #{data}")
217
+ end
195
218
  end
196
219
 
197
220
  ##
@@ -286,7 +309,7 @@ module Geocoder
286
309
  end
287
310
  rescue Timeout::Error
288
311
  raise Geocoder::LookupTimeout
289
- rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH
312
+ rescue Errno::EHOSTUNREACH, Errno::ETIMEDOUT, Errno::ENETUNREACH, Errno::ECONNRESET
290
313
  raise Geocoder::NetworkError
291
314
  end
292
315
 
@@ -16,24 +16,20 @@ module Geocoder::Lookup
16
16
  ["key"]
17
17
  end
18
18
 
19
- def query_url(query)
20
- base_url(query) + url_query_string(query)
21
- end
22
-
23
19
  private # ---------------------------------------------------------------
24
20
 
25
- def base_url(query)
26
- url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations"
27
-
28
- if !query.reverse_geocode?
21
+ def base_query_url(query)
22
+ text = CGI.escape(query.sanitized_text.strip)
23
+ url = "#{protocol}://dev.virtualearth.net/REST/v1/Locations/"
24
+ if query.reverse_geocode?
25
+ url + "#{text}?"
26
+ else
29
27
  if r = query.options[:region]
30
- url << "/#{r}"
28
+ url << "#{r}/"
31
29
  end
32
30
  # use the more forgiving 'unstructured' query format to allow special
33
31
  # chars, newlines, brackets, typos.
34
- url + "?q=" + URI.escape(query.sanitized_text.strip) + "&"
35
- else
36
- url + "/#{URI.escape(query.sanitized_text.strip)}?"
32
+ url + "?q=#{text}&"
37
33
  end
38
34
  end
39
35
 
@@ -44,6 +40,11 @@ module Geocoder::Lookup
44
40
  return doc['resourceSets'].first['estimatedTotal'] > 0 ? doc['resourceSets'].first['resources'] : []
45
41
  elsif doc['statusCode'] == 401 and doc["authenticationResultCode"] == "InvalidCredentials"
46
42
  raise_error(Geocoder::InvalidApiKey) || Geocoder.log(:warn, "Invalid Bing API key.")
43
+ elsif doc['statusCode'] == 403
44
+ raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Bing Geocoding API error: Forbidden Request")
45
+ elsif [500, 503].include?(doc['statusCode'])
46
+ raise_error(Geocoder::ServiceUnavailable) ||
47
+ Geocoder.log(:warn, "Bing Geocoding API error: Service Unavailable")
47
48
  else
48
49
  Geocoder.log(:warn, "Bing Geocoding API error: #{doc['statusCode']} (#{doc['statusDescription']}).")
49
50
  end
@@ -52,7 +53,8 @@ module Geocoder::Lookup
52
53
 
53
54
  def query_url_params(query)
54
55
  {
55
- key: configuration.api_key
56
+ key: configuration.api_key,
57
+ language: (query.language || configuration.language)
56
58
  }.merge(super)
57
59
  end
58
60
 
@@ -0,0 +1,52 @@
1
+ require 'geocoder/lookups/base'
2
+ require 'geocoder/results/db_ip_com'
3
+
4
+ module Geocoder::Lookup
5
+ class DbIpCom < Base
6
+
7
+ def name
8
+ 'DB-IP.com'
9
+ end
10
+
11
+ def supported_protocols
12
+ [:https, :http]
13
+ end
14
+
15
+ def required_api_key_parts
16
+ ['api_key']
17
+ end
18
+
19
+ private # ----------------------------------------------------------------
20
+
21
+ def base_query_url(query)
22
+ "#{protocol}://api.db-ip.com/v2/#{configuration.api_key}/#{query.sanitized_text}?"
23
+ end
24
+
25
+ ##
26
+ # Same as query_url but without the api key.
27
+ #
28
+ def cache_key(query)
29
+ "#{protocol}://api.db-ip.com/v2/#{query.sanitized_text}?" + hash_to_query(cache_key_params(query))
30
+ end
31
+
32
+ def results(query)
33
+ return [] unless (doc = fetch_data(query))
34
+
35
+ case doc['error']
36
+ when 'maximum number of queries per day exceeded'
37
+ raise_error Geocoder::OverQueryLimitError ||
38
+ Geocoder.log(:warn, 'DB-API query limit exceeded.')
39
+
40
+ when 'invalid API key'
41
+ raise_error Geocoder::InvalidApiKey ||
42
+ Geocoder.log(:warn, 'Invalid DB-IP API key.')
43
+ when nil
44
+ [doc]
45
+
46
+ else
47
+ raise_error Geocoder::Error ||
48
+ Geocoder.log(:warn, "Request failed: #{doc['error']}")
49
+ end
50
+ end
51
+ end
52
+ end
@@ -12,9 +12,11 @@ module Geocoder::Lookup
12
12
  "Data Science Toolkit"
13
13
  end
14
14
 
15
- def query_url(query)
15
+ private # ----------------------------------------------------------------
16
+
17
+ def base_query_url(query)
16
18
  host = configuration[:host] || "www.datasciencetoolkit.org"
17
- "#{protocol}://#{host}/maps/api/geocode/json?" + url_query_string(query)
19
+ "#{protocol}://#{host}/maps/api/geocode/json?"
18
20
  end
19
21
  end
20
22
  end
@@ -4,15 +4,11 @@ require 'geocoder/esri_token'
4
4
 
5
5
  module Geocoder::Lookup
6
6
  class Esri < Base
7
-
7
+
8
8
  def name
9
9
  "Esri"
10
10
  end
11
11
 
12
- def query_url(query)
13
- base_query_url(query) + url_query_string(query)
14
- end
15
-
16
12
  private # ---------------------------------------------------------------
17
13
 
18
14
  def base_query_url(query)
@@ -34,17 +30,6 @@ module Geocoder::Lookup
34
30
  end
35
31
  end
36
32
 
37
- def cache_key(query)
38
- base_query_url(query) + hash_to_query(cache_key_params(query))
39
- end
40
-
41
- def cache_key_params(query)
42
- # omit api_key and token because they may vary among requests
43
- query_url_params(query).reject do |key,value|
44
- [:api_key, :token].include?(key)
45
- end
46
- end
47
-
48
33
  def query_url_params(query)
49
34
  params = {
50
35
  :f => "pjson",
@@ -55,31 +40,56 @@ module Geocoder::Lookup
55
40
  else
56
41
  params[:text] = query.sanitized_text
57
42
  end
58
- params[:token] = token
59
- params[:forStorage] = configuration[:for_storage] if configuration[:for_storage]
43
+
44
+ params[:token] = token(query)
45
+
46
+ if for_storage_value = for_storage(query)
47
+ params[:forStorage] = for_storage_value
48
+ end
60
49
  params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
61
50
  params.merge(super)
62
51
  end
63
52
 
64
- def token
65
- create_and_save_token! if !valid_token_configured? and configuration.api_key
66
- configuration[:token].to_s unless configuration[:token].nil?
53
+ def for_storage(query)
54
+ if query.options.has_key?(:for_storage)
55
+ query.options[:for_storage]
56
+ else
57
+ configuration[:for_storage]
58
+ end
59
+ end
60
+
61
+ def token(query)
62
+ token_instance = if query.options[:token]
63
+ query.options[:token]
64
+ else
65
+ configuration[:token]
66
+ end
67
+
68
+ if !valid_token_configured?(token_instance) && configuration.api_key
69
+ token_instance = create_and_save_token!(query)
70
+ end
71
+
72
+ token_instance.to_s unless token_instance.nil?
67
73
  end
68
74
 
69
- def valid_token_configured?
70
- !configuration[:token].nil? and configuration[:token].active?
75
+ def valid_token_configured?(token_instance)
76
+ !token_instance.nil? && token_instance.active?
71
77
  end
72
78
 
73
- def create_and_save_token!
74
- save_token!(create_token)
79
+ def create_and_save_token!(query)
80
+ token_instance = create_token
81
+
82
+ if query.options[:token]
83
+ query.options[:token] = token_instance
84
+ else
85
+ Geocoder.merge_into_lookup_config(:esri, token: token_instance)
86
+ end
87
+
88
+ token_instance
75
89
  end
76
90
 
77
91
  def create_token
78
92
  Geocoder::EsriToken.generate_token(*configuration.api_key)
79
93
  end
80
-
81
- def save_token!(token_instance)
82
- Geocoder.merge_into_lookup_config(:esri, token: token_instance)
83
- end
84
94
  end
85
95
  end
@@ -7,9 +7,14 @@ module Geocoder::Lookup
7
7
  def name
8
8
  "FreeGeoIP"
9
9
  end
10
-
10
+
11
11
  def supported_protocols
12
- [:http]
12
+ if configuration[:host]
13
+ [:https]
14
+ else
15
+ # use https for default host
16
+ [:https]
17
+ end
13
18
  end
14
19
 
15
20
  def query_url(query)
@@ -18,13 +23,17 @@ module Geocoder::Lookup
18
23
 
19
24
  private # ---------------------------------------------------------------
20
25
 
26
+ def cache_key(query)
27
+ query_url(query)
28
+ end
29
+
21
30
  def parse_raw_data(raw_data)
22
31
  raw_data.match(/^<html><title>404/) ? nil : super(raw_data)
23
32
  end
24
33
 
25
34
  def results(query)
26
- # don't look up a loopback address, just return the stored result
27
- return [reserved_result(query.text)] if query.loopback_ip_address?
35
+ # don't look up a loopback or private address, just return the stored result
36
+ return [reserved_result(query.text)] if query.internal_ip_address?
28
37
  # note: Freegeoip.net returns plain text "Not Found" on bad request
29
38
  (doc = fetch_data(query)) ? [doc] : []
30
39
  end
@@ -35,8 +44,8 @@ module Geocoder::Lookup
35
44
  "city" => "",
36
45
  "region_code" => "",
37
46
  "region_name" => "",
38
- "metrocode" => "",
39
- "zipcode" => "",
47
+ "metro_code" => "",
48
+ "zip_code" => "",
40
49
  "latitude" => "0",
41
50
  "longitude" => "0",
42
51
  "country_name" => "Reserved",
@@ -45,7 +54,7 @@ module Geocoder::Lookup
45
54
  end
46
55
 
47
56
  def host
48
- configuration[:host] || "freegeoip.io"
57
+ configuration[:host] || "freegeoip.app"
49
58
  end
50
59
  end
51
60
  end
@@ -8,12 +8,12 @@ module Geocoder::Lookup
8
8
  "Geocoder.ca"
9
9
  end
10
10
 
11
- def query_url(query)
12
- "#{protocol}://geocoder.ca/?" + url_query_string(query)
13
- end
14
-
15
11
  private # ---------------------------------------------------------------
16
12
 
13
+ def base_query_url(query)
14
+ "#{protocol}://geocoder.ca/?"
15
+ end
16
+
17
17
  def results(query)
18
18
  return [] unless doc = fetch_data(query)
19
19
  if doc['error'].nil?
@@ -8,11 +8,6 @@ module Geocoder::Lookup
8
8
  "Geocodio"
9
9
  end
10
10
 
11
- def query_url(query)
12
- path = query.reverse_geocode? ? "reverse" : "geocode"
13
- "#{protocol}://api.geocod.io/v1/#{path}?#{url_query_string(query)}"
14
- end
15
-
16
11
  def results(query)
17
12
  return [] unless doc = fetch_data(query)
18
13
  return doc["results"] if doc['error'].nil?
@@ -32,6 +27,11 @@ module Geocoder::Lookup
32
27
 
33
28
  private # ---------------------------------------------------------------
34
29
 
30
+ def base_query_url(query)
31
+ path = query.reverse_geocode? ? "reverse" : "geocode"
32
+ "#{protocol}://api.geocod.io/v1.3/#{path}?"
33
+ end
34
+
35
35
  def query_url_params(query)
36
36
  {
37
37
  :api_key => configuration.api_key,
@@ -9,14 +9,14 @@ module Geocoder
9
9
  "Geoportail.lu"
10
10
  end
11
11
 
12
- def query_url(query)
13
- url_base_path(query) + url_query_string(query)
14
- end
15
-
16
- private
12
+ private # ---------------------------------------------------------------
17
13
 
18
- def url_base_path(query)
19
- query.reverse_geocode? ? reverse_geocode_url_base_path : search_url_base_path
14
+ def base_query_url(query)
15
+ if query.reverse_geocode?
16
+ reverse_geocode_url_base_path
17
+ else
18
+ search_url_base_path
19
+ end
20
20
  end
21
21
 
22
22
  def search_url_base_path
@@ -21,12 +21,12 @@ module Geocoder::Lookup
21
21
  end
22
22
  end
23
23
 
24
- def query_url(query)
25
- "#{protocol}://maps.googleapis.com/maps/api/geocode/json?" + url_query_string(query)
26
- end
27
-
28
24
  private # ---------------------------------------------------------------
29
25
 
26
+ def base_query_url(query)
27
+ "#{protocol}://maps.googleapis.com/maps/api/geocode/json?"
28
+ end
29
+
30
30
  def configure_ssl!(client)
31
31
  client.instance_eval {
32
32
  @ssl_context = OpenSSL::SSL::SSLContext.new
@@ -52,21 +52,25 @@ module Geocoder::Lookup
52
52
  raise_error(Geocoder::OverQueryLimitError) ||
53
53
  Geocoder.log(:warn, "#{name} API error: over query limit.")
54
54
  when "REQUEST_DENIED"
55
- raise_error(Geocoder::RequestDenied) ||
56
- Geocoder.log(:warn, "#{name} API error: request denied.")
55
+ raise_error(Geocoder::RequestDenied, doc['error_message']) ||
56
+ Geocoder.log(:warn, "#{name} API error: request denied (#{doc['error_message']}).")
57
57
  when "INVALID_REQUEST"
58
- raise_error(Geocoder::InvalidRequest) ||
59
- Geocoder.log(:warn, "#{name} API error: invalid request.")
58
+ raise_error(Geocoder::InvalidRequest, doc['error_message']) ||
59
+ Geocoder.log(:warn, "#{name} API error: invalid request (#{doc['error_message']}).")
60
60
  end
61
61
  return []
62
62
  end
63
63
 
64
64
  def query_url_google_params(query)
65
65
  params = {
66
- (query.reverse_geocode? ? :latlng : :address) => query.sanitized_text,
67
66
  :sensor => "false",
68
67
  :language => (query.language || configuration.language)
69
68
  }
69
+ if query.options[:google_place_id]
70
+ params[:place_id] = query.sanitized_text
71
+ else
72
+ params[(query.reverse_geocode? ? :latlng : :address)] = query.sanitized_text
73
+ end
70
74
  unless (bounds = query.options[:bounds]).nil?
71
75
  params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join('|')
72
76
  end