geocoder 1.1.2 → 1.1.3
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.
- data/.travis.yml +19 -0
- data/CHANGELOG.rdoc +13 -0
- data/README.rdoc +59 -6
- data/gemfiles/Gemfile.mongoid-2.4.x +15 -0
- data/lib/generators/geocoder/config/templates/initializer.rb +3 -3
- data/lib/geocoder.rb +1 -1
- data/lib/geocoder/calculations.rb +12 -0
- data/lib/geocoder/configuration.rb +1 -0
- data/lib/geocoder/exceptions.rb +7 -0
- data/lib/geocoder/lookups/base.rb +3 -1
- data/lib/geocoder/lookups/google.rb +4 -2
- data/lib/geocoder/lookups/mapquest.rb +33 -0
- data/lib/geocoder/lookups/test.rb +32 -0
- data/lib/geocoder/models/mongoid.rb +9 -2
- data/lib/geocoder/results/mapquest.rb +66 -0
- data/lib/geocoder/results/nominatim.rb +20 -4
- data/lib/geocoder/results/test.rb +15 -0
- data/lib/geocoder/results/yandex.rb +4 -0
- data/lib/geocoder/stores/active_record.rb +10 -8
- data/lib/geocoder/version.rb +1 -1
- data/test/calculations_test.rb +12 -6
- data/test/error_handling_test.rb +3 -3
- data/test/fixtures/mapquest_madison_square_garden.json +27 -0
- data/test/fixtures/mapquest_no_results.json +1 -0
- data/test/lookup_test.rb +1 -1
- data/test/mongoid_test.rb +2 -1
- data/test/mongoid_test_helper.rb +6 -2
- data/test/result_test.rb +1 -1
- data/test/test_helper.rb +23 -0
- data/test/test_mode_test.rb +51 -0
- metadata +38 -28
data/.travis.yml
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
rvm:
|
2
|
+
- 1.8.7
|
3
|
+
- 1.9.2
|
4
|
+
- 1.9.3
|
5
|
+
gemfile:
|
6
|
+
- Gemfile
|
7
|
+
- gemfiles/Gemfile.mongoid-2.4.x
|
8
|
+
env: SSL_CERT_DIR=/etc/ssl/certs
|
9
|
+
matrix:
|
10
|
+
exclude:
|
11
|
+
- rvm: 1.8.7
|
12
|
+
gemfile: Gemfile
|
13
|
+
env: SSL_CERT_DIR=/etc/ssl/certs
|
14
|
+
- rvm: 1.9.2
|
15
|
+
gemfile: Gemfile
|
16
|
+
env: SSL_CERT_DIR=/etc/ssl/certs
|
17
|
+
- rvm: 1.9.3
|
18
|
+
gemfile: gemfiles/Gemfile.mongoid-2.4.x
|
19
|
+
env: SSL_CERT_DIR=/etc/ssl/certs
|
data/CHANGELOG.rdoc
CHANGED
@@ -2,6 +2,19 @@
|
|
2
2
|
|
3
3
|
Per-release changes to Geocoder.
|
4
4
|
|
5
|
+
== 1.1.3 (2012 Aug 26)
|
6
|
+
|
7
|
+
* Add support for Mapquest geocoding service (thanks github.com/razorinc).
|
8
|
+
* Add :test lookup for easy testing of apps using Geocoder (thanks github.com/mguterl).
|
9
|
+
* Add #precision method to Yandex results (thanks github.com/gemaker).
|
10
|
+
* Add support for raising :all exceptions (thanks github.com/andyvb).
|
11
|
+
* Add exceptions for certain Google geocoder responses (thanks github.com/andyvb).
|
12
|
+
* Add Travis-CI integration (thanks github.com/petergoldstein).
|
13
|
+
* Fix: unit config was not working with SQLite (thanks github.com/balvig).
|
14
|
+
* Fix: get tests to pass under Jruby (thanks github.com/petergoldstein).
|
15
|
+
* Fix: bug in distance_from_sql method (error occurred when coordinates not found).
|
16
|
+
* Fix: incompatibility with Mongoid 3.0.x (thanks github.com/petergoldstein).
|
17
|
+
|
5
18
|
== 1.1.2 (2012 May 24)
|
6
19
|
|
7
20
|
* Add ability to specify default units and distance calculation method (thanks github.com/abravalheri).
|
data/README.rdoc
CHANGED
@@ -201,6 +201,20 @@ For reverse geocoding you can also specify an alternate name attribute where the
|
|
201
201
|
reverse_geocoded_by :coordinates, :address => :loc # MongoDB
|
202
202
|
|
203
203
|
|
204
|
+
== Advanced Querying
|
205
|
+
|
206
|
+
When querying for objects (if you're using ActiveRecord) you can also look within a square rather than a radius (circle) by using the <tt>within_bounding_box</tt> scope:
|
207
|
+
|
208
|
+
distance = 20
|
209
|
+
center_point = [40.71, 100.23]
|
210
|
+
box = Geocoder::Calculations.bounding_box(center_point, distance)
|
211
|
+
Venue.within_bounding_box(box, distance)
|
212
|
+
|
213
|
+
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. If you want to improve performance AND have access to distance and bearing info, use both scopes:
|
214
|
+
|
215
|
+
Venue.near(center_point, distance).within_bounding_box(box, distance)
|
216
|
+
|
217
|
+
|
204
218
|
== Advanced Geocoding
|
205
219
|
|
206
220
|
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 <tt>Geocoder::Result</tt> objects) in which you handle the parsed geocoding result any way you like, for example:
|
@@ -264,7 +278,7 @@ The following is a comparison of the supported geocoding APIs. The "Limitations"
|
|
264
278
|
|
265
279
|
==== Google (<tt>:google</tt>)
|
266
280
|
|
267
|
-
API key::
|
281
|
+
API key:: required for Premier (do NOT use a key for the free version)
|
268
282
|
Key signup:: http://code.google.com/apis/maps/signup.html
|
269
283
|
Quota:: 2,500 requests/day, 100,000 with Google Maps API Premier
|
270
284
|
Region:: world
|
@@ -312,9 +326,8 @@ Limitations:: Please limit request rate to 1 per second and include your contact
|
|
312
326
|
|
313
327
|
==== Yandex (<tt>:yandex</tt>)
|
314
328
|
|
315
|
-
API key::
|
316
|
-
|
317
|
-
Quota:: ?
|
329
|
+
API key:: none
|
330
|
+
Quota:: 25000 requests / day
|
318
331
|
Region:: Russia
|
319
332
|
SSL support:: no
|
320
333
|
Languages:: Russian, Belarusian, and Ukrainian
|
@@ -333,13 +346,24 @@ Documentation:: ?
|
|
333
346
|
Terms of Service:: http://geocoder.ca/?terms=1
|
334
347
|
Limitations:: "Under no circumstances can our data be re-distributed or re-sold by anyone to other parties without our written permission."
|
335
348
|
|
336
|
-
====
|
349
|
+
==== Mapquest (<tt>:mapquest</tt>)
|
337
350
|
|
338
351
|
API key:: none
|
339
352
|
Quota:: ?
|
340
353
|
Region:: world
|
341
354
|
SSL support:: no
|
342
355
|
Languages:: English
|
356
|
+
Documentation:: http://www.mapquestapi.com/geocoding/
|
357
|
+
Terms of Service:: http://info.mapquest.com/terms-of-use/
|
358
|
+
Limitations:: ?
|
359
|
+
|
360
|
+
==== FreeGeoIP
|
361
|
+
|
362
|
+
API key:: none
|
363
|
+
Quota:: 1000 requests per hour. After reaching the hourly quota, all of your requests will result in HTTP 403 (Forbidden) until it clears up on the next roll over.
|
364
|
+
Region:: world
|
365
|
+
SSL support:: no
|
366
|
+
Languages:: English
|
343
367
|
Documentation:: http://github.com/fiorix/freegeoip/blob/master/README.rst
|
344
368
|
Terms of Service:: ?
|
345
369
|
Limitations:: ?
|
@@ -416,6 +440,29 @@ You can use Geocoder outside of Rails by calling the <tt>Geocoder.search</tt> me
|
|
416
440
|
This returns an array of <tt>Geocoder::Result</tt> objects with all information provided by the geocoding service. Please see above and in the code for details.
|
417
441
|
|
418
442
|
|
443
|
+
== Testing Apps that Use Geocoder
|
444
|
+
|
445
|
+
When writing tests for an app that uses Geocoder it may be useful to avoid network calls and have Geocoder return consistent, configurable results. To do this, configure and use the <tt>:test</tt> lookup. For example:
|
446
|
+
|
447
|
+
Geocoder::Configuration.lookup = :test
|
448
|
+
|
449
|
+
Geocoder::Lookup::Test.add_stub(
|
450
|
+
"New York, NY", [
|
451
|
+
{
|
452
|
+
'latitude' => 40.7143528,
|
453
|
+
'longitude' => -74.0059731,
|
454
|
+
'address' => 'New York, NY, USA',
|
455
|
+
'state' => 'New York',
|
456
|
+
'state_code' => 'NY',
|
457
|
+
'country' => 'United States',
|
458
|
+
'country_code' => 'US'
|
459
|
+
}
|
460
|
+
]
|
461
|
+
)
|
462
|
+
|
463
|
+
Now, any time Geocoder looks up "New York, NY" its results array will contain one result with the above attributes.
|
464
|
+
|
465
|
+
|
419
466
|
== Command Line Interface
|
420
467
|
|
421
468
|
When you install the Geocoder gem it adds a +geocode+ command to your shell. You can search for a street address, IP address, postal code, coordinates, etc just like you can with the Geocoder.search method for example:
|
@@ -441,7 +488,7 @@ Mongo document classes (Mongoid and MongoMapper) have a built-in +near+ scope, b
|
|
441
488
|
|
442
489
|
=== Latitude/Longitude Order
|
443
490
|
|
444
|
-
Coordinates are generally printed and spoken as latitude, then
|
491
|
+
Coordinates are generally printed and spoken as latitude, then longitude ([lat,lon]). Geocoder respects this convention and always expects method arguments to be given in [lat,lon] order. However, MongoDB requires that coordinates be stored in [lon,lat] order as per the GeoJSON spec (http://geojson.org/geojson-spec.html#positions), so internally they are stored "backwards." However, this does not affect order of arguments to methods when using Mongoid or MongoMapper.
|
445
492
|
|
446
493
|
To access an object's coordinates in the conventional order, use the <tt>to_coordinates</tt> instance method provided by Geocoder. For example:
|
447
494
|
|
@@ -485,6 +532,12 @@ By default Geocoder will rescue any exceptions raised by calls to the geocoding
|
|
485
532
|
|
486
533
|
Geocoder::Configuration.always_raise = [SocketError, TimeoutError]
|
487
534
|
|
535
|
+
You can also do this to raise all exceptions:
|
536
|
+
|
537
|
+
Geocoder::Configuration.always_raise = :all
|
538
|
+
|
539
|
+
See <tt>lib/geocoder/exceptions.rb</tt> for a list of raise-able exceptions.
|
540
|
+
|
488
541
|
|
489
542
|
== Known Issue
|
490
543
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
Geocoder.configure do
|
1
|
+
Geocoder.configure do |config|
|
2
2
|
## Configurable parameters: if you wish to change some configurable
|
3
3
|
## behaviour in Geocoder, feel free to uncomment the following lines
|
4
4
|
## and provide custom parameters.
|
@@ -19,7 +19,7 @@ Geocoder.configure do
|
|
19
19
|
# config.always_raise = []
|
20
20
|
|
21
21
|
## Calculation options
|
22
|
-
# config.units
|
23
|
-
# config.
|
22
|
+
# config.units = :mi # :km for kilometers or :mi for miles
|
23
|
+
# config.distances = :linear # :spherical or :linear
|
24
24
|
end
|
25
25
|
|
data/lib/geocoder.rb
CHANGED
@@ -57,7 +57,7 @@ module Geocoder
|
|
57
57
|
# All street address lookups, default first.
|
58
58
|
#
|
59
59
|
def street_lookups
|
60
|
-
[:google, :google_premier, :yahoo, :bing, :geocoder_ca, :yandex, :nominatim]
|
60
|
+
[:google, :google_premier, :yahoo, :bing, :geocoder_ca, :yandex, :nominatim, :mapquest, :test]
|
61
61
|
end
|
62
62
|
|
63
63
|
##
|
@@ -24,6 +24,18 @@ module Geocoder
|
|
24
24
|
# Not a number constant
|
25
25
|
NAN = defined?(::Float::NAN) ? ::Float::NAN : 0 / 0.0
|
26
26
|
|
27
|
+
##
|
28
|
+
# Returns true if all given arguments are valid latitude/longitude values.
|
29
|
+
#
|
30
|
+
def coordinates_present?(*args)
|
31
|
+
args.each do |a|
|
32
|
+
# note that Float::NAN != Float::NAN
|
33
|
+
# still, this could probably be improved:
|
34
|
+
return false if (!a.is_a?(Numeric) or a.to_s == "NaN")
|
35
|
+
end
|
36
|
+
true
|
37
|
+
end
|
38
|
+
|
27
39
|
##
|
28
40
|
# Distance spanned by one degree of latitude in the given units.
|
29
41
|
#
|
data/lib/geocoder/exceptions.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'net/http'
|
2
|
+
require 'net/https'
|
2
3
|
require 'uri'
|
3
4
|
|
4
5
|
unless defined?(ActiveSupport::JSON)
|
@@ -99,7 +100,8 @@ module Geocoder
|
|
99
100
|
# Return false if exception not raised.
|
100
101
|
#
|
101
102
|
def raise_error(error, message = nil)
|
102
|
-
|
103
|
+
exceptions = Geocoder::Configuration.always_raise
|
104
|
+
if exceptions == :all or exceptions.include?( error.is_a?(Class) ? error : error.class )
|
103
105
|
raise error, message
|
104
106
|
else
|
105
107
|
false
|
@@ -18,9 +18,11 @@ module Geocoder::Lookup
|
|
18
18
|
raise_error(Geocoder::OverQueryLimitError) ||
|
19
19
|
warn("Google Geocoding API error: over query limit.")
|
20
20
|
when "REQUEST_DENIED"
|
21
|
-
|
21
|
+
raise_error(Geocoder::RequestDenied) ||
|
22
|
+
warn("Google Geocoding API error: request denied.")
|
22
23
|
when "INVALID_REQUEST"
|
23
|
-
|
24
|
+
raise_error(Geocoder::InvalidRequest) ||
|
25
|
+
warn("Google Geocoding API error: invalid request.")
|
24
26
|
end
|
25
27
|
return []
|
26
28
|
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require "geocoder/results/mapquest"
|
3
|
+
|
4
|
+
module Geocoder::Lookup
|
5
|
+
class Mapquest < Base
|
6
|
+
|
7
|
+
private # ---------------------------------------------------------------
|
8
|
+
|
9
|
+
def results(query, reverse = false)
|
10
|
+
return [] unless doc = fetch_data(query, reverse)
|
11
|
+
doc.is_a?(Array) ? doc : [doc]
|
12
|
+
end
|
13
|
+
|
14
|
+
def query_url(query, reverse = false)
|
15
|
+
params = {
|
16
|
+
:format => "json",
|
17
|
+
:polygon => "1",
|
18
|
+
:addressdetails => "1",
|
19
|
+
:"accept-language" => Geocoder::Configuration.language
|
20
|
+
}
|
21
|
+
if (reverse)
|
22
|
+
method = 'reverse'
|
23
|
+
parts = query.split(/\s*,\s*/);
|
24
|
+
params[:lat] = parts[0]
|
25
|
+
params[:lon] = parts[1]
|
26
|
+
else
|
27
|
+
method = 'search'
|
28
|
+
params[:q] = query
|
29
|
+
end
|
30
|
+
"http://open.mapquestapi.com/#{method}?" + hash_to_query(params)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'geocoder/lookups/base'
|
2
|
+
require 'geocoder/results/test'
|
3
|
+
|
4
|
+
module Geocoder
|
5
|
+
module Lookup
|
6
|
+
class Test < Base
|
7
|
+
|
8
|
+
def self.add_stub(query, results)
|
9
|
+
stubs[query] = results
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.read_stub(query)
|
13
|
+
stubs.fetch(query) { raise ArgumentError, "unknown stub request #{query}" }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.stubs
|
17
|
+
@stubs ||= {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.reset
|
21
|
+
@stubs = {}
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def results(query, reverse = false)
|
27
|
+
Geocoder::Lookup::Test.read_stub(query)
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'mongoid/version'
|
1
2
|
require 'geocoder/models/base'
|
2
3
|
require 'geocoder/models/mongo_base'
|
3
4
|
|
@@ -17,8 +18,14 @@ module Geocoder
|
|
17
18
|
def geocoder_init(options)
|
18
19
|
super(options)
|
19
20
|
if options[:skip_index] == false
|
20
|
-
|
21
|
-
|
21
|
+
# create 2d index
|
22
|
+
if (::Mongoid::VERSION >= "3")
|
23
|
+
index({ geocoder_options[:coordinates].to_sym => '2d' },
|
24
|
+
{:min => -180, :max => 180})
|
25
|
+
else
|
26
|
+
index [[ geocoder_options[:coordinates], '2d' ]],
|
27
|
+
:min => -180, :max => 180
|
28
|
+
end
|
22
29
|
end
|
23
30
|
end
|
24
31
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder::Result
|
4
|
+
class Mapquest < Base
|
5
|
+
|
6
|
+
def house_number
|
7
|
+
@data['address']['house_number']
|
8
|
+
end
|
9
|
+
|
10
|
+
def address
|
11
|
+
@data['display_name']
|
12
|
+
end
|
13
|
+
|
14
|
+
def street
|
15
|
+
@data['address']['road']
|
16
|
+
end
|
17
|
+
|
18
|
+
def city
|
19
|
+
@data['address']['city']
|
20
|
+
end
|
21
|
+
|
22
|
+
def village
|
23
|
+
@data['address']['villiage']
|
24
|
+
end
|
25
|
+
|
26
|
+
def town
|
27
|
+
@data['address']['town']
|
28
|
+
end
|
29
|
+
|
30
|
+
def state
|
31
|
+
@data['address']['state']
|
32
|
+
end
|
33
|
+
|
34
|
+
alias_method :state_code, :state
|
35
|
+
|
36
|
+
def postal_code
|
37
|
+
@data['address']['postcode']
|
38
|
+
end
|
39
|
+
|
40
|
+
def county
|
41
|
+
@data['address']['county']
|
42
|
+
end
|
43
|
+
|
44
|
+
def country
|
45
|
+
@data['address']['country']
|
46
|
+
end
|
47
|
+
|
48
|
+
def country_code
|
49
|
+
@data['address']['country_code']
|
50
|
+
end
|
51
|
+
|
52
|
+
def coordinates
|
53
|
+
[@data['lat'].to_f, @data['lon'].to_f]
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.response_attributes
|
57
|
+
%w[place_id boundingbox license polygonpoints display_name class type stadium suburb]
|
58
|
+
end
|
59
|
+
|
60
|
+
response_attributes.each do |a|
|
61
|
+
define_method a do
|
62
|
+
@data[a]
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -3,6 +3,12 @@ require 'geocoder/results/base'
|
|
3
3
|
module Geocoder::Result
|
4
4
|
class Nominatim < Base
|
5
5
|
|
6
|
+
def poi
|
7
|
+
%w[stadium bus_stop tram_stop].each do |key|
|
8
|
+
@data['address'][key] if @data['address'].key?(key)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
6
12
|
def house_number
|
7
13
|
@data['address']['house_number']
|
8
14
|
end
|
@@ -12,11 +18,17 @@ module Geocoder::Result
|
|
12
18
|
end
|
13
19
|
|
14
20
|
def street
|
15
|
-
|
21
|
+
%w[road pedestrian highway].each do |key|
|
22
|
+
return @data['address'][key] if @data['address'].key?(key)
|
23
|
+
end
|
24
|
+
return nil
|
16
25
|
end
|
17
26
|
|
18
27
|
def city
|
19
|
-
|
28
|
+
%w[city town village hamlet].each do |key|
|
29
|
+
return @data['address'][key] if @data['address'].key?(key)
|
30
|
+
end
|
31
|
+
return nil
|
20
32
|
end
|
21
33
|
|
22
34
|
def village
|
@@ -49,13 +61,17 @@ module Geocoder::Result
|
|
49
61
|
@data['address']['country_code']
|
50
62
|
end
|
51
63
|
|
64
|
+
def suburb
|
65
|
+
@data['address']['suburb']
|
66
|
+
end
|
67
|
+
|
52
68
|
def coordinates
|
53
69
|
[@data['lat'].to_f, @data['lon'].to_f]
|
54
70
|
end
|
55
71
|
|
56
72
|
def self.response_attributes
|
57
|
-
%w[place_id
|
58
|
-
polygonpoints
|
73
|
+
%w[place_id osm_type osm_id boundingbox license
|
74
|
+
polygonpoints display_name class type stadium]
|
59
75
|
end
|
60
76
|
|
61
77
|
response_attributes.each do |a|
|
@@ -0,0 +1,15 @@
|
|
1
|
+
require 'geocoder/results/base'
|
2
|
+
|
3
|
+
module Geocoder
|
4
|
+
module Result
|
5
|
+
class Test < Base
|
6
|
+
|
7
|
+
%w[latitude longitude city state state_code province
|
8
|
+
province_code postal_code country country_code address].each do |attr|
|
9
|
+
define_method(attr) do
|
10
|
+
@data[attr.to_s] || @data[attr.to_sym]
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -57,6 +57,10 @@ module Geocoder::Result
|
|
57
57
|
address_details['Locality']['Premise']['PremiseName']
|
58
58
|
end
|
59
59
|
|
60
|
+
def precision
|
61
|
+
@data['GeoObject']['metaDataProperty']['GeocoderMetaData']['precision']
|
62
|
+
end
|
63
|
+
|
60
64
|
private # ----------------------------------------------------------------
|
61
65
|
|
62
66
|
def address_details
|
@@ -33,7 +33,7 @@ module Geocoder::Store
|
|
33
33
|
#
|
34
34
|
scope :near, lambda{ |location, *args|
|
35
35
|
latitude, longitude = Geocoder::Calculations.extract_coordinates(location)
|
36
|
-
if latitude
|
36
|
+
if Geocoder::Calculations.coordinates_present?(latitude, longitude)
|
37
37
|
near_scope_options(latitude, longitude, *args)
|
38
38
|
else
|
39
39
|
where(false_condition) # no results if no lat/lon given
|
@@ -68,7 +68,9 @@ module Geocoder::Store
|
|
68
68
|
|
69
69
|
def distance_from_sql(location, *args)
|
70
70
|
latitude, longitude = Geocoder::Calculations.extract_coordinates(location)
|
71
|
-
|
71
|
+
if Geocoder::Calculations.coordinates_present?(latitude, longitude)
|
72
|
+
distance_from_sql_options(latitude, longitude, *args)
|
73
|
+
end
|
72
74
|
end
|
73
75
|
|
74
76
|
private # ----------------------------------------------------------------
|
@@ -202,21 +204,21 @@ module Geocoder::Store
|
|
202
204
|
end
|
203
205
|
if options[:bearing]
|
204
206
|
bearing = "CASE " +
|
205
|
-
"WHEN (#{lat_attr} >= #{latitude} AND #{lon_attr} >= #{longitude}) THEN 45.0 " +
|
206
|
-
"WHEN (#{lat_attr} < #{latitude} AND #{lon_attr} >= #{longitude}) THEN 135.0 " +
|
207
|
-
"WHEN (#{lat_attr} < #{latitude} AND #{lon_attr} < #{longitude}) THEN 225.0 " +
|
208
|
-
"WHEN (#{lat_attr} >= #{latitude} AND #{lon_attr} < #{longitude}) THEN 315.0 " +
|
207
|
+
"WHEN (#{full_column_name(lat_attr)} >= #{latitude} AND #{full_column_name(lon_attr)} >= #{longitude}) THEN 45.0 " +
|
208
|
+
"WHEN (#{full_column_name(lat_attr)} < #{latitude} AND #{full_column_name(lon_attr)} >= #{longitude}) THEN 135.0 " +
|
209
|
+
"WHEN (#{full_column_name(lat_attr)} < #{latitude} AND #{full_column_name(lon_attr)} < #{longitude}) THEN 225.0 " +
|
210
|
+
"WHEN (#{full_column_name(lat_attr)} >= #{latitude} AND #{full_column_name(lon_attr)} < #{longitude}) THEN 315.0 " +
|
209
211
|
"END"
|
210
212
|
else
|
211
213
|
bearing = false
|
212
214
|
end
|
213
215
|
|
214
|
-
distance = approx_distance_from_sql(latitude, longitude, options)
|
215
216
|
options[:units] ||= (geocoder_options[:units] || Geocoder::Configuration.units)
|
217
|
+
distance = approx_distance_from_sql(latitude, longitude, options)
|
216
218
|
|
217
219
|
b = Geocoder::Calculations.bounding_box([latitude, longitude], radius, options)
|
218
220
|
conditions = [
|
219
|
-
"#{lat_attr} BETWEEN ? AND ? AND #{lon_attr} BETWEEN ? AND ?"] +
|
221
|
+
"#{full_column_name(lat_attr)} BETWEEN ? AND ? AND #{full_column_name(lon_attr)} BETWEEN ? AND ?"] +
|
220
222
|
[b[0], b[2], b[1], b[3]
|
221
223
|
]
|
222
224
|
default_near_scope_options(latitude, longitude, radius, options).merge(
|
data/lib/geocoder/version.rb
CHANGED
data/test/calculations_test.rb
CHANGED
@@ -152,24 +152,24 @@ class CalculationsTest < Test::Unit::TestCase
|
|
152
152
|
|
153
153
|
def test_extract_coordinates
|
154
154
|
result = Geocoder::Calculations.extract_coordinates([ nil, nil ])
|
155
|
-
|
155
|
+
assert is_nan_coordinates?(result)
|
156
156
|
|
157
157
|
result = Geocoder::Calculations.extract_coordinates([ 1.0 / 3, 2.0 / 3 ])
|
158
158
|
assert_in_delta 1.0 / 3, result.first, 1E-5
|
159
159
|
assert_in_delta 2.0 / 3, result.last, 1E-5
|
160
160
|
|
161
161
|
result = Geocoder::Calculations.extract_coordinates(nil)
|
162
|
-
|
162
|
+
assert is_nan_coordinates?(result)
|
163
163
|
|
164
164
|
result = Geocoder::Calculations.extract_coordinates('')
|
165
|
-
|
165
|
+
assert is_nan_coordinates?(result)
|
166
166
|
|
167
167
|
result = Geocoder::Calculations.extract_coordinates([ 'nix' ])
|
168
|
-
|
168
|
+
assert is_nan_coordinates?(result)
|
169
169
|
|
170
170
|
o = Object.new
|
171
171
|
result = Geocoder::Calculations.extract_coordinates(o)
|
172
|
-
|
172
|
+
assert is_nan_coordinates?(result)
|
173
173
|
|
174
174
|
def o.to_coordinates
|
175
175
|
[ 1.0 / 3, 2.0 / 3 ]
|
@@ -178,5 +178,11 @@ class CalculationsTest < Test::Unit::TestCase
|
|
178
178
|
assert_in_delta 1.0 / 3, result.first, 1E-5
|
179
179
|
assert_in_delta 2.0 / 3, result.last, 1E-5
|
180
180
|
end
|
181
|
-
end
|
182
181
|
|
182
|
+
def test_coordinates_present
|
183
|
+
assert Geocoder::Calculations.coordinates_present?(3.23)
|
184
|
+
assert !Geocoder::Calculations.coordinates_present?(nil)
|
185
|
+
assert !Geocoder::Calculations.coordinates_present?(Geocoder::Calculations::NAN)
|
186
|
+
assert !Geocoder::Calculations.coordinates_present?(3.23, nil)
|
187
|
+
end
|
188
|
+
end
|
data/test/error_handling_test.rb
CHANGED
@@ -10,7 +10,7 @@ class ErrorHandlingTest < Test::Unit::TestCase
|
|
10
10
|
def test_does_not_choke_on_timeout
|
11
11
|
# keep test output clean: suppress timeout warning
|
12
12
|
orig = $VERBOSE; $VERBOSE = nil
|
13
|
-
|
13
|
+
all_lookups_except_test.each do |l|
|
14
14
|
Geocoder::Configuration.lookup = l
|
15
15
|
assert_nothing_raised { Geocoder.search("timeout") }
|
16
16
|
end
|
@@ -19,7 +19,7 @@ class ErrorHandlingTest < Test::Unit::TestCase
|
|
19
19
|
|
20
20
|
def test_always_raise_timeout_error
|
21
21
|
Geocoder::Configuration.always_raise = [TimeoutError]
|
22
|
-
|
22
|
+
all_lookups_except_test.each do |l|
|
23
23
|
lookup = Geocoder.send(:get_lookup, l)
|
24
24
|
assert_raises TimeoutError do
|
25
25
|
lookup.send(:results, "timeout")
|
@@ -29,7 +29,7 @@ class ErrorHandlingTest < Test::Unit::TestCase
|
|
29
29
|
|
30
30
|
def test_always_raise_socket_error
|
31
31
|
Geocoder::Configuration.always_raise = [SocketError]
|
32
|
-
|
32
|
+
all_lookups_except_test.each do |l|
|
33
33
|
lookup = Geocoder.send(:get_lookup, l)
|
34
34
|
assert_raises SocketError do
|
35
35
|
lookup.send(:results, "socket_error")
|
@@ -0,0 +1,27 @@
|
|
1
|
+
[
|
2
|
+
{
|
3
|
+
"place_id":"2177656031",
|
4
|
+
"licence":"Data Copyright OpenStreetMap Contributors, Some Rights Reserved. CC-BY-SA 2.0.",
|
5
|
+
"osm_type":"way",
|
6
|
+
"osm_id":"138141251",
|
7
|
+
"boundingbox":["40.7498588562012","40.751163482666","-73.9944381713867","-73.9925842285156"],
|
8
|
+
"polygonpoints":[["-73.9944367","40.7505417"],["-73.9940278","40.7511034"],["-73.9939442","40.7510658"],["-73.9938776","40.7510941"],["-73.9937734","40.7511298"],["-73.9936562","40.7511561"],["-73.993619","40.7511624"],["-73.9935537","40.7510862"],["-73.9935336","40.7510885"],["-73.9934248","40.7510898"],["-73.9933248","40.7510806"],["-73.9932268","40.7510614"],["-73.9931334","40.7510327"],["-73.9930378","40.7509909"],["-73.9929554","40.7509421"],["-73.9928865","40.7508886"],["-73.992821","40.7508216"],["-73.9927742","40.7507572"],["-73.9926591","40.7507581"],["-73.9926036","40.750603"],["-73.992704","40.7505536"],["-73.9927029","40.7505065"],["-73.9925855","40.7505009"],["-73.9925989","40.7503952"],["-73.9926442","40.7504003"],["-73.9926722","40.7503155"],["-73.9927117","40.7502402"],["-73.9927617","40.7501715"],["-73.992824","40.7501067"],["-73.9928991","40.7500484"],["-73.992869","40.7500159"],["-73.9929742","40.749956"],["-73.9930375","40.7500318"],["-73.9931229","40.7499938"],["-73.9931273","40.7499005"],["-73.9933201","40.7498624"],["-73.9933853","40.7499355"],["-73.993402","40.7499336"],["-73.9935038","40.749932"],["-73.9936041","40.7499407"],["-73.9936962","40.7499579"],["-73.9937875","40.7499846"],["-73.9938783","40.7500221"],["-73.9939639","40.7500701"],["-73.9940328","40.7501206"],["-73.9940991","40.7501842"],["-73.9941506","40.7502504"],["-73.9941562","40.7502603"],["-73.9942791","40.7502628"],["-73.9942969","40.7503035"],["-73.9943271","40.7503844"],["-73.9943435","40.7504689"],["-73.9943454","40.7505049"],["-73.9944367","40.7505417"]],
|
9
|
+
"lat":"40.7505206016777",
|
10
|
+
"lon":"-73.993490694181",
|
11
|
+
"display_name":"Madison Square Garden, 46, West 31st Street, Chelsea, New York City, New York, United States of America",
|
12
|
+
"class":"leisure",
|
13
|
+
"type":"stadium",
|
14
|
+
"address":{
|
15
|
+
"stadium":"Madison Square Garden",
|
16
|
+
"house_number":"46",
|
17
|
+
"road":"West 31st Street",
|
18
|
+
"suburb":"Chelsea",
|
19
|
+
"city":"New York City",
|
20
|
+
"county":"New York",
|
21
|
+
"state":"New York",
|
22
|
+
"postcode":"10119",
|
23
|
+
"country":"United States of America",
|
24
|
+
"country_code":"us"
|
25
|
+
}
|
26
|
+
}
|
27
|
+
]
|
@@ -0,0 +1 @@
|
|
1
|
+
[]
|
data/test/lookup_test.rb
CHANGED
@@ -4,7 +4,7 @@ require 'test_helper'
|
|
4
4
|
class LookupTest < Test::Unit::TestCase
|
5
5
|
|
6
6
|
def test_search_returns_empty_array_when_no_results
|
7
|
-
|
7
|
+
all_lookups_except_test.each do |l|
|
8
8
|
lookup = Geocoder.send(:get_lookup, l)
|
9
9
|
assert_equal [], lookup.send(:results, "no results"),
|
10
10
|
"Lookup #{l} does not return empty array when no results."
|
data/test/mongoid_test.rb
CHANGED
@@ -17,7 +17,8 @@ class MongoidTest < Test::Unit::TestCase
|
|
17
17
|
def test_custom_coordinate_field_near_scope
|
18
18
|
location = [40.750354, -73.993371]
|
19
19
|
p = Place.near(location)
|
20
|
-
|
20
|
+
key = Mongoid::VERSION >= "3" ? "location" : :location
|
21
|
+
assert_equal p.selector[key]['$nearSphere'], location.reverse
|
21
22
|
end
|
22
23
|
|
23
24
|
def test_model_configuration
|
data/test/mongoid_test_helper.rb
CHANGED
@@ -7,8 +7,12 @@ require 'geocoder/models/mongoid'
|
|
7
7
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
8
8
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
9
9
|
|
10
|
-
Mongoid
|
11
|
-
|
10
|
+
if (::Mongoid::VERSION >= "3")
|
11
|
+
Mongoid.logger = Logger.new($stderr, :debug)
|
12
|
+
else
|
13
|
+
Mongoid.configure do |config|
|
14
|
+
config.logger = Logger.new($stderr, :debug)
|
15
|
+
end
|
12
16
|
end
|
13
17
|
|
14
18
|
##
|
data/test/result_test.rb
CHANGED
@@ -4,7 +4,7 @@ require 'test_helper'
|
|
4
4
|
class ResultTest < Test::Unit::TestCase
|
5
5
|
|
6
6
|
def test_result_has_required_attributes
|
7
|
-
|
7
|
+
all_lookups_except_test.each do |l|
|
8
8
|
Geocoder::Configuration.lookup = l
|
9
9
|
result = Geocoder.search([45.423733, -75.676333]).first
|
10
10
|
assert_result_has_required_attributes(result)
|
data/test/test_helper.rb
CHANGED
@@ -163,6 +163,19 @@ module Geocoder
|
|
163
163
|
end
|
164
164
|
end
|
165
165
|
|
166
|
+
class Mapquest < Base
|
167
|
+
private #-----------------------------------------------------------------
|
168
|
+
def fetch_raw_data(query, reverse = false)
|
169
|
+
raise TimeoutError if query == "timeout"
|
170
|
+
raise SocketError if query == "socket_error"
|
171
|
+
file = case query
|
172
|
+
when "no results"; :no_results
|
173
|
+
else :madison_square_garden
|
174
|
+
end
|
175
|
+
read_fixture "mapquest_#{file}.json"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
166
179
|
end
|
167
180
|
end
|
168
181
|
|
@@ -268,8 +281,18 @@ class Test::Unit::TestCase
|
|
268
281
|
Geocoder.valid_lookups
|
269
282
|
end
|
270
283
|
|
284
|
+
def all_lookups_except_test
|
285
|
+
Geocoder.valid_lookups - [:test]
|
286
|
+
end
|
287
|
+
|
271
288
|
def street_lookups
|
272
289
|
all_lookups - [:freegeoip]
|
273
290
|
end
|
291
|
+
|
292
|
+
def is_nan_coordinates?(coordinates)
|
293
|
+
return false unless coordinates.respond_to? :size # Should be an array
|
294
|
+
return false unless coordinates.size == 2 # Should have dimension 2
|
295
|
+
coordinates[0].nan? && coordinates[1].nan? # Both coordinates should be NaN
|
296
|
+
end
|
274
297
|
end
|
275
298
|
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
require 'geocoder/lookups/test'
|
3
|
+
|
4
|
+
class TestModeTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@_original_lookup = Geocoder::Configuration.lookup
|
8
|
+
Geocoder::Configuration.lookup = :test
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
Geocoder::Lookup::Test.reset
|
13
|
+
Geocoder::Configuration.lookup = @_original_lookup
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_search_with_known_stub
|
17
|
+
coordinates = [40.7143528, -74.0059731]
|
18
|
+
attributes = {
|
19
|
+
'coordinates' => coordinates,
|
20
|
+
'latitude' => coordinates[0],
|
21
|
+
'longitude' => coordinates[1],
|
22
|
+
'address' => 'New York, NY, USA',
|
23
|
+
'state' => 'New York',
|
24
|
+
'state_code' => 'NY',
|
25
|
+
'country' => 'United States',
|
26
|
+
'country_code' => 'US',
|
27
|
+
}
|
28
|
+
|
29
|
+
Geocoder::Lookup::Test.add_stub("New York, NY", [attributes])
|
30
|
+
|
31
|
+
results = Geocoder.search("New York, NY")
|
32
|
+
assert_equal 1, results.size
|
33
|
+
|
34
|
+
result = results.first
|
35
|
+
assert_equal coordinates, result.coordinates
|
36
|
+
assert_equal attributes['latitude'], result.latitude
|
37
|
+
assert_equal attributes['longitude'], result.longitude
|
38
|
+
assert_equal attributes['address'], result.address
|
39
|
+
assert_equal attributes['state'], result.state
|
40
|
+
assert_equal attributes['state_code'], result.state_code
|
41
|
+
assert_equal attributes['country'], result.country
|
42
|
+
assert_equal attributes['country_code'], result.country_code
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_search_with_unknown_stub
|
46
|
+
assert_raise ArgumentError do
|
47
|
+
Geocoder.search("New York, NY")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
metadata
CHANGED
@@ -1,34 +1,35 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: geocoder
|
3
|
-
version: !ruby/object:Gem::Version
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.1.3
|
4
5
|
prerelease:
|
5
|
-
version: 1.1.2
|
6
6
|
platform: ruby
|
7
|
-
authors:
|
7
|
+
authors:
|
8
8
|
- Alex Reisner
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
|
13
|
-
date: 2012-05-24 00:00:00 Z
|
12
|
+
date: 2012-08-26 00:00:00.000000000 Z
|
14
13
|
dependencies: []
|
15
|
-
|
16
|
-
|
17
|
-
|
14
|
+
description: Provides object geocoding (by street or IP address), reverse geocoding
|
15
|
+
(coordinates to street address), distance queries for ActiveRecord and Mongoid,
|
16
|
+
result caching, and more. Designed for Rails but works with Sinatra and other Rack
|
17
|
+
frameworks too.
|
18
|
+
email:
|
18
19
|
- alex@alexreisner.com
|
19
|
-
executables:
|
20
|
+
executables:
|
20
21
|
- geocode
|
21
22
|
extensions: []
|
22
|
-
|
23
23
|
extra_rdoc_files: []
|
24
|
-
|
25
|
-
files:
|
24
|
+
files:
|
26
25
|
- .gitignore
|
26
|
+
- .travis.yml
|
27
27
|
- CHANGELOG.rdoc
|
28
28
|
- LICENSE
|
29
29
|
- README.rdoc
|
30
30
|
- Rakefile
|
31
31
|
- bin/geocode
|
32
|
+
- gemfiles/Gemfile.mongoid-2.4.x
|
32
33
|
- lib/generators/geocoder/config/config_generator.rb
|
33
34
|
- lib/generators/geocoder/config/templates/initializer.rb
|
34
35
|
- lib/geocoder.rb
|
@@ -43,7 +44,9 @@ files:
|
|
43
44
|
- lib/geocoder/lookups/geocoder_ca.rb
|
44
45
|
- lib/geocoder/lookups/google.rb
|
45
46
|
- lib/geocoder/lookups/google_premier.rb
|
47
|
+
- lib/geocoder/lookups/mapquest.rb
|
46
48
|
- lib/geocoder/lookups/nominatim.rb
|
49
|
+
- lib/geocoder/lookups/test.rb
|
47
50
|
- lib/geocoder/lookups/yahoo.rb
|
48
51
|
- lib/geocoder/lookups/yandex.rb
|
49
52
|
- lib/geocoder/models/active_record.rb
|
@@ -59,7 +62,9 @@ files:
|
|
59
62
|
- lib/geocoder/results/geocoder_ca.rb
|
60
63
|
- lib/geocoder/results/google.rb
|
61
64
|
- lib/geocoder/results/google_premier.rb
|
65
|
+
- lib/geocoder/results/mapquest.rb
|
62
66
|
- lib/geocoder/results/nominatim.rb
|
67
|
+
- lib/geocoder/results/test.rb
|
63
68
|
- lib/geocoder/results/yahoo.rb
|
64
69
|
- lib/geocoder/results/yandex.rb
|
65
70
|
- lib/geocoder/stores/active_record.rb
|
@@ -86,6 +91,8 @@ files:
|
|
86
91
|
- test/fixtures/google_no_city_data.json
|
87
92
|
- test/fixtures/google_no_locality.json
|
88
93
|
- test/fixtures/google_no_results.json
|
94
|
+
- test/fixtures/mapquest_madison_square_garden.json
|
95
|
+
- test/fixtures/mapquest_no_results.json
|
89
96
|
- test/fixtures/nominatim_madison_square_garden.json
|
90
97
|
- test/fixtures/nominatim_no_results.json
|
91
98
|
- test/fixtures/yahoo_garbage.json
|
@@ -106,32 +113,35 @@ files:
|
|
106
113
|
- test/result_test.rb
|
107
114
|
- test/services_test.rb
|
108
115
|
- test/test_helper.rb
|
116
|
+
- test/test_mode_test.rb
|
109
117
|
homepage: http://www.rubygeocoder.com
|
110
118
|
licenses: []
|
111
|
-
|
112
119
|
post_install_message:
|
113
120
|
rdoc_options: []
|
114
|
-
|
115
|
-
require_paths:
|
121
|
+
require_paths:
|
116
122
|
- lib
|
117
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
123
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
118
124
|
none: false
|
119
|
-
requirements:
|
120
|
-
- -
|
121
|
-
- !ruby/object:Gem::Version
|
122
|
-
version:
|
123
|
-
|
125
|
+
requirements:
|
126
|
+
- - ! '>='
|
127
|
+
- !ruby/object:Gem::Version
|
128
|
+
version: '0'
|
129
|
+
segments:
|
130
|
+
- 0
|
131
|
+
hash: 585705263
|
132
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
124
133
|
none: false
|
125
|
-
requirements:
|
126
|
-
- -
|
127
|
-
- !ruby/object:Gem::Version
|
128
|
-
version:
|
134
|
+
requirements:
|
135
|
+
- - ! '>='
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
segments:
|
139
|
+
- 0
|
140
|
+
hash: 585705263
|
129
141
|
requirements: []
|
130
|
-
|
131
142
|
rubyforge_project:
|
132
143
|
rubygems_version: 1.8.24
|
133
144
|
signing_key:
|
134
145
|
specification_version: 3
|
135
146
|
summary: Complete geocoding solution for Ruby.
|
136
147
|
test_files: []
|
137
|
-
|