geocoder 1.4.0 → 1.4.1

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of geocoder might be problematic. Click here for more details.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8a859b82bf025e96ae97b006af3874e58766556b
4
- data.tar.gz: 00eb37dfc6a988d08e3d4a2adcb924d0a778d9fa
3
+ metadata.gz: a3067b487565dbc6f761d20315246d3524e350a4
4
+ data.tar.gz: a2e89172c147db3050c203e6507da323e54d8a58
5
5
  SHA512:
6
- metadata.gz: 71456df3a167a0aaa7511c4e61869519d5dd05716d7db7be38801e997525d3d257df5511a772206a7495392b2d65fcc88a5793744cf1360bc1579af83da0e227
7
- data.tar.gz: 95faab5c456a219888ad92ba6cd64c6e27a7bc19cfd729ae2997b9e61849f247acd95f9e6c47f616530fee59d879c23b1496d83fe2d6db735c0552d858b6de6e
6
+ metadata.gz: 811f3224d6926014a1c910b605fd6644078c4808893552b8cedd31987650616323e54ba74564f20cbafbe61b39eb1b347e80912d69ab5c2f84153b4281800408
7
+ data.tar.gz: bc6301d8b24595749190b0d527ffcd8aecc1f8a804b1fc9cacc68bc7c61b92ea8f544940f09306a428653d65a28bc76536a7545cc76a5d3fd144e3a4c12aa86c
@@ -3,6 +3,13 @@ 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.4.1 (2016 Dec 2)
7
+ -------------------
8
+ * Add :location_iq lookup (thanks github.com/aleemuddin13 and glsignal).
9
+ * Add :ban_data_gouv_fr lookup (thanks github.com/JulianNacci).
10
+ * Fix :mapbox results when server returns no context (thanks github.com/jcmuller).
11
+ * Deprecate methods in Geocoder::Calculations: to_kilometers, to_miles, to_nautical_miles, mi_in_km, km_in_mi, km_in_nm, nm_in_km.
12
+
6
13
  1.4.0 (2016 Sep 8)
7
14
  -------------------
8
15
  * Only consider an object geocoded if both lat and lon are present (previously was sufficient to have only one of the two) (thanks github.com/mltsy).
data/README.md CHANGED
@@ -1,9 +1,9 @@
1
1
  Geocoder
2
2
  ========
3
3
 
4
- Geocoder is a complete geocoding solution for Ruby. With Rails it adds geocoding (by street or IP address), reverse geocoding (finding street address based on given coordinates), and distance queries. It's as simple as calling `geocode` on your objects, and then using a scope like `Venue.near("Billings, MT")`.
4
+ Geocoder is a complete geocoding solution for Ruby. With Rails, it adds geocoding (by street or IP address), reverse geocoding (finding street address based on given coordinates), and distance queries. It's as simple as calling `geocode` on your objects, and then using a scope like `Venue.near("Billings, MT")`.
5
5
 
6
- _Please note that this README is for the current `HEAD` and may document features not present in the latest gem release. For this reason, you may want to instead view the README for your particular version._
6
+ _Please note that this README is for the current `HEAD` and may document features not present in the latest gem release. For this reason, you may want to instead view the README for your [particular version](https://github.com/alexreisner/geocoder/releases)._
7
7
 
8
8
 
9
9
  Compatibility
@@ -47,7 +47,7 @@ Your model must have two attributes (database columns) for storing latitude and
47
47
  rails generate migration AddLatitudeAndLongitudeToModel latitude:float longitude:float
48
48
  rake db:migrate
49
49
 
50
- For geocoding your model must provide a method that returns an address. This can be a single attribute, but it can also be a method that returns a string assembled from different attributes (eg: `city`, `state`, and `country`).
50
+ For geocoding, your model must provide a method that returns an address. This can be a single attribute, but it can also be a method that returns a string assembled from different attributes (eg: `city`, `state`, and `country`).
51
51
 
52
52
  Next, your model must tell Geocoder which method returns your object's geocodable address:
53
53
 
@@ -102,7 +102,7 @@ By default, the methods `geocoded_by` and `reverse_geocoded_by` create a geospat
102
102
 
103
103
  ### Bulk Geocoding
104
104
 
105
- If you have just added geocoding to an existing application with a lot of objects you can use this Rake task to geocode them all:
105
+ If you have just added geocoding to an existing application with a lot of objects, you can use this Rake task to geocode them all:
106
106
 
107
107
  rake geocode:all CLASS=YourModel
108
108
 
@@ -244,16 +244,16 @@ If your model has `street`, `city`, `state`, and `country` attributes you might
244
244
  [street, city, state, country].compact.join(', ')
245
245
  end
246
246
 
247
- For reverse geocoding you can also specify an alternate name attribute where the address will be stored, for example:
247
+ For reverse geocoding, you can also specify an alternate name attribute where the address will be stored. For example:
248
248
 
249
249
  reverse_geocoded_by :latitude, :longitude, :address => :location # ActiveRecord
250
250
  reverse_geocoded_by :coordinates, :address => :loc # MongoDB
251
251
 
252
- You can also configure a specific lookup for your model which will override the globally-configured lookup, for example:
252
+ You can also configure a specific lookup for your model which will override the globally-configured lookup. For example:
253
253
 
254
254
  geocoded_by :address, :lookup => :yandex
255
255
 
256
- You can also specify a proc if you want to choose a lookup based on a specific property of an object, for example you can use specialized lookups for different regions:
256
+ You can also specify a proc if you want to choose a lookup based on a specific property of an object. For example, you can use specialized lookups for different regions:
257
257
 
258
258
  geocoded_by :address, :lookup => lambda{ |obj| obj.geocoder_lookup }
259
259
 
@@ -278,7 +278,7 @@ When querying for objects (if you're using ActiveRecord) you can also look withi
278
278
  box = Geocoder::Calculations.bounding_box(center_point, distance)
279
279
  Venue.within_bounding_box(box)
280
280
 
281
- This can also dramatically improve query performance, especially when used in conjunction with indexes on the latitude/longitude columns. Note, however, that returned results do not include `distance` and `bearing` attributes. Note that `#near` performs both bounding box and radius queries for speed.
281
+ This can also dramatically improve query performance, especially when used in conjunction with indexes on the latitude/longitude columns. Note, however, that returned results do not include `distance` and `bearing` attributes. Also note that `#near` performs both bounding box and radius queries for speed.
282
282
 
283
283
  You can also specify a minimum radius (if you're using ActiveRecord and not Sqlite) to constrain the
284
284
  lower bound (ie. think of a donut, or ring) by using the `:min_radius` option:
@@ -293,7 +293,7 @@ With ActiveRecord, you can specify alternate latitude and longitude column names
293
293
  Advanced Geocoding
294
294
  ------------------
295
295
 
296
- So far we have looked at shortcuts for assigning geocoding results to object attributes. However, if you need to do something fancy you can skip the auto-assignment by providing a block (takes the object to be geocoded and an array of `Geocoder::Result` objects) in which you handle the parsed geocoding result any way you like, for example:
296
+ So far we have looked at shortcuts for assigning geocoding results to object attributes. However, if you need to do something fancy, you can skip the auto-assignment by providing a block (takes the object to be geocoded and an array of `Geocoder::Result` objects) in which you handle the parsed geocoding result any way you like, for example:
297
297
 
298
298
  reverse_geocoded_by :latitude, :longitude do |obj,results|
299
299
  if geo = results.first
@@ -355,7 +355,7 @@ Some common configuration options are:
355
355
 
356
356
  )
357
357
 
358
- Please see lib/geocoder/configuration.rb for a complete list of configuration options. Additionally, some lookups have their own configuration options, some of which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter:
358
+ Please see `lib/geocoder/configuration.rb` for a complete list of configuration options. Additionally, some lookups have their own configuration options, some of which are directly supported by Geocoder. For example, to specify a value for Google's `bounds` parameter:
359
359
 
360
360
  # with Google:
361
361
  Geocoder.search("Paris", :bounds => [[32.1,-95.9], [33.9,-94.3]])
@@ -392,7 +392,7 @@ You can also configure multiple geocoding services at once, like this:
392
392
 
393
393
  )
394
394
 
395
- The above combines global and service-specific options and could be useful if you specify different geocoding services for different models or under different conditions. Lookup-specific settings override global settings so, for example, in the above the timeout for all lookups would be 2 seconds, except for Yandex which would be 5.
395
+ The above combines global and service-specific options and could be useful if you specify different geocoding services for different models or under different conditions. Lookup-specific settings override global settings. In the above example, the timeout for all lookups would be 2 seconds, except for Yandex which would be 5.
396
396
 
397
397
 
398
398
  ### Street Address Services
@@ -457,6 +457,17 @@ The [Google Places Details API](https://developers.google.com/places/documentati
457
457
  * **Terms of Service**: http://wiki.openstreetmap.org/wiki/Nominatim_usage_policy
458
458
  * **Limitations**: Please limit request rate to 1 per second and include your contact information in User-Agent headers (eg: `Geocoder.configure(:http_headers => { "User-Agent" => "your contact info" })`). [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
459
459
 
460
+ #### LocationIQ (`:location_iq`)
461
+
462
+ * **API key**: required
463
+ * **Quota**: 6 request/second (30k req/day), then ability to purchase more
464
+ * **Region**: world
465
+ * **SSL support**: yes
466
+ * **Languages**: ?
467
+ * **Documentation**: http://locationiq.org/#docs
468
+ * **Terms of Service**: https://unwiredlabs.com/tos
469
+ * **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://www.openstreetmap.org/copyright)
470
+
460
471
  #### OpenCageData (`:opencagedata`)
461
472
 
462
473
  * **API key**: required
@@ -591,7 +602,7 @@ The [Google Places Details API](https://developers.google.com/places/documentati
591
602
 
592
603
  #### Data Science Toolkit (`:dstk`)
593
604
 
594
- Data Science Toolkit provides an API whose reponse format is like Google's but which can be set up as a privately hosted service.
605
+ Data Science Toolkit provides an API whose response format is like Google's but which can be set up as a privately hosted service.
595
606
 
596
607
  * **API key**: none
597
608
  * **Quota**: None quota if you are self-hosting the service.
@@ -601,7 +612,7 @@ Data Science Toolkit provides an API whose reponse format is like Google's but w
601
612
  * **Documentation**: http://www.datasciencetoolkit.org/developerdocs
602
613
  * **Terms of Service**: http://www.datasciencetoolkit.org/developerdocs#googlestylegeocoder
603
614
  * **Limitations**: No reverse geocoding.
604
- * **Notes**: If you are hosting your own DSTK server you will need to configure the host name, eg: `Geocoder.configure(:lookup => :dstk, :host => "localhost:4567")`.
615
+ * **Notes**: If you are hosting your own DSTK server you will need to configure the host name, eg: `Geocoder.configure(:lookup => :dstk, :dstk => {:host => "localhost:4567"})`.
605
616
 
606
617
  #### Baidu (`:baidu`)
607
618
 
@@ -685,6 +696,16 @@ This uses the PostcodeAnywhere UK Geocode service, this will geocode any string
685
696
  * **Terms of Service**: ?
686
697
  * **Limitations**: No restrictions on use
687
698
 
699
+ #### Base Adresse Nationale FR (`:ban_data_gouv_fr`)
700
+
701
+ * **API key**: none
702
+ * **Quota**: none
703
+ * **Region**: FR
704
+ * **SSL support**: yes
705
+ * **Languages**: en / fr
706
+ * **Documentation**: https://adresse.data.gouv.fr/api/ (in french)
707
+ * **Terms of Service**: https://adresse.data.gouv.fr/faq/ (in french)
708
+ * **Limitations**: [Data licensed under Open Database License (ODbL) (you must provide attribution).](http://openstreetmap.fr/ban)
688
709
 
689
710
  ### IP Address Services
690
711
 
@@ -848,7 +869,7 @@ You must add either the *[hive_geoip2](https://rubygems.org/gems/hive_geoip2)* g
848
869
  Caching
849
870
  -------
850
871
 
851
- It's a good idea, when relying on any external service, to cache retrieved data. When implemented correctly it improves your app's response time and stability. It's easy to cache geocoding results with Geocoder, just configure a cache store:
872
+ When relying on any external service, it's always a good idea to cache retrieved data. When implemented correctly, it improves your app's response time and stability. It's easy to cache geocoding results with Geocoder -- just configure a cache store:
852
873
 
853
874
  Geocoder.configure(:cache => Redis.new)
854
875
 
@@ -875,9 +896,9 @@ If you need to expire cached content:
875
896
  # Be aware that this methods spawns a new Lookup object for each Service
876
897
  Geocoder::Lookup.all_services.each{|service| Geocoder::Lookup.get(service).cache.expire(:all)}
877
898
 
878
- Do *not* include the prefix when passing a URL to be expired. Expiring `:all` will only expire keys with the configured prefix (won't kill every entry in your key/value store).
899
+ Do *not* include the prefix when passing a URL to be expired. Expiring `:all` will only expire keys with the configured prefix -- it will *not* expire every entry in your key/value store.
879
900
 
880
- For an example of a cache store with URL expiry please see examples/autoexpire_cache.rb
901
+ For an example of a cache store with URL expiry, please see examples/autoexpire_cache.rb
881
902
 
882
903
  _Before you implement caching in your app please be sure that doing so does not violate the Terms of Service for your geocoding service._
883
904
 
@@ -885,7 +906,7 @@ _Before you implement caching in your app please be sure that doing so does not
885
906
  Forward and Reverse Geocoding in the Same Model
886
907
  -----------------------------------------------
887
908
 
888
- If you apply both forward and reverse geocoding functionality to the same model (say users can supply an address or coordinates and you want to fill in whatever's missing), you will provide two address methods:
909
+ If you apply both forward and reverse geocoding functionality to the same model (i.e. users can supply an address or coordinates and you want to fill in whatever's missing), you will provide two address methods:
889
910
 
890
911
  * one for storing the fetched address (reverse geocoding)
891
912
  * one for providing an address to use when fetching coordinates (forward geocoding)
@@ -912,7 +933,7 @@ However, there can be only one set of latitude/longitude attributes, and whichev
912
933
  reverse_geocoded_by :latitude, :longitude
913
934
  end
914
935
 
915
- The reason for this is that we don't want ambiguity when doing distance calculations. We need a single, authoritative source for coordinates!
936
+ We don't want ambiguity when doing distance calculations -- we need a single, authoritative source for coordinates!
916
937
 
917
938
  Once both forward and reverse geocoding has been applied, it is possible to call them sequentially.
918
939
 
@@ -924,11 +945,11 @@ For example:
924
945
 
925
946
  end
926
947
 
927
- For certain geolocation services such as Google geolocation API this may cause issues during subsequent updates to database records if the longtitude and latitude coordinates cannot be associated known location address (on a large body of water for example). On subsequent callbacks the following call:
948
+ For certain geolocation services such as Google's geolocation API, this may cause issues during subsequent updates to database records if the longitude and latitude coordinates cannot be associated with a known location address (on a large body of water for example). On subsequent callbacks the following call:
928
949
 
929
950
  after_validation :geocode
930
951
 
931
- will alter the longtitude and latitude attributes based on the location field, which would be the closest known location to the original coordinates. In this case it is better to add conditions to each call, as not to override coordinates that do not have known location addresses associated with them.
952
+ will alter the longitude and latitude attributes based on the location field, which would be the closest known location to the original coordinates. In this case it is better to add conditions to each call, as not to override coordinates that do not have known location addresses associated with them.
932
953
 
933
954
  For example:
934
955
 
@@ -988,8 +1009,10 @@ Now, any time Geocoder looks up "New York, NY" its results array will contain on
988
1009
  ]
989
1010
  )
990
1011
 
991
- Note:
992
- Keys must be strings not symbols when calling `add_stub` or `set_default_stub`. For example `'latitude' =>` not `:latitude =>`.
1012
+ Notes:
1013
+
1014
+ - Keys must be strings not symbols when calling `add_stub` or `set_default_stub`. For example `'latitude' =>` not `:latitude =>`.
1015
+ - To clear stubs (e.g. prior to another spec), use `Geocoder::Lookup::Test.reset`. This will clear all stubs _including the default stub_.
993
1016
 
994
1017
 
995
1018
  Command Line Interface
@@ -1007,7 +1030,7 @@ When you install the Geocoder gem it adds a `geocode` command to your shell. You
1007
1030
  Country: United States
1008
1031
  Google map: http://maps.google.com/maps?q=29.952211,-90.080563
1009
1032
 
1010
- There are also a number of options for setting the geocoding API, key, and language, viewing the raw JSON reponse, and more. Please run `geocode -h` for details.
1033
+ There are also a number of options for setting the geocoding API, key, and language, viewing the raw JSON response, and more. Please run `geocode -h` for details.
1011
1034
 
1012
1035
  Numeric Data Types and Precision
1013
1036
  --------------------------------
@@ -1040,16 +1063,16 @@ For consistency with the rest of Geocoder, always use the `to_coordinates` metho
1040
1063
  Notes on Non-Rails Frameworks
1041
1064
  -----------------------------
1042
1065
 
1043
- If you are using Geocoder with ActiveRecord and a framework other than Rails (like Sinatra or Padrino) you will need to add this in your model before calling Geocoder methods:
1066
+ If you are using Geocoder with ActiveRecord and a framework other than Rails (like Sinatra or Padrino), you will need to add this in your model before calling Geocoder methods:
1044
1067
 
1045
1068
  extend Geocoder::Model::ActiveRecord
1046
1069
 
1047
1070
  Optimisation of Distance Queries
1048
1071
  --------------------------------
1049
1072
 
1050
- In MySQL and Postgres the finding of objects near a given point is speeded up by using a bounding box to limit the number of points over which a full distance calculation needs to be done.
1073
+ In MySQL and Postgres, the finding of objects near a given point is sped up by using a bounding box to limit the number of points over which a full distance calculation needs to be done.
1051
1074
 
1052
- To take advantage of this optimisation you need to add a composite index on latitude and longitude. In your Rails migration:
1075
+ To take advantage of this optimisation, you need to add a composite index on latitude and longitude. In your Rails migration:
1053
1076
 
1054
1077
  add_index :table, [:latitude, :longitude]
1055
1078
 
@@ -1150,7 +1173,7 @@ You can also fetch the response in the console:
1150
1173
  Reporting Issues
1151
1174
  ----------------
1152
1175
 
1153
- 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). Also avoid vague language like "it doesn't work." Please describe as specifically as you can what behavior your are actually seeing (eg: an error message? a nil return value?).
1176
+ 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). Also avoid vague language like "it doesn't work." Please describe as specifically as you can what behavior you are actually seeing (eg: an error message? a nil return value?).
1154
1177
 
1155
1178
  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.
1156
1179
 
@@ -10,12 +10,6 @@ module Geocoder
10
10
  #
11
11
  COMPASS_POINTS = %w[N NE E SE S SW W NW]
12
12
 
13
- ##
14
- # Radius of the Earth, in kilometers.
15
- # Value taken from: http://en.wikipedia.org/wiki/Earth_radius
16
- #
17
- EARTH_RADIUS = 6371.0
18
-
19
13
  ##
20
14
  # Conversion factor: multiply by kilometers to get miles.
21
15
  #
@@ -31,6 +25,16 @@ module Geocoder
31
25
  #
32
26
  DEGREES_PER_RADIAN = 57.2957795
33
27
 
28
+ ##
29
+ # Radius of the Earth, in kilometers.
30
+ # Value taken from: http://en.wikipedia.org/wiki/Earth_radius
31
+ #
32
+ EARTH_RADII = {km: 6371.0}
33
+ EARTH_RADII[:mi] = EARTH_RADII[:km] * KM_IN_MI
34
+ EARTH_RADII[:nm] = EARTH_RADII[:km] * KM_IN_NM
35
+
36
+ EARTH_RADIUS = EARTH_RADII[:km] # TODO: deprecate this constant (use `EARTH_RADII[:km]`)
37
+
34
38
  # Not a number constant
35
39
  NAN = defined?(::Float::NAN) ? ::Float::NAN : 0 / 0.0
36
40
 
@@ -38,19 +42,13 @@ module Geocoder
38
42
  # Returns true if all given arguments are valid latitude/longitude values.
39
43
  #
40
44
  def coordinates_present?(*args)
41
- args.each do |a|
42
- # note that Float::NAN != Float::NAN
43
- # still, this could probably be improved:
44
- return false if (!a.is_a?(Numeric) or a.to_s == "NaN")
45
- end
46
- true
45
+ args.all? { |a| a.is_a? Numeric and !a.to_f.nan? }
47
46
  end
48
47
 
49
48
  ##
50
49
  # Distance spanned by one degree of latitude in the given units.
51
50
  #
52
51
  def latitude_degree_distance(units = nil)
53
- units ||= Geocoder.config.units
54
52
  2 * Math::PI * earth_radius(units) / 360
55
53
  end
56
54
 
@@ -59,7 +57,6 @@ module Geocoder
59
57
  # This ranges from around 69 miles at the equator to zero at the poles.
60
58
  #
61
59
  def longitude_degree_distance(latitude, units = nil)
62
- units ||= Geocoder.config.units
63
60
  latitude_degree_distance(units) * Math.cos(to_radians(latitude))
64
61
  end
65
62
 
@@ -80,10 +77,6 @@ module Geocoder
80
77
  # Use Geocoder.configure(:units => ...) to configure default units.
81
78
  #
82
79
  def distance_between(point1, point2, options = {})
83
-
84
- # set default options
85
- options[:units] ||= Geocoder.config.units
86
-
87
80
  # convert to coordinate arrays
88
81
  point1 = extract_coordinates(point1)
89
82
  point2 = extract_coordinates(point2)
@@ -212,12 +205,11 @@ module Geocoder
212
205
  def bounding_box(point, radius, options = {})
213
206
  lat,lon = extract_coordinates(point)
214
207
  radius = radius.to_f
215
- units = options[:units] || Geocoder.config.units
216
208
  [
217
- lat - (radius / latitude_degree_distance(units)),
218
- lon - (radius / longitude_degree_distance(lat, units)),
219
- lat + (radius / latitude_degree_distance(units)),
220
- lon + (radius / longitude_degree_distance(lat, units))
209
+ lat - (radius / latitude_degree_distance(options[:units])),
210
+ lon - (radius / longitude_degree_distance(lat, options[:units])),
211
+ lat + (radius / latitude_degree_distance(options[:units])),
212
+ lon + (radius / longitude_degree_distance(lat, options[:units]))
221
213
  ]
222
214
  end
223
215
 
@@ -239,10 +231,6 @@ module Geocoder
239
231
  # Use Geocoder.configure(:units => ...) to configure default units.
240
232
  # * <tt>:seed</tt> - The seed for the random number generator
241
233
  def random_point_near(center, radius, options = {})
242
-
243
- # set default options
244
- options[:units] ||= Geocoder.config.units
245
-
246
234
  random = Random.new(options[:seed] || Random.new_seed)
247
235
 
248
236
  # convert to coordinate arrays
@@ -274,7 +262,6 @@ module Geocoder
274
262
  # which returns a [lat,lon] array
275
263
  #
276
264
  def endpoint(start, heading, distance, options = {})
277
- options[:units] ||= Geocoder.config.units
278
265
  radius = earth_radius(options[:units])
279
266
 
280
267
  start = extract_coordinates(start)
@@ -325,12 +312,10 @@ module Geocoder
325
312
  end
326
313
 
327
314
  def distance_to_radians(distance, units = nil)
328
- units ||= Geocoder.config.units
329
315
  distance.to_f / earth_radius(units)
330
316
  end
331
317
 
332
318
  def radians_to_distance(radians, units = nil)
333
- units ||= Geocoder.config.units
334
319
  radians * earth_radius(units)
335
320
  end
336
321
 
@@ -338,6 +323,7 @@ module Geocoder
338
323
  # Convert miles to kilometers.
339
324
  #
340
325
  def to_kilometers(mi)
326
+ Geocoder.log(:warn, "DEPRECATION WARNING: Geocoder::Calculations.to_kilometers is deprecated and will be removed in Geocoder 1.5.0. Please multiply by MI_IN_KM instead.")
341
327
  mi * mi_in_km
342
328
  end
343
329
 
@@ -345,14 +331,16 @@ module Geocoder
345
331
  # Convert kilometers to miles.
346
332
  #
347
333
  def to_miles(km)
348
- km * km_in_mi
334
+ Geocoder.log(:warn, "DEPRECATION WARNING: Geocoder::Calculations.to_miles is deprecated and will be removed in Geocoder 1.5.0. Please multiply by KM_IN_MI instead.")
335
+ km * KM_IN_MI
349
336
  end
350
337
 
351
338
  ##
352
339
  # Convert kilometers to nautical miles.
353
340
  #
354
341
  def to_nautical_miles(km)
355
- km * km_in_nm
342
+ Geocoder.log(:warn, "DEPRECATION WARNING: Geocoder::Calculations.to_nautical_miles is deprecated and will be removed in Geocoder 1.5.0. Please multiply by KM_IN_NM instead.")
343
+ km * KM_IN_NM
356
344
  end
357
345
 
358
346
  ##
@@ -360,18 +348,14 @@ module Geocoder
360
348
  # Use Geocoder.configure(:units => ...) to configure default units.
361
349
  #
362
350
  def earth_radius(units = nil)
363
- units ||= Geocoder.config.units
364
- case units
365
- when :km; EARTH_RADIUS
366
- when :mi; to_miles(EARTH_RADIUS)
367
- when :nm; to_nautical_miles(EARTH_RADIUS)
368
- end
351
+ EARTH_RADII[units || Geocoder.config.units]
369
352
  end
370
353
 
371
354
  ##
372
355
  # Conversion factor: km to mi.
373
356
  #
374
357
  def km_in_mi
358
+ Geocoder.log(:warn, "DEPRECATION WARNING: Geocoder::Calculations.km_in_mi is deprecated and will be removed in Geocoder 1.5.0. Please use the constant KM_IN_MI instead.")
375
359
  KM_IN_MI
376
360
  end
377
361
 
@@ -379,15 +363,15 @@ module Geocoder
379
363
  # Conversion factor: km to nm.
380
364
  #
381
365
  def km_in_nm
366
+ Geocoder.log(:warn, "DEPRECATION WARNING: Geocoder::Calculations.km_in_nm is deprecated and will be removed in Geocoder 1.5.0. Please use the constant KM_IN_NM instead.")
382
367
  KM_IN_NM
383
368
  end
384
369
 
385
-
386
-
387
370
  ##
388
371
  # Conversion factor: mi to km.
389
372
  #
390
373
  def mi_in_km
374
+ Geocoder.log(:warn, "DEPRECATION WARNING: Geocoder::Calculations.mi_in_km is deprecated and will be removed in Geocoder 1.5.0. Please use 1.0 / KM_IN_MI instead.")
391
375
  1.0 / KM_IN_MI
392
376
  end
393
377
 
@@ -395,6 +379,7 @@ module Geocoder
395
379
  # Conversion factor: nm to km.
396
380
  #
397
381
  def nm_in_km
382
+ Geocoder.log(:warn, "DEPRECATION WARNING: Geocoder::Calculations.nm_in_km is deprecated and will be removed in Geocoder 1.5.0. Please use 1.0 / KM_IN_NM instead.")
398
383
  1.0 / KM_IN_NM
399
384
  end
400
385
 
@@ -407,13 +392,8 @@ module Geocoder
407
392
  def extract_coordinates(point)
408
393
  case point
409
394
  when Array
410
- if point.size == 2
411
- lat, lon = point
412
- if !lat.nil? && lat.respond_to?(:to_f) and
413
- !lon.nil? && lon.respond_to?(:to_f)
414
- then
415
- return [ lat.to_f, lon.to_f ]
416
- end
395
+ if point.size == 2 and coordinates_present?(*point)
396
+ return point.map {|coords| coords.to_f}
417
397
  end
418
398
  when String
419
399
  point = Geocoder.coordinates(point) and return point
@@ -428,4 +408,3 @@ module Geocoder
428
408
  end
429
409
  end
430
410
  end
431
-
@@ -23,6 +23,7 @@ module Geocoder
23
23
  #
24
24
  def street_services
25
25
  @street_services ||= [
26
+ :location_iq,
26
27
  :dstk,
27
28
  :esri,
28
29
  :google,
@@ -46,6 +47,7 @@ module Geocoder
46
47
  :okf,
47
48
  :postcode_anywhere_uk,
48
49
  :geoportail_lu,
50
+ :ban_data_gouv_fr,
49
51
  :test,
50
52
  :latlon
51
53
  ]
@@ -0,0 +1,130 @@
1
+ # encoding: utf-8
2
+
3
+ require 'geocoder/lookups/base'
4
+ require 'geocoder/results/ban_data_gouv_fr'
5
+
6
+ module Geocoder::Lookup
7
+ class BanDataGouvFr < Base
8
+
9
+ def name
10
+ "Base Adresse Nationale Française"
11
+ end
12
+
13
+ def map_link_url(coordinates)
14
+ "https://www.openstreetmap.org/#map=19/#{coordinates.join('/')}"
15
+ end
16
+
17
+ def query_url(query)
18
+ method = query.reverse_geocode? ? "reverse" : "search"
19
+ "#{protocol}://api-adresse.data.gouv.fr/#{method}/?" + url_query_string(query)
20
+ end
21
+
22
+ private # ---------------------------------------------------------------
23
+
24
+ def any_result?(doc)
25
+ doc['features'].any?
26
+ end
27
+
28
+ def results(query)
29
+ if doc = fetch_data(query) and any_result?(doc)
30
+ [doc]
31
+ else
32
+ []
33
+ end
34
+ end
35
+
36
+ #### PARAMS ####
37
+
38
+ def query_url_params(query)
39
+ query_ban_datagouv_fr_params(query).merge(super)
40
+ end
41
+
42
+ def query_ban_datagouv_fr_params(query)
43
+ query.reverse_geocode? ? reverse_geocode_ban_fr_params(query) : search_geocode_ban_fr_params(query)
44
+ end
45
+
46
+ #### SEARCH GEOCODING PARAMS ####
47
+ #
48
+ # :q => required, full text search param)
49
+
50
+ # :limit => force limit number of results returned by raw API
51
+ # (default = 5) note : only first result is taken
52
+ # in account in geocoder
53
+ #
54
+ # :autocomplete => pass 0 to disable autocomplete treatment of :q
55
+ # (default = 1)
56
+ #
57
+ # :lat => force filter results around specific lat/lon
58
+ #
59
+ # :lon => force filter results around specific lat/lon
60
+ #
61
+ # :type => force filter the returned result type
62
+ # (check results for a list of accepted types)
63
+ #
64
+ # :postcode => force filter results on a specific city post code
65
+ #
66
+ # :citycode => force filter results on a specific city UUID INSEE code
67
+ #
68
+ # For up to date doc (in french only) : https://adresse.data.gouv.fr/api/
69
+ #
70
+ def search_geocode_ban_fr_params(query)
71
+ params = {
72
+ q: query.sanitized_text
73
+ }
74
+ unless (limit = query.options[:limit]).nil? || !limit_param_is_valid?(limit)
75
+ params[:limit] = limit.to_i
76
+ end
77
+ unless (autocomplete = query.options[:autocomplete]).nil? || !autocomplete_param_is_valid?(autocomplete)
78
+ params[:autocomplete] = autocomplete.to_s
79
+ end
80
+ unless (type = query.options[:type]).nil? || !type_param_is_valid?(type)
81
+ params[:type] = type.downcase
82
+ end
83
+ unless (postcode = query.options[:postcode]).nil? || !code_param_is_valid?(postcode)
84
+ params[:postcode] = postcode.to_s
85
+ end
86
+ unless (citycode = query.options[:citycode]).nil? || !code_param_is_valid?(citycode)
87
+ params[:citycode] = citycode.to_s
88
+ end
89
+ params
90
+ end
91
+
92
+ #### REVERSE GEOCODING PARAMS ####
93
+ #
94
+ # :lat => required
95
+ #
96
+ # :lon => required
97
+ #
98
+ # :type => force returned results type
99
+ # (check results for a list of accepted types)
100
+ #
101
+ def reverse_geocode_ban_fr_params(query)
102
+ lat_lon = query.coordinates
103
+ params = {
104
+ lat: lat_lon.first,
105
+ lon: lat_lon.last
106
+ }
107
+ unless (type = query.options[:type]).nil? || !type_param_is_valid?(type)
108
+ params[:type] = type.downcase
109
+ end
110
+ params
111
+ end
112
+
113
+ def limit_param_is_valid?(param)
114
+ param.to_i.positive?
115
+ end
116
+
117
+ def autocomplete_param_is_valid?(param)
118
+ [0,1].include?(param.to_i)
119
+ end
120
+
121
+ def type_param_is_valid?(param)
122
+ %w(housenumber street locality village town city).include?(param.downcase)
123
+ end
124
+
125
+ def code_param_is_valid?(param)
126
+ (1..99999).include?(param.to_i)
127
+ end
128
+
129
+ end
130
+ end
@@ -0,0 +1,32 @@
1
+ require 'geocoder/lookups/nominatim'
2
+ require "geocoder/results/location_iq"
3
+
4
+ module Geocoder::Lookup
5
+ class LocationIq < Nominatim
6
+ def name
7
+ "LocationIq"
8
+ end
9
+
10
+ def required_api_key_parts
11
+ ["api_key"]
12
+ end
13
+
14
+ def query_url(query)
15
+ method = query.reverse_geocode? ? "reverse.php" : "search.php"
16
+ host = configuration[:host] || "locationiq.org/v1"
17
+ "#{protocol}://#{host}/#{method}?key=#{configuration.api_key}&" + url_query_string(query)
18
+ end
19
+
20
+ private
21
+
22
+ def results(query)
23
+ return [] unless doc = fetch_data(query)
24
+
25
+ if !doc.is_a?(Array) && doc['error'] =~ /Invalid\skey/
26
+ raise_error(Geocoder::InvalidApiKey, doc['error'])
27
+ end
28
+
29
+ doc.is_a?(Array) ? doc : [doc]
30
+ end
31
+ end
32
+ end
@@ -47,6 +47,12 @@ module Geocoder::Lookup
47
47
  :language => (query.language || configuration.language)
48
48
  }.merge(super)
49
49
 
50
+ [:countrycode, :min_confidence, :no_dedupe, :no_annotations, :no_record, :limit].each do |option|
51
+ unless (option_value = query.options[option]).nil?
52
+ params[option] = option_value
53
+ end
54
+ end
55
+
50
56
  unless (bounds = query.options[:bounds]).nil?
51
57
  params[:bounds] = bounds.map{ |point| "%f,%f" % point }.join(',')
52
58
  end
@@ -0,0 +1,257 @@
1
+ # encoding: utf-8
2
+ require 'geocoder/results/base'
3
+
4
+ module Geocoder::Result
5
+ class BanDataGouvFr < Base
6
+
7
+ #### BASE METHODS ####
8
+
9
+ def self.response_attributes
10
+ %w[limit attribution version licence type features]
11
+ end
12
+
13
+ response_attributes.each do |a|
14
+ unless method_defined?(a)
15
+ define_method a do
16
+ @data[a]
17
+ end
18
+ end
19
+ end
20
+
21
+ #### BEST RESULT ####
22
+
23
+ def result
24
+ features[0] if features.any?
25
+ end
26
+
27
+ #### GEOMETRY ####
28
+
29
+ def geometry
30
+ result['geometry'] if result
31
+ end
32
+
33
+ def precision
34
+ geometry['type'] if geometry
35
+ end
36
+
37
+ def coordinates
38
+ coords = geometry["coordinates"]
39
+ return [coords[1].to_f, coords[0].to_f]
40
+ end
41
+
42
+ #### PROPERTIES ####
43
+
44
+ # List of raw attrbutes returned by BAN data gouv fr API:
45
+ #
46
+ # :id => [string] UUID of the result, said to be not stable
47
+ # atm, based on IGN reference (Institut national de
48
+ # l'information géographique et forestière)
49
+ #
50
+ # :type => [string] result type (housenumber, street, city,
51
+ # town, village, locality)
52
+ #
53
+ # :score => [float] value between 0 and 1 giving result's
54
+ # relevancy
55
+ #
56
+ # :housenumber => [string] street number and extra information
57
+ # (bis, ter, A, B)
58
+ #
59
+ # :street => [string] street name
60
+ #
61
+ # :name => [string] housenumber and street name
62
+ #
63
+ # :postcode => [string] city post code (used for mails by La Poste,
64
+ # beware many cities got severeal postcodes)
65
+ #
66
+ # :citycode => [string] city code (INSEE reference,
67
+ # consider it as a french institutional UUID)
68
+ #
69
+ # :city => [string] city name
70
+ #
71
+ # :context => [string] department code, department name and
72
+ # region code
73
+ #
74
+ # :label => [string] full address without state, country name
75
+ # and country code
76
+ #
77
+ # CITIES ONLY PROPERTIES
78
+ #
79
+ # :adm_weight => [string] administrative weight (importance) of
80
+ # the city
81
+ #
82
+ # :population => [float] number of inhabitants with a 1000 factor
83
+ #
84
+ # For up to date doc (in french only) : https://adresse.data.gouv.fr/api/
85
+ #
86
+ def properties
87
+ result['properties'] if result
88
+ end
89
+
90
+ # List of usable Geocoder results' methods
91
+ #
92
+ # score => [float] result relevance 0 to 1
93
+ #
94
+ # location_id => [string] location's IGN UUID
95
+ #
96
+ # result_type => [string] housenumber / street / city
97
+ # / town / village / locality
98
+ #
99
+ # international_address => [string] full address with country code
100
+ #
101
+ # national_address => [string] full address with country code
102
+ #
103
+ # street_address => [string] housenumber + extra inf
104
+ # + street name
105
+ #
106
+ # street_number => [string] housenumber + extra inf
107
+ # (bis, ter, etc)
108
+ #
109
+ # street_name => [string] street's name
110
+ #
111
+ # city_name => [string] city's name
112
+ #
113
+ # city_code => [string] city's INSEE UUID
114
+ #
115
+ # postal_code => [string] city's postal code (used for mails)
116
+ #
117
+ # context => [string] city's department code, department
118
+ # name and region name
119
+ #
120
+ # demartment_name => [string] city's department name
121
+ #
122
+ # department_code => [string] city's department INSEE UUID
123
+ #
124
+ # region_name => [string] city's region name
125
+ #
126
+ # population => [string] city's inhabitants count
127
+ #
128
+ # administrative_weight => [integer] city's importance on a scale
129
+ # from 6 (capital city) to 1 (regular village)
130
+ #
131
+ def score
132
+ properties['score']
133
+ end
134
+
135
+ def location_id
136
+ properties['id']
137
+ end
138
+
139
+ # Types
140
+ #
141
+ # housenumber
142
+ # street
143
+ # city
144
+ # town
145
+ # village
146
+ # locality
147
+ #
148
+ def result_type
149
+ properties['type']
150
+ end
151
+
152
+ def international_address
153
+ "#{national_address}, #{country}"
154
+ end
155
+
156
+ def national_address
157
+ properties['label']
158
+ end
159
+
160
+ def street_address
161
+ properties['name']
162
+ end
163
+
164
+ def street_number
165
+ properties['housenumber']
166
+ end
167
+
168
+ def street_name
169
+ properties['street']
170
+ end
171
+
172
+ def city_name
173
+ properties['city']
174
+ end
175
+
176
+ def city_code
177
+ properties['citycode']
178
+ end
179
+
180
+ def postal_code
181
+ properties['postcode']
182
+ end
183
+
184
+ def context
185
+ properties['context'].split(/,/).map(&:strip)
186
+ end
187
+
188
+ def department_code
189
+ context[0] if context.length > 0
190
+ end
191
+
192
+ # Monkey logic to handle fact Paris is both a city and a department
193
+ # in Île-de-France region
194
+ def department_name
195
+ if context.length > 1
196
+ if context[1] == "Île-de-France"
197
+ "Paris"
198
+ else
199
+ context[1]
200
+ end
201
+ end
202
+ end
203
+
204
+ def region_name
205
+ if context.length == 2 && context[1] == "Île-de-France"
206
+ context[1]
207
+ elsif context.length > 2
208
+ context[2]
209
+ end
210
+ end
211
+
212
+ def country
213
+ "France"
214
+ end
215
+
216
+ # Country code types
217
+ # FR : France
218
+ # GF : Guyane Française
219
+ # RE : Réunion
220
+ # NC : Nouvelle-Calédonie
221
+ # GP : Guadeloupe
222
+ # MQ : Martinique
223
+ # MU : Maurice
224
+ # PF : Polynésie française
225
+ #
226
+ # Will need refacto to handle different country codes, but BAN API
227
+ # is currently mainly designed for geocode FR country code addresses
228
+ def country_code
229
+ "FR"
230
+ end
231
+
232
+ #### ALIAS METHODS ####
233
+
234
+ alias_method :address, :international_address
235
+ alias_method :street, :street_name
236
+ alias_method :city, :city_name
237
+ alias_method :state, :region_name
238
+ alias_method :state_code, :state
239
+
240
+ #### CITIES' METHODS ####
241
+
242
+ def population
243
+ (properties['population'].to_f * 1000).to_i if city?(result_type)
244
+ end
245
+
246
+ def administrative_weight
247
+ properties['adm_weight'].to_i if city?(result_type)
248
+ end
249
+
250
+ private
251
+
252
+ def city?(result_type)
253
+ %w(village town city).include?(result_type)
254
+ end
255
+
256
+ end
257
+ end
@@ -30,6 +30,10 @@ module Geocoder
30
30
  def website
31
31
  @data["website"]
32
32
  end
33
+
34
+ def photos
35
+ @data["photos"]
36
+ end
33
37
  end
34
38
  end
35
39
  end
@@ -0,0 +1,6 @@
1
+ require 'geocoder/results/nominatim'
2
+
3
+ module Geocoder::Result
4
+ class LocationIq < Nominatim
5
+ end
6
+ end
@@ -4,43 +4,53 @@ module Geocoder::Result
4
4
  class Mapbox < Base
5
5
 
6
6
  def coordinates
7
- @data["geometry"]["coordinates"].reverse.map(&:to_f)
7
+ data['geometry']['coordinates'].reverse.map(&:to_f)
8
8
  end
9
9
 
10
10
  def place_name
11
- @data['text']
11
+ data['text']
12
12
  end
13
13
 
14
14
  def street
15
- @data['properties']['address']
15
+ data['properties']['address']
16
16
  end
17
17
 
18
18
  def city
19
- @data['context'].map { |c| c['text'] if c['id'] =~ /place/ }.compact.first
19
+ context_part('place')
20
20
  end
21
21
 
22
22
  def state
23
- @data['context'].map { |c| c['text'] if c['id'] =~ /region/ }.compact.first
23
+ context_part('region')
24
24
  end
25
25
 
26
26
  alias_method :state_code, :state
27
27
 
28
28
  def postal_code
29
- @data['context'].map { |c| c['text'] if c['id'] =~ /postcode/ }.compact.first
29
+ context_part('postcode')
30
30
  end
31
31
 
32
32
  def country
33
- @data['context'].map { |c| c['text'] if c['id'] =~ /country/ }.compact.first
33
+ context_part('country')
34
34
  end
35
35
 
36
36
  alias_method :country_code, :country
37
37
 
38
38
  def neighborhood
39
- @data['context'].map { |c| c['text'] if c['id'] =~ /neighborhood/ }.compact.first
39
+ context_part('neighborhood')
40
40
  end
41
41
 
42
42
  def address
43
- [place_name, street, city, state, postal_code, country].compact.join(", ")
43
+ [place_name, street, city, state, postal_code, country].compact.join(', ')
44
+ end
45
+
46
+ private
47
+
48
+ def context_part(name)
49
+ context.map { |c| c['text'] if c['id'] =~ Regexp.new(name) }.compact.first
50
+ end
51
+
52
+ def context
53
+ Array(data['context'])
44
54
  end
45
55
  end
46
56
  end
@@ -1,3 +1,3 @@
1
1
  module Geocoder
2
- VERSION = "1.4.0"
2
+ VERSION = "1.4.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: geocoder
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.0
4
+ version: 1.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Reisner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-08 00:00:00.000000000 Z
11
+ date: 2016-12-02 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Provides object geocoding (by street or IP address), reverse geocoding
14
14
  (coordinates to street address), distance queries for ActiveRecord and Mongoid,
@@ -49,6 +49,7 @@ files:
49
49
  - lib/geocoder/lookup.rb
50
50
  - lib/geocoder/lookups/baidu.rb
51
51
  - lib/geocoder/lookups/baidu_ip.rb
52
+ - lib/geocoder/lookups/ban_data_gouv_fr.rb
52
53
  - lib/geocoder/lookups/base.rb
53
54
  - lib/geocoder/lookups/bing.rb
54
55
  - lib/geocoder/lookups/dstk.rb
@@ -66,6 +67,7 @@ files:
66
67
  - lib/geocoder/lookups/ipapi_com.rb
67
68
  - lib/geocoder/lookups/ipinfo_io.rb
68
69
  - lib/geocoder/lookups/latlon.rb
70
+ - lib/geocoder/lookups/location_iq.rb
69
71
  - lib/geocoder/lookups/mapbox.rb
70
72
  - lib/geocoder/lookups/mapquest.rb
71
73
  - lib/geocoder/lookups/mapzen.rb
@@ -93,6 +95,7 @@ files:
93
95
  - lib/geocoder/request.rb
94
96
  - lib/geocoder/results/baidu.rb
95
97
  - lib/geocoder/results/baidu_ip.rb
98
+ - lib/geocoder/results/ban_data_gouv_fr.rb
96
99
  - lib/geocoder/results/base.rb
97
100
  - lib/geocoder/results/bing.rb
98
101
  - lib/geocoder/results/dstk.rb
@@ -110,6 +113,7 @@ files:
110
113
  - lib/geocoder/results/ipapi_com.rb
111
114
  - lib/geocoder/results/ipinfo_io.rb
112
115
  - lib/geocoder/results/latlon.rb
116
+ - lib/geocoder/results/location_iq.rb
113
117
  - lib/geocoder/results/mapbox.rb
114
118
  - lib/geocoder/results/mapquest.rb
115
119
  - lib/geocoder/results/mapzen.rb