graticule 0.1.3 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/CHANGELOG.txt +11 -0
  2. data/Manifest.txt +26 -11
  3. data/README.txt +1 -1
  4. data/bin/geocode +1 -1
  5. data/lib/graticule.rb +10 -8
  6. data/lib/graticule/cli.rb +1 -0
  7. data/lib/graticule/geocoder.rb +1 -12
  8. data/lib/graticule/geocoder/bogus.rb +15 -0
  9. data/lib/graticule/geocoder/geocoder_ca.rb +52 -0
  10. data/lib/graticule/geocoder/geocoder_us.rb +47 -0
  11. data/lib/graticule/geocoder/google.rb +106 -0
  12. data/lib/graticule/geocoder/host_ip.rb +50 -0
  13. data/lib/graticule/geocoder/local_search_maps.rb +45 -0
  14. data/lib/graticule/geocoder/meta_carta.rb +38 -0
  15. data/lib/graticule/geocoder/postcode_anywhere.rb +63 -0
  16. data/lib/graticule/geocoder/rest.rb +110 -0
  17. data/lib/graticule/geocoder/yahoo.rb +96 -0
  18. data/lib/graticule/location.rb +19 -7
  19. data/lib/graticule/version.rb +2 -2
  20. data/test/fixtures/responses/host_ip/private.txt +4 -0
  21. data/test/fixtures/responses/host_ip/success.txt +4 -0
  22. data/test/fixtures/responses/host_ip/unknown.txt +4 -0
  23. data/test/fixtures/responses/local_search_maps/success.txt +1 -0
  24. data/test/fixtures/responses/postcode_anywhere/badkey.xml +9 -0
  25. data/test/fixtures/responses/postcode_anywhere/canada.xml +16 -0
  26. data/test/fixtures/responses/postcode_anywhere/empty.xml +16 -0
  27. data/test/fixtures/responses/postcode_anywhere/success.xml +16 -0
  28. data/test/fixtures/responses/postcode_anywhere/uk.xml +18 -0
  29. data/test/test_helper.rb +4 -2
  30. data/test/unit/graticule/geocoder/geocoder_us_test.rb +43 -0
  31. data/test/unit/graticule/geocoder/google_test.rb +66 -0
  32. data/test/unit/graticule/geocoder/host_ip_test.rb +39 -0
  33. data/test/unit/graticule/geocoder/local_search_maps_test.rb +30 -0
  34. data/test/unit/graticule/geocoder/meta_carta_test.rb +44 -0
  35. data/test/unit/graticule/geocoder/postcode_anywhere_test.rb +50 -0
  36. data/test/unit/graticule/geocoder/yahoo_test.rb +48 -0
  37. data/test/unit/graticule/geocoder_test.rb +5 -9
  38. data/test/unit/graticule/location_test.rb +22 -7
  39. metadata +37 -18
  40. data/lib/graticule/geocoders/bogus.rb +0 -11
  41. data/lib/graticule/geocoders/geocoder_us.rb +0 -45
  42. data/lib/graticule/geocoders/google.rb +0 -99
  43. data/lib/graticule/geocoders/meta_carta.rb +0 -102
  44. data/lib/graticule/geocoders/rest.rb +0 -98
  45. data/lib/graticule/geocoders/yahoo.rb +0 -101
  46. data/test/unit/graticule/geocoders/geocoder_us_test.rb +0 -42
  47. data/test/unit/graticule/geocoders/geocoders.rb +0 -56
  48. data/test/unit/graticule/geocoders/google_test.rb +0 -22
  49. data/test/unit/graticule/geocoders/meta_carta_test.rb +0 -70
  50. data/test/unit/graticule/geocoders/yahoo_test.rb +0 -49
metadata CHANGED
@@ -1,10 +1,10 @@
1
1
  --- !ruby/object:Gem::Specification
2
- rubygems_version: 0.8.11
2
+ rubygems_version: 0.9.2
3
3
  specification_version: 1
4
4
  name: graticule
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.3
7
- date: 2007-02-14 00:00:00 -05:00
6
+ version: 0.2.0
7
+ date: 2007-03-17 00:00:00 -04:00
8
8
  summary: API for using all the popular geocoding services.
9
9
  require_paths:
10
10
  - lib
@@ -25,6 +25,7 @@ required_ruby_version: !ruby/object:Gem::Version::Requirement
25
25
  platform: ruby
26
26
  signing_key:
27
27
  cert_chain:
28
+ post_install_message:
28
29
  authors:
29
30
  - Brandon Keepers
30
31
  files:
@@ -42,12 +43,16 @@ files:
42
43
  - lib/graticule/distance/spherical.rb
43
44
  - lib/graticule/distance/vincenty.rb
44
45
  - lib/graticule/geocoder.rb
45
- - lib/graticule/geocoders/bogus.rb
46
- - lib/graticule/geocoders/geocoder_us.rb
47
- - lib/graticule/geocoders/google.rb
48
- - lib/graticule/geocoders/meta_carta.rb
49
- - lib/graticule/geocoders/rest.rb
50
- - lib/graticule/geocoders/yahoo.rb
46
+ - lib/graticule/geocoder/bogus.rb
47
+ - lib/graticule/geocoder/geocoder_ca.rb
48
+ - lib/graticule/geocoder/geocoder_us.rb
49
+ - lib/graticule/geocoder/google.rb
50
+ - lib/graticule/geocoder/host_ip.rb
51
+ - lib/graticule/geocoder/local_search_maps.rb
52
+ - lib/graticule/geocoder/meta_carta.rb
53
+ - lib/graticule/geocoder/postcode_anywhere.rb
54
+ - lib/graticule/geocoder/rest.rb
55
+ - lib/graticule/geocoder/yahoo.rb
51
56
  - lib/graticule/location.rb
52
57
  - lib/graticule/version.rb
53
58
  - test/fixtures/responses/geocoder_us/success.xml
@@ -59,29 +64,43 @@ files:
59
64
  - test/fixtures/responses/google/success.xml
60
65
  - test/fixtures/responses/google/unavailable.xml
61
66
  - test/fixtures/responses/google/unknown_address.xml
67
+ - test/fixtures/responses/host_ip/private.txt
68
+ - test/fixtures/responses/host_ip/success.txt
69
+ - test/fixtures/responses/host_ip/unknown.txt
70
+ - test/fixtures/responses/local_search_maps/success.txt
62
71
  - test/fixtures/responses/meta_carta/bad_address.xml
63
72
  - test/fixtures/responses/meta_carta/multiple.xml
64
73
  - test/fixtures/responses/meta_carta/success.xml
74
+ - test/fixtures/responses/postcode_anywhere/badkey.xml
75
+ - test/fixtures/responses/postcode_anywhere/canada.xml
76
+ - test/fixtures/responses/postcode_anywhere/empty.xml
77
+ - test/fixtures/responses/postcode_anywhere/success.xml
78
+ - test/fixtures/responses/postcode_anywhere/uk.xml
65
79
  - test/fixtures/responses/yahoo/success.xml
66
80
  - test/fixtures/responses/yahoo/unknown_address.xml
67
81
  - test/mocks/uri.rb
68
82
  - test/test_helper.rb
69
83
  - test/unit/graticule/distance_test.rb
84
+ - test/unit/graticule/geocoder/geocoder_us_test.rb
85
+ - test/unit/graticule/geocoder/google_test.rb
86
+ - test/unit/graticule/geocoder/host_ip_test.rb
87
+ - test/unit/graticule/geocoder/local_search_maps_test.rb
88
+ - test/unit/graticule/geocoder/meta_carta_test.rb
89
+ - test/unit/graticule/geocoder/postcode_anywhere_test.rb
90
+ - test/unit/graticule/geocoder/yahoo_test.rb
70
91
  - test/unit/graticule/geocoder_test.rb
71
- - test/unit/graticule/geocoders/geocoder_us_test.rb
72
- - test/unit/graticule/geocoders/geocoders.rb
73
- - test/unit/graticule/geocoders/google_test.rb
74
- - test/unit/graticule/geocoders/meta_carta_test.rb
75
- - test/unit/graticule/geocoders/yahoo_test.rb
76
92
  - test/unit/graticule/location_test.rb
77
93
  test_files:
78
94
  - test/unit/graticule/distance_test.rb
79
95
  - test/unit/graticule/geocoder_test.rb
80
96
  - test/unit/graticule/location_test.rb
81
- - test/unit/graticule/geocoders/geocoder_us_test.rb
82
- - test/unit/graticule/geocoders/google_test.rb
83
- - test/unit/graticule/geocoders/meta_carta_test.rb
84
- - test/unit/graticule/geocoders/yahoo_test.rb
97
+ - test/unit/graticule/geocoder/geocoder_us_test.rb
98
+ - test/unit/graticule/geocoder/google_test.rb
99
+ - test/unit/graticule/geocoder/host_ip_test.rb
100
+ - test/unit/graticule/geocoder/local_search_maps_test.rb
101
+ - test/unit/graticule/geocoder/meta_carta_test.rb
102
+ - test/unit/graticule/geocoder/postcode_anywhere_test.rb
103
+ - test/unit/graticule/geocoder/yahoo_test.rb
85
104
  rdoc_options: []
86
105
 
87
106
  extra_rdoc_files: []
@@ -1,11 +0,0 @@
1
- module Graticule #:nodoc:
2
-
3
- # Bogus geocoder that can be used for test purposes
4
- class BogusGeocoder < Geocoder
5
-
6
- def locate(address)
7
- Location.new :street => address
8
- end
9
-
10
- end
11
- end
@@ -1,45 +0,0 @@
1
- module Graticule #:nodoc:
2
-
3
- # A library for lookup up coordinates with geocoder.us' API.
4
- #
5
- # http://geocoder.us/help/
6
- class GeocoderUsGeocoder < RestGeocoder
7
-
8
- # Creates a new GeocoderUs object optionally using +username+ and
9
- # +password+.
10
- #
11
- # You can sign up for a geocoder.us account here:
12
- #
13
- # http://geocoder.us/user/signup
14
- def initialize(user = nil, password = nil)
15
- if user and password then
16
- @url = URI.parse 'http://geocoder.us/member/service/rest/geocode'
17
- @url.user = user
18
- @url.password = password
19
- else
20
- @url = URI.parse 'http://rpc.geocoder.us/service/rest/geocode'
21
- end
22
- end
23
-
24
- # Locates +address+ and returns the address' latitude and longitude or
25
- # raises an AddressError.
26
- def locate(address)
27
- get :address => address
28
- end
29
-
30
- def parse_response(xml) #:nodoc:
31
- location = Location.new
32
- location.street = xml.elements['rdf:RDF/geo:Point/dc:description'].text
33
-
34
- location.latitude = xml.elements['rdf:RDF/geo:Point/geo:lat'].text.to_f
35
- location.longitude = xml.elements['rdf:RDF/geo:Point/geo:long'].text.to_f
36
-
37
- return location
38
- end
39
-
40
- def check_error(xml) #:nodoc:
41
- raise AddressError, xml.text if xml.text == 'couldn\'t find this address! sorry'
42
- end
43
-
44
- end
45
- end
@@ -1,99 +0,0 @@
1
-
2
- module Graticule
3
-
4
- # First you need a Google Maps API key. You can register for one here:
5
- # http://www.google.com/apis/maps/signup.html
6
- #
7
- # Then you create a GoogleGeocode object and start locating addresses:
8
- #
9
- # require 'rubygems'
10
- # require 'graticule'
11
- #
12
- # gg = Graticule.service(:google).new(:key => MAPS_API_KEY)
13
- # location = gg.locate '1600 Amphitheater Pkwy, Mountain View, CA'
14
- # p location.coordinates
15
- #
16
- class GoogleGeocoder < RestGeocoder
17
- # http://www.google.com/apis/maps/documentation/#Geocoding_HTTP_Request
18
-
19
- # http://www.google.com/apis/maps/documentation/reference.html#GGeoAddressAccuracy
20
- PRECISION = {
21
- 0 => :unknown, # Unknown location. (Since 2.59)
22
- 1 => :country, # Country level accuracy. (Since 2.59)
23
- 2 => :state, # Region (state, province, prefecture, etc.) level accuracy. (Since 2.59)
24
- 3 => :state, # Sub-region (county, municipality, etc.) level accuracy. (Since 2.59)
25
- 4 => :city, # Town (city, village) level accuracy. (Since 2.59)
26
- 5 => :zip, # Post code (zip code) level accuracy. (Since 2.59)
27
- 6 => :street, # Street level accuracy. (Since 2.59)
28
- 7 => :street, # Intersection level accuracy. (Since 2.59)
29
- 8 => :address # Address level accuracy. (Since 2.59)
30
- }
31
-
32
- # Creates a new GoogleGeocode that will use Google Maps API key +key+. You
33
- # can sign up for an API key here:
34
- #
35
- # http://www.google.com/apis/maps/signup.html
36
- def initialize(key)
37
- @key = key
38
- @url = URI.parse 'http://maps.google.com/maps/geo'
39
- end
40
-
41
- # Locates +address+ returning a Location
42
- def locate(address)
43
- get :q => address
44
- end
45
-
46
- # Extracts a Location from +xml+.
47
- def parse_response(xml) #:nodoc:
48
- address = REXML::XPath.first(xml, '//xal:AddressDetails', 'xal' => "urn:oasis:names:tc:ciq:xsdschema:xAL:2.0")
49
-
50
- longitude, latitude, = xml.elements['/kml/Response/Placemark/Point/coordinates'].text.split(',').map { |v| v.to_f }
51
-
52
- Location.new \
53
- :street => address.elements['Country/AdministrativeArea/SubAdministrativeArea/Locality/Thoroughfare/ThoroughfareName/text()'].value,
54
- :city => address.elements['Country/AdministrativeArea/SubAdministrativeArea/Locality/LocalityName/text()'].value,
55
- :state => address.elements['Country/AdministrativeArea/AdministrativeAreaName/text()'].value,
56
- :zip => address.elements['Country/AdministrativeArea/SubAdministrativeArea/Locality/PostalCode/PostalCodeNumber/text()'].value,
57
- :country => address.elements['Country/CountryNameCode/text()'].value,
58
- :latitude => latitude,
59
- :longitude => longitude,
60
- :precision => PRECISION[address.attribute('Accuracy').value.to_i] || :unknown
61
- end
62
-
63
- # Extracts and raises an error from +xml+, if any.
64
- def check_error(xml) #:nodoc:
65
- status ||= xml.elements['/kml/Response/Status/code'].text.to_i
66
- case status
67
- when 200 then # ignore, ok
68
- when 500 then
69
- raise Error, 'server error'
70
- when 601 then
71
- raise AddressError, 'missing address'
72
- when 602 then
73
- raise AddressError, 'unknown address'
74
- when 603 then
75
- raise AddressError, 'unavailable address'
76
- when 610 then
77
- raise CredentialsError, 'invalid key'
78
- when 620 then
79
- raise CredentialsError, 'too many queries'
80
- else
81
- raise Error, "unknown error #{status}"
82
- end
83
- end
84
-
85
- # Creates a URL from the Hash +params+. Automatically adds the key and
86
- # sets the output type to 'xml'.
87
- def make_url(params) #:nodoc:
88
- params[:key] = @key
89
- params[:output] = 'xml'
90
-
91
- super params
92
- end
93
-
94
- private
95
- def text(element)
96
- element.text if element
97
- end
98
- end
99
- end
@@ -1,102 +0,0 @@
1
-
2
- module Graticule
3
-
4
- # Library for looking up coordinates with MetaCarta's GeoParser API.
5
- #
6
- # http://labs.metacarta.com/GeoParser/documentation.html
7
- class MetaCartaGeocoder < RestGeocoder
8
- Location = Struct.new :name, :type, :population, :hierarchy,
9
- :latitude, :longitude, :confidence, :viewbox
10
-
11
- def initialize # :nodoc:
12
- @url = URI.parse 'http://labs.metacarta.com/GeoParser/'
13
- end
14
-
15
- # Locates +place+ and returns a Location object.
16
- def locate(place)
17
- locations, = get :q => place
18
- return locations.first
19
- end
20
-
21
- # Retrieve all locations matching +place+.
22
- #
23
- # Returns an Array of Location objects and a pair of coordinates that will
24
- # surround them.
25
- def locations(place)
26
- get :loc => place
27
- end
28
-
29
- def check_error(xml) # :nodoc:
30
- raise AddressError, 'bad location' unless xml.elements['Locations/Location']
31
- end
32
-
33
- def make_url(params) # :nodoc:
34
- params[:output] = 'locations'
35
-
36
- super params
37
- end
38
-
39
- def parse_response(xml) # :nodoc:
40
- locations = []
41
-
42
- xml.elements['/Locations'].each do |l|
43
- next if REXML::Text === l or l.name == 'ViewBox'
44
- location = Location.new
45
-
46
- location.viewbox = viewbox_coords l.elements['ViewBox/gml:Box/gml:coordinates']
47
-
48
- location.name = l.attributes['Name']
49
- location.type = l.attributes['Type']
50
- population = l.attributes['Population'].to_i
51
- location.population = population > 0 ? population : nil
52
- location.hierarchy = l.attributes['Hierarchy']
53
-
54
- coords = l.elements['Centroid/gml:Point/gml:coordinates'].text.split ','
55
- location.latitude = coords.first.to_f
56
- location.longitude = coords.last.to_f
57
-
58
- confidence = l.elements['Confidence']
59
- location.confidence = confidence.text.to_f if confidence
60
-
61
- locations << location
62
- end
63
-
64
- query_viewbox = xml.elements['/Locations/ViewBox/gml:Box/gml:coordinates']
65
-
66
- return locations, viewbox_coords(query_viewbox)
67
- end
68
-
69
- # Turns a element containing a pair of coordinates into a pair of coordinate
70
- # Arrays.
71
- def viewbox_coords(viewbox) # :nodoc:
72
- return viewbox.text.split(' ').map do |coords|
73
- coords.split(',').map { |c| c.to_f }
74
- end
75
- end
76
-
77
- end
78
-
79
- # A Location contains the following fields:
80
- #
81
- # +name+:: The name of this location
82
- # +type+:: The type of this location (no clue what it means)
83
- # +population+:: The number of people who live here or nil
84
- # +hierarchy+:: The places above this place
85
- # +latitude+:: Latitude of the location
86
- # +longitude+:: Longitude of the location
87
- # +confidence+:: Accuracy confidence (if any)
88
- # +viewbox+:: Pair of coordinates forming a box around this place
89
- #
90
- # viewbox runs from lower left to upper right.
91
- class MetaCartaGeocoder::Location
92
-
93
- ##
94
- # The latitude and longitude for this location.
95
-
96
- def coordinates
97
- [latitude, longitude]
98
- end
99
-
100
- end
101
-
102
- end
@@ -1,98 +0,0 @@
1
- require 'open-uri'
2
- require 'rexml/document'
3
-
4
- module Graticule #:nodoc:
5
-
6
- # Abstract class for implementing REST APIs.
7
- #
8
- # === Example
9
- #
10
- # The following methods must be implemented in sublcasses:
11
- #
12
- # +initialize+:: Sets @url to the service enpoint.
13
- # +check_error+:: Checks for errors in the server response.
14
- # +parse_response+:: Extracts information from the server response.
15
- #
16
- # If you have extra URL paramaters (application id, output type) or need to
17
- # perform URL customization, override +make_url+.
18
- #
19
- # class FakeService < RCRest
20
- #
21
- # class Error < RCRest::Error; end
22
- #
23
- # def initialize(appid)
24
- # @appid = appid
25
- # @url = URI.parse 'http://example.com/test'
26
- # end
27
- #
28
- # def check_error(xml)
29
- # raise Error, xml.elements['error'].text if xml.elements['error']
30
- # end
31
- #
32
- # def make_url(params)
33
- # params[:appid] = @appid
34
- # super params
35
- # end
36
- #
37
- # def parse_response(xml)
38
- # return xml
39
- # end
40
- #
41
- # def test(query)
42
- # get :q => query
43
- # end
44
- #
45
- # end
46
- class RestGeocoder < Geocoder
47
-
48
- # Web services initializer.
49
- #
50
- # Concrete web services implementations must set the +url+ instance
51
- # variable which must be a URI.
52
- def initialize
53
- raise NotImplementedError
54
- end
55
-
56
- # Must extract and raise an error from +xml+, an REXML::Document, if any.
57
- # Must returns if no error could be found.
58
- def check_error(xml)
59
- raise NotImplementedError
60
- end
61
-
62
- # Performs a GET request with +params+. Calls the parse_response method on
63
- # the concrete class with an REXML::Document instance and returns its
64
- # result.
65
- def get(params = {})
66
- url = make_url params
67
-
68
- url.open do |response|
69
- res = REXML::Document.new response.read
70
- check_error(res)
71
- return parse_response(res)
72
- end
73
- rescue OpenURI::HTTPError => e
74
- response = REXML::Document.new e.io.read
75
- check_error response
76
- raise
77
- end
78
-
79
- # Creates a URI from the Hash +params+. Override this then call super if
80
- # you need to add extra params like an application id or output type.
81
- def make_url(params)
82
- escaped_params = params.sort_by { |k,v| k.to_s }.map do |k,v|
83
- "#{URI.escape k.to_s}=#{URI.escape v.to_s}"
84
- end
85
-
86
- url = @url.dup
87
- url.query = escaped_params.join '&'
88
- return url
89
- end
90
-
91
- # Must parse results from +xml+, an REXML::Document, into something sensible
92
- # for the API.
93
- def parse_response(xml)
94
- raise NotImplementedError
95
- end
96
-
97
- end
98
- end