dusty-geocoder 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/README.txt ADDED
@@ -0,0 +1,36 @@
1
+ == DESCRIPTION:
2
+
3
+ Used to interact with Googles Geocoding API
4
+
5
+
6
+ == REQUIREMENTS:
7
+
8
+ patron
9
+ json
10
+
11
+
12
+ == INSTALL:
13
+
14
+ $ gem build geocoder.gemspec
15
+ $ sudo gem install geocoder-x.x.x.gem
16
+
17
+
18
+ == USAGE:
19
+
20
+ Geocoder.search('123 My St, MyCity, NY')
21
+ # returns an array of addresses or throws an exception
22
+
23
+ Geocoder.first('123 My St, MyCity, NY')
24
+ # returns a single address or throws an exception
25
+
26
+ See Geocoder::Response.check_status for errors thrown depending on the results
27
+ Errors in the HTTP call throw a Geocoder::ConnectionError
28
+
29
+ Your google API key is required. You may set this in one of two ways.
30
+
31
+ 1. Set the class variable with Geocoder::Client.key = 'xxxxxx'
32
+ $ Geocoder.search('My Address') # uses default key
33
+
34
+ 2. Send the key with your searches
35
+ $ Geocoder.search('My Address', key) # uses defined key
36
+
@@ -0,0 +1,81 @@
1
+ module Geocoder
2
+
3
+ class Client
4
+
5
+ ##
6
+ # Returns the default key
7
+ def self.key
8
+ @key ||= raise(MapKeyError, 'Missing Key: Geocoder::Client.key=(key)')
9
+ end
10
+
11
+ ##
12
+ # Sets the default key
13
+ def self.key=(key)
14
+ @key = key
15
+ end
16
+
17
+ ##
18
+ # Initialize the Client
19
+ #
20
+ # If the key is passed it will be used in place of the default key
21
+ def initialize(key=nil)
22
+ @key ||= self.class.key
23
+ @http = Patron::Session.new
24
+ @http.base_url = 'http://maps.google.com/maps/geo'
25
+ end
26
+
27
+ ##
28
+ # Search for addresses that match a string
29
+ #
30
+ # @param [String] Address required for search
31
+ # @return [Array<Address>] An array of addresses
32
+ # @raise [StandardError] on errors
33
+ def search(address)
34
+ begin
35
+ response = @http.get(hash_to_string(:q => address))
36
+ rescue StandardError => e
37
+ raise(ConnectionError, e.message)
38
+ end
39
+ unless response.status == 200
40
+ raise(ConnectionError, "Response Code: #{response.status}")
41
+ end
42
+ Response.new(response.body).addresses
43
+ end
44
+
45
+ ##
46
+ # Search for the first address that matches a string
47
+ #
48
+ # @see Geocoder::Client#search
49
+ # @param [String] Address required for search
50
+ # @return [Address] An address object
51
+ # @raise [StandardError] on errors
52
+ def first(address)
53
+ search.first
54
+ end
55
+
56
+ private
57
+
58
+ ##
59
+ # Set the default parameters to use in searches
60
+ def default_params
61
+ {:key => @key, :gl => 'US', :output => 'json'}
62
+ end
63
+
64
+ ##
65
+ # Convert a hash into a query parameter
66
+ #
67
+ # Example:
68
+ # {:q => 'my address', :output => 'json'}
69
+ # ?q=my%20address&output=json
70
+ #
71
+ # @return [String]
72
+ def hash_to_string(hash)
73
+ output = default_params.update(hash).map do |key, value|
74
+ "#{key}=#{@http.escape(value.to_s)}"
75
+ end.join("&")
76
+ "?#{output}"
77
+ end
78
+
79
+ end
80
+
81
+ end
@@ -0,0 +1,170 @@
1
+ module Geocoder
2
+
3
+ class Response
4
+ attr_reader :json
5
+
6
+ ##
7
+ # Initialize the response and check for errors in the Status code
8
+ #
9
+ # @see check_status
10
+ # @raise [StandardError]
11
+ def initialize(json)
12
+ @json = json
13
+ @hash = JSON.parse(json)
14
+ check_status
15
+ end
16
+
17
+ ##
18
+ # Return an array of addresses that matched the search
19
+ #
20
+ # @return [Array<Address>]
21
+ def addresses
22
+ @addresses ||= @hash["Placemark"].map {|place| Address.new(place)}
23
+ end
24
+
25
+ ##
26
+ # Check the status returned by Google and throw exception on
27
+ # results that are not 200
28
+ #
29
+ # @raise [StandardError]
30
+ def check_status
31
+ case @hash["Status"]["code"]
32
+ when 200 then
33
+ true
34
+ when 500
35
+ raise ServerError, "Unknown server error"
36
+ when 601
37
+ raise MissingAddressError, "Missing address"
38
+ when 602
39
+ raise UnknownAddressError, "Unknown address"
40
+ when 603
41
+ raise UnavailableAddressError, "Unavailable address"
42
+ when 610
43
+ raise InvalidMapKeyError, "Invalid map key"
44
+ when 620
45
+ raise TooManyQueriesError, "Too many queries for map key"
46
+ else
47
+ raise UnknownError, "Unknown error: #{@hash['code']}"
48
+ end
49
+ end
50
+
51
+ end
52
+
53
+ class Address
54
+ ##
55
+ # Initialize class
56
+ #
57
+ # set @hash to the json parsed hash
58
+ def initialize(hash)
59
+ @hash = hash
60
+ end
61
+
62
+ ##
63
+ # Address
64
+ #
65
+ # @return [String] address
66
+ def address
67
+ @address ||= @hash["address"]
68
+ end
69
+
70
+ ##
71
+ # Street
72
+ #
73
+ # @return [String] street
74
+ def street
75
+ @street ||= @hash["AddressDetails"]["Country"]["AdministrativeArea"]\
76
+ ["Locality"]["Thoroughfare"]["ThoroughfareName"]
77
+ end
78
+
79
+ ##
80
+ # City
81
+ #
82
+ # @return [String] city
83
+ def city
84
+ @city ||= @hash["AddressDetails"]["Country"]["AdministrativeArea"]\
85
+ ["Locality"]["LocalityName"]
86
+ end
87
+
88
+ ##
89
+ # State
90
+ #
91
+ # @return [String] state
92
+ def state
93
+ @state ||= @hash["AddressDetails"]["Country"]["AdministrativeArea"]\
94
+ ["AdministrativeAreaName"]
95
+ end
96
+
97
+ ##
98
+ # Zipcode
99
+ #
100
+ # @return [String] zipcode
101
+ def zipcode
102
+ @zipcode ||= @hash["AddressDetails"]["Country"]["AdministrativeArea"]\
103
+ ["Locality"]["PostalCode"]["PostalCodeNumber"]
104
+ end
105
+
106
+ ##
107
+ # Country
108
+ #
109
+ # @return [String] country
110
+ def country
111
+ @country ||= @hash["AddressDetails"]["Country"]["CountryNameCode"]
112
+ end
113
+
114
+ ##
115
+ # Accuracy
116
+ #
117
+ # Convert Googles Accuracy integer into a word describing how accurate
118
+ # the match is
119
+ #
120
+ # @see accuracy_map
121
+ # @return [String] accuracy
122
+ def accuracy
123
+ @accuracy ||= accuracy_map[@hash["AddressDetails"]["Accuracy"].to_i]
124
+ end
125
+
126
+ ##
127
+ # Coordinates
128
+ #
129
+ # An array of coordinates in the form of [lat, lng, elevation]
130
+ #
131
+ # @return [<Array>] lat, lng, elevation
132
+ def coordinates
133
+ @coordinates ||= [lat, lng, elevation]
134
+ end
135
+
136
+ ##
137
+ # Lat
138
+ #
139
+ # @return [Float] latitude
140
+ def lat
141
+ @lat ||= @hash["Point"]["coordinates"][0].to_f
142
+ end
143
+
144
+ ##
145
+ # Lng
146
+ #
147
+ # @return [Float] longitude
148
+ def lng
149
+ @lng ||= @hash["Point"]["coordinates"][1].to_f
150
+ end
151
+
152
+ ##
153
+ # Elevation
154
+ #
155
+ # @return [Float] elevation
156
+ def elevation
157
+ @elevation ||= @hash["Point"]["coordinates"][2].to_f
158
+ end
159
+
160
+ private
161
+
162
+ ##
163
+ # Map Googles code to a user friendly word
164
+ #
165
+ # @return [String]
166
+ def accuracy_map
167
+ %w{ unknown country state county city zip zip+4 street address }
168
+ end
169
+ end
170
+ end
data/lib/geocoder.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'patron'
2
+ require 'json'
3
+ module Geocoder
4
+
5
+ class Error < StandardError; end
6
+ class ServerError < Error; end
7
+ class AddressError < Error; end
8
+ class MissingAddressError < AddressError; end
9
+ class UnknownAddressError < AddressError; end
10
+ class UnavailableAddressError < AddressError; end
11
+ class MapKeyError < Error; end
12
+ class InvalidMapKeyError < MapKeyError; end
13
+ class TooManyQueriesError < MapKeyError; end
14
+ class UnknownError < Error; end
15
+ class ConnectionError < Error; end
16
+
17
+ ##
18
+ # The current version of the application
19
+ def self.version
20
+ "0.0.2"
21
+ end
22
+
23
+ ##
24
+ # Search for addresses that match a string
25
+ #
26
+ # @see Geocoder::Client#search
27
+ def self.search(address,key=nil)
28
+ Client.new(key).search(address)
29
+ end
30
+
31
+ ##
32
+ # Search for the first address that matches a string
33
+ #
34
+ # @see Geocoder::Client#first
35
+ def self.first(address,key=nil)
36
+ search(address,key).first
37
+ end
38
+
39
+ end
40
+
41
+ require File.join(
42
+ File.expand_path(File.dirname(__FILE__)), 'geocoder', 'client'
43
+ )
44
+ require File.join(
45
+ File.expand_path(File.dirname(__FILE__)), 'geocoder', 'response'
46
+ )
metadata ADDED
@@ -0,0 +1,76 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dusty-geocoder
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Dusty Doris
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-05-16 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: json
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: patron
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ description:
36
+ email: github@dusty.name
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - README.txt
43
+ files:
44
+ - README.txt
45
+ - lib/geocoder.rb
46
+ - lib/geocoder/client.rb
47
+ - lib/geocoder/response.rb
48
+ has_rdoc: true
49
+ homepage: http://code.dusty.name
50
+ licenses:
51
+ post_install_message:
52
+ rdoc_options: []
53
+
54
+ require_paths:
55
+ - lib
56
+ required_ruby_version: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: "0"
61
+ version:
62
+ required_rubygems_version: !ruby/object:Gem::Requirement
63
+ requirements:
64
+ - - ">="
65
+ - !ruby/object:Gem::Version
66
+ version: "0"
67
+ version:
68
+ requirements: []
69
+
70
+ rubyforge_project: none
71
+ rubygems_version: 1.3.5
72
+ signing_key:
73
+ specification_version: 2
74
+ summary: Interface to Google's Geocoder API
75
+ test_files: []
76
+