geocoder 1.5.2 → 1.6.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (53) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +40 -0
  3. data/LICENSE +1 -1
  4. data/README.md +16 -39
  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/cache.rb +4 -0
  9. data/lib/geocoder/configuration.rb +2 -1
  10. data/lib/geocoder/configuration_hash.rb +4 -4
  11. data/lib/geocoder/ip_address.rb +2 -1
  12. data/lib/geocoder/lookup.rb +7 -3
  13. data/lib/geocoder/lookups/abstract_api.rb +46 -0
  14. data/lib/geocoder/lookups/ban_data_gouv_fr.rb +14 -1
  15. data/lib/geocoder/lookups/esri.rb +6 -0
  16. data/lib/geocoder/lookups/geocodio.rb +1 -1
  17. data/lib/geocoder/lookups/google.rb +7 -2
  18. data/lib/geocoder/lookups/google_places_details.rb +8 -14
  19. data/lib/geocoder/lookups/google_places_search.rb +28 -2
  20. data/lib/geocoder/lookups/google_premier.rb +4 -0
  21. data/lib/geocoder/lookups/here.rb +7 -16
  22. data/lib/geocoder/lookups/ip2location.rb +5 -13
  23. data/lib/geocoder/lookups/ipgeolocation.rb +51 -0
  24. data/lib/geocoder/lookups/latlon.rb +1 -2
  25. data/lib/geocoder/lookups/maxmind_local.rb +7 -1
  26. data/lib/geocoder/lookups/nationaal_georegister_nl.rb +38 -0
  27. data/lib/geocoder/lookups/osmnames.rb +57 -0
  28. data/lib/geocoder/lookups/pickpoint.rb +1 -1
  29. data/lib/geocoder/lookups/smarty_streets.rb +6 -1
  30. data/lib/geocoder/lookups/telize.rb +1 -1
  31. data/lib/geocoder/lookups/tencent.rb +9 -9
  32. data/lib/geocoder/lookups/test.rb +4 -0
  33. data/lib/geocoder/lookups/uk_ordnance_survey_names.rb +59 -0
  34. data/lib/geocoder/lookups/yandex.rb +1 -2
  35. data/lib/geocoder/results/abstract_api.rb +146 -0
  36. data/lib/geocoder/results/baidu.rb +0 -4
  37. data/lib/geocoder/results/ban_data_gouv_fr.rb +27 -2
  38. data/lib/geocoder/results/db_ip_com.rb +1 -1
  39. data/lib/geocoder/results/ipgeolocation.rb +59 -0
  40. data/lib/geocoder/results/ipregistry.rb +4 -8
  41. data/lib/geocoder/results/nationaal_georegister_nl.rb +62 -0
  42. data/lib/geocoder/results/nominatim.rb +4 -0
  43. data/lib/geocoder/results/osmnames.rb +56 -0
  44. data/lib/geocoder/results/uk_ordnance_survey_names.rb +59 -0
  45. data/lib/geocoder/results/yandex.rb +217 -59
  46. data/lib/geocoder/sql.rb +4 -4
  47. data/lib/geocoder/util.rb +29 -0
  48. data/lib/geocoder/version.rb +1 -1
  49. data/lib/maxmind_database.rb +3 -3
  50. metadata +19 -11
  51. data/lib/geocoder/lookups/geocoder_us.rb +0 -51
  52. data/lib/geocoder/results/geocoder_us.rb +0 -39
  53. data/lib/hash_recursive_merge.rb +0 -74
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6e1ac31854d2fcd30eb9cecb552d2b148b17355da7b15a71130cee3a432c335
4
- data.tar.gz: 8cebc67335e4d3fd263249cc441673353cf0487415ccc8a855e2b457c6631e42
3
+ metadata.gz: 17d8f44da8b584b65c5546df089f0c16e6d20045676d4a1fe3fef38cdf3c3c59
4
+ data.tar.gz: c527329b8d1f28a326092e3b3f6d2c9c143dacc2da2397fab5b4109ae7387f09
5
5
  SHA512:
6
- metadata.gz: 826c1fb83145b010b610d34e42b0719673b4c51ce755b639425e3072bdb96dddcf373e605dce9f33c34aba46e95db71f64b50a84df71c67189a81fc8426f344b
7
- data.tar.gz: 698ef9a7643854cb7ac2316e22a51aed4a1a2ee763a8b65c9d7ab722566bbdcb3a95ce685389d20ecc164b3f9ccf1626deef21515d662d1339e88d28152985f7
6
+ metadata.gz: 918ed290277a1aa7e57a102ad06b0cf733e1908e9f31ead6cd59c5d08e5cc5b7d2f581a9958961781e013b535763c92701ad02f2bd8268374e339a36fd75eb25
7
+ data.tar.gz: 14416b59a9f34890d9a466aad87a883651f13f58a1f0a972c7d48370daed0f70923b9534b13e489673dbbc19543c82fb9017dd274529ce3a587bebe1f230649d
data/CHANGELOG.md CHANGED
@@ -3,6 +3,46 @@ 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.7 (2021 Apr 17)
7
+ -------------------
8
+ * Add support for Abstract API lookup (thanks github.com/randoum).
9
+
10
+ 1.6.6 (2021 Mar 4)
11
+ -------------------
12
+ * Rescue from exception on cache read/write error. Issue warning instead.
13
+
14
+ 1.6.5 (2021 Feb 10)
15
+ -------------------
16
+ * Fix backward coordinates bug in NationaalregisterNl lookup (thanks github.com/Marthyn).
17
+ * Allow removal of single stubs in test mode (thanks github.com/jmmastey).
18
+ * Improve results for :ban_data_gouv_fr lookup (thanks github.com/Intrepidd).
19
+
20
+ 1.6.4 (2020 Oct 6)
21
+ -------------------
22
+ * Various updates in response to geocoding API changes.
23
+ * Refactor of Google Places Search lookup (thanks github.com/maximilientyc).
24
+
25
+ 1.6.3 (2020 Apr 30)
26
+ -------------------
27
+ * Update URL for :telize lookup (thanks github.com/alexwalling).
28
+ * Fix bug parsing IPv6 with port (thanks github.com/gdomingu).
29
+
30
+ 1.6.2 (2020 Mar 16)
31
+ -------------------
32
+ * Add support for :nationaal_georegister_nl lookup (thanks github.com/opensourceame).
33
+ * Add support for :uk_ordnance_survey_names lookup (thanks github.com/pezholio).
34
+ * Refactor and fix bugs in Yandex lookup (thanks github.com/iarie and stereodenis).
35
+
36
+ 1.6.1 (2020 Jan 23)
37
+ -------------------
38
+ * Sanitize lat/lon values passed to within_bounding_box to prevent SQL injection.
39
+
40
+ 1.6.0 (2020 Jan 6)
41
+ -------------------
42
+ * Drop support for Rails 3.x.
43
+ * Add support for :osmnames lookup (thanks github.com/zacviandier).
44
+ * Add support for :ipgeolocation IP lookup (thanks github.com/ahsannawaz111).
45
+
6
46
  1.5.2 (2019 Oct 3)
7
47
  -------------------
8
48
  * Add support for :ipregistry lookup (thanks github.com/ipregistry).
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2009-11 Alex Reisner
1
+ Copyright (c) 2009-2021 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
@@ -53,8 +51,8 @@ The Rest:
53
51
  * [Technical Discussions](#technical-discussions)
54
52
  * [Troubleshooting](#troubleshooting)
55
53
  * [Known Issues](#known-issues)
56
- * [Reporting Issues](#reporting-issues)
57
- * [Contributing](#contributing)
54
+ * [Reporting Issues](https://github.com/alexreisner/geocoder/blob/master/CONTRIBUTING.md#reporting-bugs)
55
+ * [Contributing](https://github.com/alexreisner/geocoder/blob/master/CONTRIBUTING.md#making-changes)
58
56
 
59
57
  See Also:
60
58
 
@@ -215,7 +213,7 @@ Some common options are:
215
213
  # set default units to kilometers:
216
214
  units: :km,
217
215
 
218
- # caching (see [below](#caching) for details):
216
+ # caching (see Caching section below for details):
219
217
  cache: Redis.new,
220
218
  cache_prefix: "..."
221
219
 
@@ -534,10 +532,14 @@ With the above stub defined, any query for "New York, NY" will return the result
534
532
  ]
535
533
  )
536
534
 
535
+ You may also delete a single stub, or reset all stubs _including the default stub_:
536
+
537
+ Geocoder::Lookup::Test.delete_stub('New York, NY')
538
+ Geocoder::Lookup::Test.reset
539
+
537
540
  Notes:
538
541
 
539
542
  - Keys must be strings (not symbols) when calling `add_stub` or `set_default_stub`. For example `'country' =>` not `:country =>`.
540
- - To clear stubs (e.g. prior to another spec), use `Geocoder::Lookup::Test.reset`. This will clear all stubs _including the default stub_.
541
543
  - The stubbed result objects returned by the Test lookup do not support all the methods real result objects do. If you need to test interaction with real results it may be better to use an external stubbing tool and something like WebMock or VCR to prevent network calls.
542
544
 
543
545
 
@@ -678,29 +680,4 @@ If anyone has a more elegant solution to this problem I am very interested in se
678
680
  The `near` method will not look across the 180th meridian to find objects close to a given point. In practice this is rarely an issue outside of New Zealand and certain surrounding islands. This problem does not exist with the zero-meridian. The problem is due to a shortcoming of the Haversine formula which Geocoder uses to calculate distances.
679
681
 
680
682
 
681
- Reporting Issues
682
- ----------------
683
-
684
- When reporting an issue, please list the version of Geocoder you are using and any relevant information about your application (Rails version, database type and version, etc). Please describe as specifically as you can what behavior you are seeing (eg: an error message? a nil return value?).
685
-
686
- Please DO NOT use GitHub issues to ask questions about how to use Geocoder. Sites like [StackOverflow](http://www.stackoverflow.com/) are a better forum for such discussions.
687
-
688
-
689
- Contributing
690
- ------------
691
-
692
- Contributions are welcome via Github pull requests. If you are new to the project and looking for a way to get involved, try picking up an issue with a "beginner-task" label. Hints about what needs to be done are usually provided.
693
-
694
- For all contributions, please respect the following guidelines:
695
-
696
- * Each pull request should implement ONE feature or bugfix. If you want to add or fix more than one thing, submit more than one pull request.
697
- * Do not commit changes to files that are irrelevant to your feature or bugfix (eg: `.gitignore`).
698
- * Do not add dependencies on other gems.
699
- * Do not add unnecessary `require` statements which could cause LoadErrors on certain systems.
700
- * Remember: Geocoder needs to run outside of Rails. Don't assume things like ActiveSupport are available.
701
- * Be willing to accept criticism and work on improving your code; Geocoder is used by thousands of developers and care must be taken not to introduce bugs.
702
- * Be aware that the pull request review process is not immediate, and is generally proportional to the size of the pull request.
703
- * 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
-
705
-
706
- Copyright (c) 2009-18 Alex Reisner, released under the MIT license.
683
+ Copyright :copyright: 2009-2021 Alex Reisner, released under the MIT license.
data/bin/console ADDED
@@ -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
@@ -18,6 +18,8 @@ module Geocoder
18
18
  when store.respond_to?(:read)
19
19
  store.read key_for(url)
20
20
  end
21
+ rescue => e
22
+ warn "Geocoder cache read error: #{e}"
21
23
  end
22
24
 
23
25
  ##
@@ -32,6 +34,8 @@ module Geocoder
32
34
  when store.respond_to?(:write)
33
35
  store.write key_for(url), value
34
36
  end
37
+ rescue => e
38
+ warn "Geocoder cache write error: #{e}"
35
39
  end
36
40
 
37
41
  ##
@@ -1,5 +1,6 @@
1
1
  require 'singleton'
2
2
  require 'geocoder/configuration_hash'
3
+ require 'geocoder/util'
3
4
 
4
5
  module Geocoder
5
6
 
@@ -85,7 +86,7 @@ module Geocoder
85
86
  end
86
87
 
87
88
  def configure(options)
88
- @data.rmerge!(options)
89
+ Util.recursive_hash_merge(@data, options)
89
90
  end
90
91
 
91
92
  def initialize # :nodoc
@@ -1,11 +1,11 @@
1
- require 'hash_recursive_merge'
2
-
3
1
  module Geocoder
4
2
  class ConfigurationHash < Hash
5
- include HashRecursiveMerge
6
-
7
3
  def method_missing(meth, *args, &block)
8
4
  has_key?(meth) ? self[meth] : super
9
5
  end
6
+
7
+ def respond_to_missing?(meth, include_private = false)
8
+ has_key?(meth) || super
9
+ end
10
10
  end
11
11
  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
 
@@ -61,6 +63,7 @@ module Geocoder
61
63
  def ip_services
62
64
  @ip_services ||= [
63
65
  :baidu_ip,
66
+ :abstract_api,
64
67
  :freegeoip,
65
68
  :geoip2,
66
69
  :maxmind,
@@ -74,7 +77,8 @@ module Geocoder
74
77
  :ipdata_co,
75
78
  :db_ip_com,
76
79
  :ipstack,
77
- :ip2location
80
+ :ip2location,
81
+ :ipgeolocation
78
82
  ]
79
83
  end
80
84
 
@@ -0,0 +1,46 @@
1
+ # encoding: utf-8
2
+
3
+ require 'geocoder/lookups/base'
4
+ require 'geocoder/results/abstract_api'
5
+
6
+ module Geocoder::Lookup
7
+ class AbstractApi < Base
8
+
9
+ def name
10
+ "Abstract API"
11
+ end
12
+
13
+ def required_api_key_parts
14
+ ['api_key']
15
+ end
16
+
17
+ def supported_protocols
18
+ [:https]
19
+ end
20
+
21
+ private # ---------------------------------------------------------------
22
+
23
+ def base_query_url(query)
24
+ "#{protocol}://ipgeolocation.abstractapi.com/v1/?"
25
+ end
26
+
27
+ def query_url_params(query)
28
+ params = {api_key: configuration.api_key}
29
+
30
+ ip_address = query.sanitized_text
31
+ if ip_address.is_a?(String) && ip_address.length > 0
32
+ params[:ip_address] = ip_address
33
+ end
34
+
35
+ params.merge(super)
36
+ end
37
+
38
+ def results(query, reverse = false)
39
+ if doc = fetch_data(query)
40
+ [doc]
41
+ else
42
+ []
43
+ end
44
+ end
45
+ end
46
+ end
@@ -22,7 +22,7 @@ module Geocoder::Lookup
22
22
  end
23
23
 
24
24
  def any_result?(doc)
25
- doc['features'].any?
25
+ doc['features'] and doc['features'].any?
26
26
  end
27
27
 
28
28
  def results(query)
@@ -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
@@ -9,6 +9,10 @@ module Geocoder::Lookup
9
9
  "Esri"
10
10
  end
11
11
 
12
+ def supported_protocols
13
+ [:https]
14
+ end
15
+
12
16
  private # ---------------------------------------------------------------
13
17
 
14
18
  def base_query_url(query)
@@ -47,6 +51,8 @@ module Geocoder::Lookup
47
51
  params[:forStorage] = for_storage_value
48
52
  end
49
53
  params[:sourceCountry] = configuration[:source_country] if configuration[:source_country]
54
+ params[:preferredLabelValues] = configuration[:preferred_label_values] if configuration[:preferred_label_values]
55
+
50
56
  params.merge(super)
51
57
  end
52
58
 
@@ -29,7 +29,7 @@ module Geocoder::Lookup
29
29
 
30
30
  def base_query_url(query)
31
31
  path = query.reverse_geocode? ? "reverse" : "geocode"
32
- "#{protocol}://api.geocod.io/v1.3/#{path}?"
32
+ "#{protocol}://api.geocod.io/v1.6/#{path}?"
33
33
  end
34
34
 
35
35
  def query_url_params(query)
@@ -44,10 +44,15 @@ module Geocoder::Lookup
44
44
  super(response) and ['OK', 'ZERO_RESULTS'].include?(status)
45
45
  end
46
46
 
47
+ def result_root_attr
48
+ 'results'
49
+ end
50
+
47
51
  def results(query)
48
52
  return [] unless doc = fetch_data(query)
49
- case doc['status']; when "OK" # OK status implies >0 results
50
- return doc['results']
53
+ case doc['status']
54
+ when "OK" # OK status implies >0 results
55
+ return doc[result_root_attr]
51
56
  when "OVER_QUERY_LIMIT"
52
57
  raise_error(Geocoder::OverQueryLimitError) ||
53
58
  Geocoder.log(:warn, "#{name} API error: over query limit.")
@@ -22,21 +22,15 @@ module Geocoder
22
22
  "#{protocol}://maps.googleapis.com/maps/api/place/details/json?"
23
23
  end
24
24
 
25
+ def result_root_attr
26
+ 'result'
27
+ end
28
+
25
29
  def results(query)
26
- return [] unless doc = fetch_data(query)
27
-
28
- case doc["status"]
29
- when "OK"
30
- return [doc["result"]]
31
- when "OVER_QUERY_LIMIT"
32
- raise_error(Geocoder::OverQueryLimitError) || Geocoder.log(:warn, "Google Places Details API error: over query limit.")
33
- when "REQUEST_DENIED"
34
- raise_error(Geocoder::RequestDenied) || Geocoder.log(:warn, "Google Places Details API error: request denied.")
35
- when "INVALID_REQUEST"
36
- raise_error(Geocoder::InvalidRequest) || Geocoder.log(:warn, "Google Places Details API error: invalid request.")
37
- end
38
-
39
- []
30
+ result = super(query)
31
+ return [result] unless result.is_a? Array
32
+
33
+ result
40
34
  end
41
35
 
42
36
  def query_url_google_params(query)
@@ -18,16 +18,42 @@ module Geocoder
18
18
 
19
19
  private
20
20
 
21
+ def result_root_attr
22
+ 'candidates'
23
+ end
24
+
21
25
  def base_query_url(query)
22
- "#{protocol}://maps.googleapis.com/maps/api/place/textsearch/json?"
26
+ "#{protocol}://maps.googleapis.com/maps/api/place/findplacefromtext/json?"
23
27
  end
24
28
 
25
29
  def query_url_google_params(query)
26
30
  {
27
- query: query.text,
31
+ input: query.text,
32
+ inputtype: 'textquery',
33
+ fields: fields(query),
28
34
  language: query.language || configuration.language
29
35
  }
30
36
  end
37
+
38
+ def fields(query)
39
+ query_fields = query.options[:fields]
40
+ return format_fields(query_fields) if query_fields
41
+
42
+ default_fields
43
+ end
44
+
45
+ def default_fields
46
+ legacy = %w[id reference]
47
+ basic = %w[business_status formatted_address geometry icon name
48
+ photos place_id plus_code types]
49
+ contact = %w[opening_hours]
50
+ atmosphere = %W[price_level rating user_ratings_total]
51
+ format_fields(legacy, basic, contact, atmosphere)
52
+ end
53
+
54
+ def format_fields(*fields)
55
+ fields.flatten.join(',')
56
+ end
31
57
  end
32
58
  end
33
59
  end