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
@@ -7,38 +7,34 @@ module Geocoder::Result
7
7
  ['lat', 'lng'].map{ |i| @data['location'][i] }
8
8
  end
9
9
 
10
- def address
11
- @data['formatted_address']
12
- end
13
-
14
- def state
15
- province
16
- end
17
-
18
10
  def province
19
- @data['addressComponent']['province']
11
+ @data['addressComponent'] and @data['addressComponent']['province'] or ""
20
12
  end
21
13
 
14
+ alias_method :state, :province
15
+
22
16
  def city
23
- @data['addressComponent']['city']
17
+ @data['addressComponent'] and @data['addressComponent']['city'] or ""
24
18
  end
25
19
 
26
20
  def district
27
- @data['addressComponent']['district']
21
+ @data['addressComponent'] and @data['addressComponent']['district'] or ""
28
22
  end
29
23
 
30
24
  def street
31
- @data['addressComponent']['street']
25
+ @data['addressComponent'] and @data['addressComponent']['street'] or ""
32
26
  end
33
27
 
34
28
  def street_number
35
- @data['addressComponent']['street_number']
29
+ @data['addressComponent'] and @data['addressComponent']['street_number']
36
30
  end
37
31
 
38
32
  def formatted_address
39
- @data['formatted_address']
33
+ @data['formatted_address'] or ""
40
34
  end
41
35
 
36
+ alias_method :address, :formatted_address
37
+
42
38
  def address_components
43
39
  @data['addressComponent']
44
40
  end
@@ -7,7 +7,7 @@ module Geocoder::Result
7
7
  #### BASE METHODS ####
8
8
 
9
9
  def self.response_attributes
10
- %w[limit attribution version licence type features]
10
+ %w[limit attribution version licence type features center]
11
11
  end
12
12
 
13
13
  response_attributes.each do |a|
@@ -20,8 +20,20 @@ module Geocoder
20
20
  ##
21
21
  # A string in the given format.
22
22
  #
23
+ # This default implementation dumbly follows the United States address
24
+ # format and will return incorrect results for most countries. Some APIs
25
+ # return properly formatted addresses and those should be funneled
26
+ # through this method.
27
+ #
23
28
  def address(format = :full)
24
- fail
29
+ if state_code.to_s != ""
30
+ s = ", #{state_code}"
31
+ elsif state.to_s != ""
32
+ s = ", #{state}"
33
+ else
34
+ s = ""
35
+ end
36
+ "#{city}#{s} #{postal_code}, #{country}".sub(/^[ ,]*/, '')
25
37
  end
26
38
 
27
39
  ##
@@ -24,7 +24,7 @@ module Geocoder::Result
24
24
  alias_method :country_code, :country
25
25
 
26
26
  def postal_code
27
- @data['address']['postalCode']
27
+ @data['address']['postalCode'].to_s
28
28
  end
29
29
 
30
30
  def coordinates
@@ -0,0 +1,58 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class DbIpCom < Base
5
+
6
+ def coordinates
7
+ ['latitude', 'longitude'].map{ |coordinate_name| @data[coordinate_name] }
8
+ end
9
+
10
+ def city
11
+ @data['city']
12
+ end
13
+
14
+ def district
15
+ @data['district']
16
+ end
17
+
18
+ def state_code
19
+ @data['stateProv']
20
+ end
21
+ alias_method :state, :state_code
22
+
23
+ def zip_code
24
+ @data['zipCode']
25
+ end
26
+ alias_method :postal_code, :zip_code
27
+
28
+ def country_name
29
+ @data['countryName']
30
+ end
31
+ alias_method :country, :country_name
32
+
33
+ def country_code
34
+ @data['countryCode']
35
+ end
36
+
37
+ def continent_name
38
+ @data['continentName']
39
+ end
40
+ alias_method :continent, :continent_name
41
+
42
+ def continent_code
43
+ @data['continentCode']
44
+ end
45
+
46
+ def time_zone
47
+ @data['timeZone']
48
+ end
49
+
50
+ def gmt_offset
51
+ @data['gmtOffset']
52
+ end
53
+
54
+ def currency_code
55
+ @data['currencyCode']
56
+ end
57
+ end
58
+ end
@@ -3,11 +3,6 @@ require 'geocoder/results/base'
3
3
  module Geocoder::Result
4
4
  class Freegeoip < Base
5
5
 
6
- def address(format = :full)
7
- s = state_code.to_s == "" ? "" : ", #{state_code}"
8
- "#{city}#{s} #{postal_code}, #{country}".sub(/^[ ,]*/, "")
9
- end
10
-
11
6
  def city
12
7
  @data['city']
13
8
  end
@@ -16,17 +16,17 @@ module Geocoder::Result
16
16
  end
17
17
 
18
18
  def city
19
- @data['city']
19
+ @data['city'] or (@data['standard'] and @data['standard']['city']) or ""
20
20
  end
21
21
 
22
22
  def state
23
- @data['prov']
23
+ @data['prov'] or (@data['standard'] and @data['standard']['prov']) or ""
24
24
  end
25
25
 
26
26
  alias_method :state_code, :state
27
27
 
28
28
  def postal_code
29
- @data['postal']
29
+ @data['postal'] or (@data['standard'] and @data['standard']['postal']) or ""
30
30
  end
31
31
 
32
32
  def country
@@ -3,10 +3,6 @@ require 'geocoder/results/base'
3
3
  module Geocoder
4
4
  module Result
5
5
  class Geoip2 < Base
6
- def address(format = :full)
7
- s = state.to_s == '' ? '' : ", #{state_code}"
8
- "#{city}#{s} #{postal_code}, #{country}".sub(/^[ ,]*/, '')
9
- end
10
6
 
11
7
  def coordinates
12
8
  %w[latitude longitude].map do |l|
@@ -15,11 +11,15 @@ module Geocoder
15
11
  end
16
12
 
17
13
  def city
18
- data.fetch('city', {}).fetch('names', {}).fetch(locale, '')
14
+ fetch_name(
15
+ data.fetch('city', {}).fetch('names', {})
16
+ )
19
17
  end
20
18
 
21
19
  def state
22
- data.fetch('subdivisions', []).fetch(0, {}).fetch('names', {}).fetch(locale, '')
20
+ fetch_name(
21
+ data.fetch('subdivisions', []).fetch(0, {}).fetch('names', {})
22
+ )
23
23
  end
24
24
 
25
25
  def state_code
@@ -27,7 +27,9 @@ module Geocoder
27
27
  end
28
28
 
29
29
  def country
30
- data.fetch('country', {}).fetch('names', {}).fetch(locale, '')
30
+ fetch_name(
31
+ data.fetch('country', {}).fetch('names', {})
32
+ )
31
33
  end
32
34
 
33
35
  def country_code
@@ -48,14 +50,26 @@ module Geocoder
48
50
  end
49
51
  end
50
52
 
51
- private
53
+ def language=(l)
54
+ @language = l.to_s
55
+ end
56
+
57
+ def language
58
+ @language ||= default_language
59
+ end
52
60
 
53
61
  def data
54
62
  @data.to_hash
55
63
  end
56
64
 
57
- def locale
58
- @locale ||= Geocoder.config[:language].to_s
65
+ private
66
+
67
+ def default_language
68
+ @default_language = Geocoder.config[:language].to_s
69
+ end
70
+
71
+ def fetch_name(names)
72
+ names[language] || names[default_language] || ''
59
73
  end
60
74
  end
61
75
  end
@@ -59,11 +59,13 @@ module Geocoder::Result
59
59
  private
60
60
 
61
61
  def geolocalized?
62
- try_to_extract('coordinates', geomlonlat).present?
62
+ !!try_to_extract('coordinates', geomlonlat)
63
63
  end
64
64
 
65
- def try_to_extract(key, nullable_hash)
66
- nullable_hash.try(:[], key)
65
+ def try_to_extract(key, hash)
66
+ if hash.is_a?(Hash) and hash.include?(key)
67
+ hash[key]
68
+ end
67
69
  end
68
70
  end
69
71
  end
@@ -120,19 +120,30 @@ module Geocoder::Result
120
120
  def precision
121
121
  geometry['location_type'] if geometry
122
122
  end
123
-
123
+
124
124
  def partial_match
125
125
  @data['partial_match']
126
126
  end
127
-
127
+
128
128
  def place_id
129
129
  @data['place_id']
130
- end
130
+ end
131
131
 
132
132
  def viewport
133
133
  viewport = geometry['viewport'] || fail
134
- south, west = %w(lat lng).map { |c| viewport['southwest'][c] }
135
- north, east = %w(lat lng).map { |c| viewport['northeast'][c] }
134
+ bounding_box_from viewport
135
+ end
136
+
137
+ def bounds
138
+ bounding_box_from geometry['bounds']
139
+ end
140
+
141
+ private
142
+
143
+ def bounding_box_from(box)
144
+ return nil unless box
145
+ south, west = %w(lat lng).map { |c| box['southwest'][c] }
146
+ north, east = %w(lat lng).map { |c| box['northeast'][c] }
136
147
  [south, west, north, east]
137
148
  end
138
149
  end
@@ -17,9 +17,20 @@ module Geocoder::Result
17
17
  fail unless d = @data['Location']['DisplayPosition']
18
18
  [d['Latitude'].to_f, d['Longitude'].to_f]
19
19
  end
20
+
21
+ def route
22
+ address_data['Street']
23
+ end
24
+
25
+ def street_number
26
+ address_data['HouseNumber']
27
+ end
20
28
 
21
29
  def state
22
- address_data['County']
30
+ fail unless d = address_data['AdditionalData']
31
+ if v = d.find{|ad| ad['key']=='StateName'}
32
+ return v['value']
33
+ end
23
34
  end
24
35
 
25
36
  def province
@@ -0,0 +1,22 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Ip2location < Base
5
+
6
+ def address(format = :full)
7
+ "#{city_name} #{zip_code}, #{country_name}".sub(/^[ ,]*/, '')
8
+ end
9
+
10
+ def self.response_attributes
11
+ %w[country_code country_name region_name city_name latitude longitude
12
+ zip_code time_zone isp domain net_speed idd_code area_code usage_type
13
+ weather_station_code weather_station_name mcc mnc mobile_brand elevation]
14
+ end
15
+
16
+ response_attributes.each do |attr|
17
+ define_method attr do
18
+ @data[attr] || ""
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,40 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class IpdataCo < Base
5
+
6
+ def city
7
+ @data['city']
8
+ end
9
+
10
+ def state
11
+ @data['region']
12
+ end
13
+
14
+ def state_code
15
+ @data['region_code']
16
+ end
17
+
18
+ def country
19
+ @data['country_name']
20
+ end
21
+
22
+ def country_code
23
+ @data['country_code']
24
+ end
25
+
26
+ def postal_code
27
+ @data['postal']
28
+ end
29
+
30
+ def self.response_attributes
31
+ %w[ip asn organisation currency currency_symbol calling_code flag time_zone is_eu]
32
+ end
33
+
34
+ response_attributes.each do |a|
35
+ define_method a do
36
+ @data[a]
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,59 @@
1
+ require 'geocoder/results/base'
2
+
3
+ module Geocoder::Result
4
+ class Ipgeolocation < Base
5
+
6
+ def coordinates
7
+ [@data['latitude'].to_f, @data['longitude'].to_f]
8
+ end
9
+
10
+ def address(format = :full)
11
+ "#{city}, #{state} #{postal_code}, #{country_name}".sub(/^[ ,]*/, "")
12
+ end
13
+
14
+ def state
15
+ @data['state_prov']
16
+ end
17
+
18
+ def state_code
19
+ @data['state_prov']
20
+ end
21
+
22
+ def country
23
+ @data['country_name']
24
+ end
25
+
26
+ def country_code
27
+ @data['country_code2']
28
+ end
29
+
30
+ def postal_code
31
+ @data['zipcode']
32
+ end
33
+
34
+ def self.response_attributes
35
+ [
36
+ ['ip', ''],
37
+ ['hostname', ''],
38
+ ['continent_code', ''],
39
+ ['continent_name', ''],
40
+ ['country_code2', ''],
41
+ ['country_code3', ''],
42
+ ['country_name', ''],
43
+ ['country_capital',''],
44
+ ['district',''],
45
+ ['state_prov',''],
46
+ ['city', ''],
47
+ ['zipcode', ''],
48
+ ['time_zone', {}],
49
+ ['currency', {}]
50
+ ]
51
+ end
52
+
53
+ response_attributes.each do |attr, default|
54
+ define_method attr do
55
+ @data[attr] || default
56
+ end
57
+ end
58
+ end
59
+ end