dusty-geocoder 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
+