geocoder 1.5.1 → 1.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +26 -0
  3. data/LICENSE +1 -1
  4. data/README.md +8 -10
  5. data/bin/console +13 -0
  6. data/examples/autoexpire_cache_redis.rb +2 -0
  7. data/lib/easting_northing.rb +171 -0
  8. data/lib/geocoder/ip_address.rb +2 -1
  9. data/lib/geocoder/lookup.rb +7 -3
  10. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +13 -0
  11. data/lib/geocoder/lookups/base.rb +2 -0
  12. data/lib/geocoder/lookups/esri.rb +2 -0
  13. data/lib/geocoder/lookups/freegeoip.rb +4 -4
  14. data/lib/geocoder/lookups/here.rb +7 -16
  15. data/lib/geocoder/lookups/ip2location.rb +5 -13
  16. data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  17. data/lib/geocoder/lookups/ipregistry.rb +68 -0
  18. data/lib/geocoder/lookups/latlon.rb +1 -2
  19. data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  20. data/lib/geocoder/lookups/osmnames.rb +57 -0
  21. data/lib/geocoder/lookups/pickpoint.rb +1 -1
  22. data/lib/geocoder/lookups/smarty_streets.rb +6 -1
  23. data/lib/geocoder/lookups/telize.rb +1 -1
  24. data/lib/geocoder/lookups/tencent.rb +9 -9
  25. data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  26. data/lib/geocoder/lookups/yandex.rb +3 -4
  27. data/lib/geocoder/results/baidu.rb +0 -4
  28. data/lib/geocoder/results/ban_data_gouv_fr.rb +1 -1
  29. data/lib/geocoder/results/here.rb +4 -1
  30. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  31. data/lib/geocoder/results/ipregistry.rb +308 -0
  32. data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  33. data/lib/geocoder/results/osmnames.rb +56 -0
  34. data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  35. data/lib/geocoder/results/yandex.rb +217 -59
  36. data/lib/geocoder/sql.rb +4 -4
  37. data/lib/geocoder/version.rb +1 -1
  38. data/lib/hash_recursive_merge.rb +1 -2
  39. data/lib/maxmind_database.rb +3 -3
  40. metadata +19 -15
  41. data/lib/geocoder/lookups/geocoder_us.rb +0 -51
  42. data/lib/geocoder/results/geocoder_us.rb +0 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: e556ddf944bdad35735def9028fafebcf61ee294
4
- data.tar.gz: a64476b63f73c13f24e385bc090193422bb92faa
2
+ SHA256:
3
+ metadata.gz: b8ab5b6c482a72aa85d0594577eb88c912ae9304254f006b9f7a37818318c94b
4
+ data.tar.gz: d2a71cc1cd294237c006ade75db89a99a2a01e31515eefc825aa833cb136acaa
5
5
  SHA512:
6
- metadata.gz: '08394b88099374e31e32306a418865b2ffecc4df707044e277072b99d9cadc6f92e1acd70fc18884128f381e28c2c42571f66eb3968a983e214a5a1ca89cf839'
7
- data.tar.gz: 87dadf53fe66e26c2f3eec8bfc671b9cebaf76f50bd08f815ae8b08592bd2c87aab8fa1812ef07b282805383b81e93f9777d5224b5c86ebe412f6261fb9fe943
6
+ metadata.gz: 1badbbf1f2633044d3f9a3ce56cf89f1573538795128c945102c02141f76304dc6c3ef98fef8befe0b9865871beec1cd98109290f05c28cbc042162d084af3a9
7
+ data.tar.gz: 3edf26f306e5a72a764a0def55a74eeff0652e90956b3cba26d44e7c51a5746df01a6ae09639ea61773768b0ffd58be888bca687a3427f2e1e5cec202c12aa02
@@ -3,6 +3,32 @@ Changelog
3
3
 
4
4
  Major changes to Geocoder for each release. Please see the Git log for complete list of changes.
5
5
 
6
+ 1.6.3 (2020 Apr 30)
7
+ -------------------
8
+ * Update URL for :telize lookup (thanks github.com/alexwalling).
9
+ * Fix bug parsing IPv6 with port (thanks github.com/gdomingu).
10
+
11
+ 1.6.2 (2020 Mar 16)
12
+ -------------------
13
+ * Add support for :nationaal_georegister_nl lookup (thanks github.com/opensourceame).
14
+ * Add support for :uk_ordnance_survey_names lookup (thanks github.com/pezholio).
15
+ * Refactor and fix bugs in Yandex lookup (thanks github.com/iarie and stereodenis).
16
+
17
+ 1.6.1 (2020 Jan 23)
18
+ -------------------
19
+ * Sanitize lat/lon values passed to within_bounding_box to prevent SQL injection.
20
+
21
+ 1.6.0 (2020 Jan 6)
22
+ -------------------
23
+ * Drop support for Rails 3.x.
24
+ * Add support for :osmnames lookup (thanks github.com/zacviandier).
25
+ * Add support for :ipgeolocation IP lookup (thanks github.com/ahsannawaz111).
26
+
27
+ 1.5.2 (2019 Oct 3)
28
+ -------------------
29
+ * Add support for :ipregistry lookup (thanks github.com/ipregistry).
30
+ * Various fixes for Yandex lookup.
31
+
6
32
  1.5.1 (2019 Jan 23)
7
33
  -------------------
8
34
  * Add support for :tencent lookup (thanks github.com/Anders-E).
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009-11 Alex Reisner
1
+ Copyright (c) 2009-2020 Alex Reisner
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -1,29 +1,27 @@
1
1
  Geocoder
2
2
  ========
3
3
 
4
- **A complete geocoding solution for Ruby.**
4
+ **Complete geocoding solution for Ruby.**
5
5
 
6
6
  [![Gem Version](https://badge.fury.io/rb/geocoder.svg)](http://badge.fury.io/rb/geocoder)
7
7
  [![Code Climate](https://codeclimate.com/github/alexreisner/geocoder/badges/gpa.svg)](https://codeclimate.com/github/alexreisner/geocoder)
8
8
  [![Build Status](https://travis-ci.org/alexreisner/geocoder.svg?branch=master)](https://travis-ci.org/alexreisner/geocoder)
9
- [![GitHub Issues](https://img.shields.io/github/issues/alexreisner/geocoder.svg)](https://github.com/alexreisner/geocoder/issues)
10
- [![License](https://img.shields.io/badge/license-MIT-blue.svg)](https://opensource.org/licenses/MIT)
11
9
 
12
10
  Key features:
13
11
 
14
- * Forward and reverse geocoding, and IP address geocoding.
12
+ * Forward and reverse geocoding.
13
+ * IP address geocoding.
15
14
  * Connects to more than 40 APIs worldwide.
16
15
  * Performance-enhancing features like caching.
17
- * Advanced configuration allows different parameters and APIs to be used in different conditions.
18
16
  * Integrates with ActiveRecord and Mongoid.
19
17
  * Basic geospatial queries: search within radius (or rectangle, or ring).
20
18
 
21
19
  Compatibility:
22
20
 
23
- * Supports multiple Ruby versions: Ruby 2.x, and JRuby.
24
- * Supports multiple databases: MySQL, PostgreSQL, SQLite, and MongoDB (1.7.0 and higher).
25
- * Supports Rails 3, 4, and 5. If you need to use it with Rails 2 please see the `rails2` branch (no longer maintained, limited feature set).
26
- * Works very well outside of Rails, you just need to install either the `json` (for MRI) or `json_pure` (for JRuby) gem.
21
+ * Ruby versions: 2.x, and JRuby.
22
+ * Databases: MySQL, PostgreSQL, SQLite, and MongoDB.
23
+ * Rails: 4, 5, and 6.
24
+ * Works outside of Rails with the `json` (for MRI) or `json_pure` (for JRuby) gem.
27
25
 
28
26
 
29
27
  Table of Contents
@@ -703,4 +701,4 @@ For all contributions, please respect the following guidelines:
703
701
  * If your pull request is merged, please do not ask for an immediate release of the gem. There are many factors contributing to when releases occur (remember that they affect thousands of apps with Geocoder in their Gemfiles). If necessary, please install from the Github source until the next official release.
704
702
 
705
703
 
706
- Copyright (c) 2009-18 Alex Reisner, released under the MIT license.
704
+ Copyright :copyright: 2009-2020 Alex Reisner, released under the MIT license.
@@ -0,0 +1,13 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'bundler/setup'
4
+ require 'geocoder'
5
+
6
+ if File.exist?("api_keys.yml")
7
+ require 'yaml'
8
+ @api_keys = YAML.load(File.read("api_keys.yml"), symbolize_names: true)
9
+ Geocoder.configure(@api_keys)
10
+ end
11
+
12
+ require 'irb'
13
+ IRB.start
@@ -1,6 +1,8 @@
1
1
  # This class implements a cache with simple delegation to the Redis store, but
2
2
  # when it creates a key/value pair, it also sends an EXPIRE command with a TTL.
3
3
  # It should be fairly simple to do the same thing with Memcached.
4
+ # Alternatively, this class could inherit from Redis, which would make most
5
+ # of the below methods unnecessary.
4
6
  class AutoexpireCacheRedis
5
7
  def initialize(store, ttl = 86400)
6
8
  @store = store
@@ -0,0 +1,171 @@
1
+ module Geocoder
2
+ class EastingNorthing
3
+ attr_reader :easting, :northing, :lat_lng
4
+
5
+ def initialize(opts)
6
+ @easting = opts[:easting]
7
+ @northing = opts[:northing]
8
+
9
+ @lat_lng = to_WGS84(to_osgb_36)
10
+ end
11
+
12
+ private
13
+
14
+ def to_osgb_36
15
+ osgb_fo = 0.9996012717
16
+ northing0 = -100_000.0
17
+ easting0 = 400_000.0
18
+ phi0 = deg_to_rad(49.0)
19
+ lambda0 = deg_to_rad(-2.0)
20
+ a = 6_377_563.396
21
+ b = 6_356_256.909
22
+ eSquared = ((a * a) - (b * b)) / (a * a)
23
+ phi = 0.0
24
+ lambda = 0.0
25
+ n = (a - b) / (a + b)
26
+ m = 0.0
27
+ phiPrime = ((northing - northing0) / (a * osgb_fo)) + phi0
28
+
29
+ while (northing - northing0 - m) >= 0.001
30
+ m =
31
+ (b * osgb_fo)\
32
+ * (((1 + n + ((5.0 / 4.0) * n * n) + ((5.0 / 4.0) * n * n * n))\
33
+ * (phiPrime - phi0))\
34
+ - (((3 * n) + (3 * n * n) + ((21.0 / 8.0) * n * n * n))\
35
+ * Math.sin(phiPrime - phi0)\
36
+ * Math.cos(phiPrime + phi0))\
37
+ + ((((15.0 / 8.0) * n * n) + ((15.0 / 8.0) * n * n * n))\
38
+ * Math.sin(2.0 * (phiPrime - phi0))\
39
+ * Math.cos(2.0 * (phiPrime + phi0)))\
40
+ - (((35.0 / 24.0) * n * n * n)\
41
+ * Math.sin(3.0 * (phiPrime - phi0))\
42
+ * Math.cos(3.0 * (phiPrime + phi0))))
43
+
44
+ phiPrime += (northing - northing0 - m) / (a * osgb_fo)
45
+ end
46
+
47
+ v = a * osgb_fo * ((1.0 - eSquared * sin_pow_2(phiPrime))**-0.5)
48
+ rho =
49
+ a\
50
+ * osgb_fo\
51
+ * (1.0 - eSquared)\
52
+ * ((1.0 - eSquared * sin_pow_2(phiPrime))**-1.5)
53
+ etaSquared = (v / rho) - 1.0
54
+ vii = Math.tan(phiPrime) / (2 * rho * v)
55
+ viii =
56
+ (Math.tan(phiPrime) / (24.0 * rho * (v**3.0)))\
57
+ * (5.0\
58
+ + (3.0 * tan_pow_2(phiPrime))\
59
+ + etaSquared\
60
+ - (9.0 * tan_pow_2(phiPrime) * etaSquared))
61
+ ix =
62
+ (Math.tan(phiPrime) / (720.0 * rho * (v**5.0)))\
63
+ * (61.0\
64
+ + (90.0 * tan_pow_2(phiPrime))\
65
+ + (45.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime)))
66
+ x = sec(phiPrime) / v
67
+ xi =
68
+ (sec(phiPrime) / (6.0 * v * v * v))\
69
+ * ((v / rho) + (2 * tan_pow_2(phiPrime)))
70
+ xiii =
71
+ (sec(phiPrime) / (120.0 * (v**5.0)))\
72
+ * (5.0\
73
+ + (28.0 * tan_pow_2(phiPrime))\
74
+ + (24.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime)))
75
+ xiia =
76
+ (sec(phiPrime) / (5040.0 * (v**7.0)))\
77
+ * (61.0\
78
+ + (662.0 * tan_pow_2(phiPrime))\
79
+ + (1320.0 * tan_pow_2(phiPrime) * tan_pow_2(phiPrime))\
80
+ + (720.0\
81
+ * tan_pow_2(phiPrime)\
82
+ * tan_pow_2(phiPrime)\
83
+ * tan_pow_2(phiPrime)))
84
+ phi =
85
+ phiPrime\
86
+ - (vii * ((easting - easting0)**2.0))\
87
+ + (viii * ((easting - easting0)**4.0))\
88
+ - (ix * ((easting - easting0)**6.0))
89
+ lambda =
90
+ lambda0\
91
+ + (x * (easting - easting0))\
92
+ - (xi * ((easting - easting0)**3.0))\
93
+ + (xiii * ((easting - easting0)**5.0))\
94
+ - (xiia * ((easting - easting0)**7.0))
95
+
96
+ [rad_to_deg(phi), rad_to_deg(lambda)]
97
+ end
98
+
99
+ def to_WGS84(latlng)
100
+ latitude = latlng[0]
101
+ longitude = latlng[1]
102
+
103
+ a = 6_377_563.396
104
+ b = 6_356_256.909
105
+ eSquared = ((a * a) - (b * b)) / (a * a)
106
+
107
+ phi = deg_to_rad(latitude)
108
+ lambda = deg_to_rad(longitude)
109
+ v = a / Math.sqrt(1 - eSquared * sin_pow_2(phi))
110
+ h = 0
111
+ x = (v + h) * Math.cos(phi) * Math.cos(lambda)
112
+ y = (v + h) * Math.cos(phi) * Math.sin(lambda)
113
+ z = ((1 - eSquared) * v + h) * Math.sin(phi)
114
+
115
+ tx = 446.448
116
+ ty = -124.157
117
+ tz = 542.060
118
+
119
+ s = -0.0000204894
120
+ rx = deg_to_rad(0.00004172222)
121
+ ry = deg_to_rad(0.00006861111)
122
+ rz = deg_to_rad(0.00023391666)
123
+
124
+ xB = tx + (x * (1 + s)) + (-rx * y) + (ry * z)
125
+ yB = ty + (rz * x) + (y * (1 + s)) + (-rx * z)
126
+ zB = tz + (-ry * x) + (rx * y) + (z * (1 + s))
127
+
128
+ a = 6_378_137.000
129
+ b = 6_356_752.3141
130
+ eSquared = ((a * a) - (b * b)) / (a * a)
131
+
132
+ lambdaB = rad_to_deg(Math.atan(yB / xB))
133
+ p = Math.sqrt((xB * xB) + (yB * yB))
134
+ phiN = Math.atan(zB / (p * (1 - eSquared)))
135
+
136
+ (1..10).each do |_i|
137
+ v = a / Math.sqrt(1 - eSquared * sin_pow_2(phiN))
138
+ phiN1 = Math.atan((zB + (eSquared * v * Math.sin(phiN))) / p)
139
+ phiN = phiN1
140
+ end
141
+
142
+ phiB = rad_to_deg(phiN)
143
+
144
+ [phiB, lambdaB]
145
+ end
146
+
147
+ def deg_to_rad(degrees)
148
+ degrees / 180.0 * Math::PI
149
+ end
150
+
151
+ def rad_to_deg(r)
152
+ (r / Math::PI) * 180
153
+ end
154
+
155
+ def sin_pow_2(x)
156
+ Math.sin(x) * Math.sin(x)
157
+ end
158
+
159
+ def cos_pow_2(x)
160
+ Math.cos(x) * Math.cos(x)
161
+ end
162
+
163
+ def tan_pow_2(x)
164
+ Math.tan(x) * Math.tan(x)
165
+ end
166
+
167
+ def sec(x)
168
+ 1.0 / Math.cos(x)
169
+ end
170
+ end
171
+ end
@@ -20,7 +20,8 @@ module Geocoder
20
20
  end
21
21
 
22
22
  def valid?
23
- !!((self =~ Resolv::IPv4::Regex) || (self =~ Resolv::IPv6::Regex))
23
+ ip = self[/(?<=\[)(.*?)(?=\])/] || self
24
+ !!((ip =~ Resolv::IPv4::Regex) || (ip =~ Resolv::IPv6::Regex))
24
25
  end
25
26
  end
26
27
  end
@@ -32,11 +32,12 @@ module Geocoder
32
32
  :google_places_search,
33
33
  :bing,
34
34
  :geocoder_ca,
35
- :geocoder_us,
36
35
  :yandex,
36
+ :nationaal_georegister_nl,
37
37
  :nominatim,
38
38
  :mapbox,
39
39
  :mapquest,
40
+ :uk_ordnance_survey_names,
40
41
  :opencagedata,
41
42
  :pelias,
42
43
  :pickpoint,
@@ -51,7 +52,8 @@ module Geocoder
51
52
  :ban_data_gouv_fr,
52
53
  :test,
53
54
  :latlon,
54
- :amap
55
+ :amap,
56
+ :osmnames
55
57
  ]
56
58
  end
57
59
 
@@ -69,11 +71,13 @@ module Geocoder
69
71
  :pointpin,
70
72
  :maxmind_geoip2,
71
73
  :ipinfo_io,
74
+ :ipregistry,
72
75
  :ipapi_com,
73
76
  :ipdata_co,
74
77
  :db_ip_com,
75
78
  :ipstack,
76
- :ip2location
79
+ :ip2location,
80
+ :ipgeolocation
77
81
  ]
78
82
  end
79
83
 
@@ -86,6 +86,12 @@ module Geocoder::Lookup
86
86
  unless (citycode = query.options[:citycode]).nil? || !code_param_is_valid?(citycode)
87
87
  params[:citycode] = citycode.to_s
88
88
  end
89
+ unless (lat = query.options[:lat]).nil? || !latitude_is_valid?(lat)
90
+ params[:lat] = lat
91
+ end
92
+ unless (lon = query.options[:lon]).nil? || !longitude_is_valid?(lon)
93
+ params[:lon] = lon
94
+ end
89
95
  params
90
96
  end
91
97
 
@@ -126,5 +132,12 @@ module Geocoder::Lookup
126
132
  (1..99999).include?(param.to_i)
127
133
  end
128
134
 
135
+ def latitude_is_valid?(param)
136
+ param.to_f <= 90 && param.to_f >= -90
137
+ end
138
+
139
+ def longitude_is_valid?(param)
140
+ param.to_f <= 180 && param.to_f >= -180
141
+ end
129
142
  end
130
143
  end
@@ -197,6 +197,8 @@ module Geocoder
197
197
  raise_error(err) or Geocoder.log(:warn, "Geocoding API connection cannot be established.")
198
198
  rescue Errno::ECONNREFUSED => err
199
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")
200
202
  rescue Timeout::Error => err
201
203
  raise_error(err) or Geocoder.log(:warn, "Geocoding API not responding fast enough " +
202
204
  "(use Geocoder.configure(:timeout => ...) to set limit).")
@@ -47,6 +47,8 @@ module Geocoder::Lookup
47
47
  params[:forStorage] = for_storage_value
48
48
  end
49
49
  params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
50
+ params[:preferredLabelValues] = configuration[:preferred_label_values] if configuration[:preferred_label_values]
51
+
50
52
  params.merge(super)
51
53
  end
52
54
 
@@ -10,7 +10,7 @@ module Geocoder::Lookup
10
10
 
11
11
  def supported_protocols
12
12
  if configuration[:host]
13
- [:http, :https]
13
+ [:https]
14
14
  else
15
15
  # use https for default host
16
16
  [:https]
@@ -44,8 +44,8 @@ module Geocoder::Lookup
44
44
  "city" => "",
45
45
  "region_code" => "",
46
46
  "region_name" => "",
47
- "metrocode" => "",
48
- "zipcode" => "",
47
+ "metro_code" => "",
48
+ "zip_code" => "",
49
49
  "latitude" => "0",
50
50
  "longitude" => "0",
51
51
  "country_name" => "Reserved",
@@ -54,7 +54,7 @@ module Geocoder::Lookup
54
54
  end
55
55
 
56
56
  def host
57
- configuration[:host] || "freegeoip.net"
57
+ configuration[:host] || "freegeoip.app"
58
58
  end
59
59
  end
60
60
  end
@@ -9,13 +9,17 @@ module Geocoder::Lookup
9
9
  end
10
10
 
11
11
  def required_api_key_parts
12
- ["app_id", "app_code"]
12
+ ['api_key']
13
+ end
14
+
15
+ def supported_protocols
16
+ [:https]
13
17
  end
14
18
 
15
19
  private # ---------------------------------------------------------------
16
20
 
17
21
  def base_query_url(query)
18
- "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.api.here.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
22
+ "#{protocol}://#{if query.reverse_geocode? then 'reverse.' end}geocoder.ls.hereapi.com/6.2/#{if query.reverse_geocode? then 'reverse' end}geocode.json?"
19
23
  end
20
24
 
21
25
  def results(query)
@@ -31,8 +35,7 @@ module Geocoder::Lookup
31
35
  def query_url_here_options(query, reverse_geocode)
32
36
  options = {
33
37
  gen: 9,
34
- app_id: api_key,
35
- app_code: api_code,
38
+ apikey: configuration.api_key,
36
39
  language: (query.language || configuration.language)
37
40
  }
38
41
  if reverse_geocode
@@ -61,17 +64,5 @@ module Geocoder::Lookup
61
64
  )
62
65
  end
63
66
  end
64
-
65
- def api_key
66
- if (a = configuration.api_key)
67
- return a.first if a.is_a?(Array)
68
- end
69
- end
70
-
71
- def api_code
72
- if (a = configuration.api_key)
73
- return a.last if a.is_a?(Array)
74
- end
75
- end
76
67
  end
77
68
  end