geocoda 0.0.1

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 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: []