geocoda 0.0.1

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 geocoda.gemspec
15
+ $ sudo gem install geocoda-x.x.x.gem
16
+
17
+
18
+ == USAGE:
19
+
20
+ Geocoda.search('123 My St, MyCity, NY')
21
+ # returns an array of addresses or throws an exception
22
+
23
+ Geocoda.first('123 My St, MyCity, NY')
24
+ # returns a single address or throws an exception
25
+
26
+ See Geocoda::Response.check_status for errors thrown depending on the results
27
+ Errors in the HTTP call throw a Geocoda::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 Geocoda::Client.key = 'xxxxxx'
32
+ $ Geocoda.search('My Address') # uses default key
33
+
34
+ 2. Send the key with your searches
35
+ $ Geocoda.search('My Address', key) # uses defined key
36
+
@@ -0,0 +1,81 @@
1
+ module Geocoda
2
+
3
+ class Client
4
+
5
+ ##
6
+ # Returns the default key
7
+ def self.key
8
+ @key ||= raise(MapKeyError, 'Missing Key: Geocoda::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 Geocoda::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,173 @@
1
+ module Geocoda
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"] rescue nil
77
+ end
78
+
79
+ ##
80
+ # City
81
+ #
82
+ # @return [String] city
83
+ def city
84
+ @city ||= @hash["AddressDetails"]["Country"]["AdministrativeArea"]\
85
+ ["Locality"]["LocalityName"] rescue nil
86
+ end
87
+
88
+ ##
89
+ # State
90
+ #
91
+ # @return [String] state
92
+ def state
93
+ @state ||= @hash["AddressDetails"]["Country"]["AdministrativeArea"]\
94
+ ["AdministrativeAreaName"] rescue nil
95
+ end
96
+
97
+ ##
98
+ # Zipcode
99
+ #
100
+ # @return [String] zipcode
101
+ def zipcode
102
+ @zipcode ||= @hash["AddressDetails"]["Country"]["AdministrativeArea"]\
103
+ ["Locality"]["PostalCode"]["PostalCodeNumber"] rescue nil
104
+ end
105
+
106
+ ##
107
+ # Country
108
+ #
109
+ # @return [String] country
110
+ def country
111
+ @country ||= @hash["AddressDetails"]["Country"]["CountryNameCode"]\
112
+ rescue nil
113
+ end
114
+
115
+ ##
116
+ # Accuracy
117
+ #
118
+ # Convert Googles Accuracy integer into a word describing how accurate
119
+ # the match is
120
+ #
121
+ # @see accuracy_map
122
+ # @return [String] accuracy
123
+ def accuracy
124
+ @accuracy ||= accuracy_map[@hash["AddressDetails"]["Accuracy"].to_i]\
125
+ rescue nil
126
+ end
127
+
128
+ ##
129
+ # Coordinates
130
+ #
131
+ # An array of coordinates in the form of [lat, lng, elevation]
132
+ #
133
+ # @return [<Array>] lat, lng, elevation
134
+ def coordinates
135
+ @coordinates ||= [lat, lng, elevation]
136
+ end
137
+
138
+ ##
139
+ # Lat
140
+ #
141
+ # @return [Float] latitude
142
+ def lat
143
+ @lat ||= @hash["Point"]["coordinates"][0].to_f rescue nil
144
+ end
145
+
146
+ ##
147
+ # Lng
148
+ #
149
+ # @return [Float] longitude
150
+ def lng
151
+ @lng ||= @hash["Point"]["coordinates"][1].to_f rescue nil
152
+ end
153
+
154
+ ##
155
+ # Elevation
156
+ #
157
+ # @return [Float] elevation
158
+ def elevation
159
+ @elevation ||= @hash["Point"]["coordinates"][2].to_f rescue nil
160
+ end
161
+
162
+ private
163
+
164
+ ##
165
+ # Map Googles code to a user friendly word
166
+ #
167
+ # @return [String]
168
+ def accuracy_map
169
+ %w{ unknown country state county city zip zip+4 street address }
170
+ end
171
+
172
+ end
173
+ end
data/lib/geocoda.rb ADDED
@@ -0,0 +1,46 @@
1
+ require 'patron'
2
+ require 'json'
3
+ module Geocoda
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.3"
21
+ end
22
+
23
+ ##
24
+ # Search for addresses that match a string
25
+ #
26
+ # @see Geocoda::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 Geocoda::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__)), 'geocoda', 'client'
43
+ )
44
+ require File.join(
45
+ File.expand_path(File.dirname(__FILE__)), 'geocoda', 'response'
46
+ )
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: geocoda
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Dusty Doris
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-19 00:00:00.000000000Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: json
16
+ requirement: &70110201151060 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70110201151060
25
+ - !ruby/object:Gem::Dependency
26
+ name: patron
27
+ requirement: &70110201150500 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: *70110201150500
36
+ description:
37
+ email: github@dusty.name
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files:
41
+ - README.txt
42
+ files:
43
+ - README.txt
44
+ - lib/geocoda.rb
45
+ - lib/geocoda/client.rb
46
+ - lib/geocoda/response.rb
47
+ homepage: https://github.com/dusty/geocoda
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project: none
67
+ rubygems_version: 1.8.10
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Interface to Google's Geocoder API
71
+ test_files: []