geosack 1.0
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 +44 -0
- data/lib/geosack.rb +126 -0
- data/test/geosack_test.rb +44 -0
- metadata +54 -0
data/README
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
== Geosack On Rails
|
2
|
+
|
3
|
+
This plugin enables you to utilize geosack.com unique geocode caching service. Geosack provides a persistent api that caches google-map/geocode lookups - enabling you to re-request the same information any number of times you like without exceeding your quota's or rate-limits from google.
|
4
|
+
|
5
|
+
To install the plugin, extract the files from the archive to a directory named "geosack" in your vendors/plugin directory.
|
6
|
+
|
7
|
+
Using the plugin is straightforward:
|
8
|
+
|
9
|
+
To use the geocoding service you will need a google API key, obtained from here:
|
10
|
+
|
11
|
+
http://code.google.com/apis/maps/signup.html
|
12
|
+
|
13
|
+
Once you have this key, you can create your Geosack object:
|
14
|
+
|
15
|
+
geosack = Geosack::Base.new(:api_key => YOUR_API_KEY)
|
16
|
+
|
17
|
+
Then you are free to start making geocode requests.
|
18
|
+
|
19
|
+
result, location = geosack.geo(:q => 'San Jose')
|
20
|
+
|
21
|
+
The placename to be looked is specified by the :q parameter. The only other parameter is :output which is the response format - KML/XML/JSON. The default response format is XML.
|
22
|
+
|
23
|
+
You don't need to worry about the 2 second delay that google requires - geosack takes care of that for you.
|
24
|
+
|
25
|
+
The result object is a reflection of the response returned by google to your request. Anything other than a 200 (G_GEO_SUCCESS) is a failure.
|
26
|
+
|
27
|
+
You will also need to check for 610 (G_GEO_TOO_MANY_QUERIES) responses which indicate you have reached your limit for the 24 period. Note that this limit only applies to new requests sent to google - if you send a request that has already been cached by geosack, the response will come from geosack, not from google, and your daily limit will be unaffected.
|
28
|
+
|
29
|
+
Heres an example to get your started:
|
30
|
+
|
31
|
+
geosack = Geosack::Base.new(:key => API_KEY)
|
32
|
+
result, resp = geosack.geo(:q => lookup)
|
33
|
+
if result == Geosack::StatusCodes::G_GEO_SUCCESS
|
34
|
+
doc = REXML::Document.new(resp)
|
35
|
+
doc.root.each_element('//Response') do |response|
|
36
|
+
response.each_element('//Placemark') do |place|
|
37
|
+
longitude,latitude = place.elements['//coordinates'].text.split(',')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
else
|
41
|
+
# failed
|
42
|
+
end
|
43
|
+
|
44
|
+
Have fun, and feel free to contact us at mailto:info@packetnode.com with any questions or suggestions.
|
data/lib/geosack.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
# Copyright (c) 2008 Philip Mcmahon
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the "Software"), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in
|
11
|
+
# all copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
19
|
+
# THE SOFTWARE.
|
20
|
+
|
21
|
+
module Geosack #:nodoc:
|
22
|
+
|
23
|
+
class GeosackError < StandardError; end #:nodoc
|
24
|
+
|
25
|
+
# Base class
|
26
|
+
class Base
|
27
|
+
|
28
|
+
# Defines the required parameter(s)
|
29
|
+
REQUIRED_OPTIONS = {:base => [:key],
|
30
|
+
:geo => [:q]}
|
31
|
+
|
32
|
+
GEOSACK_URL = 'http://www.geosack.com/maps/geo'
|
33
|
+
STATUS_RESPONSE = '//kml/Response/Status/code'
|
34
|
+
|
35
|
+
attr_accessor :key
|
36
|
+
|
37
|
+
# Initializes the Geosack::Base class
|
38
|
+
#
|
39
|
+
# geosack = Geosack::Base.new(:api_key => 'MY_API_KEY')
|
40
|
+
#
|
41
|
+
# === Required options
|
42
|
+
# :api_key - Your Google geocoding/maps API key
|
43
|
+
def initialize(options = {})
|
44
|
+
check_options(:base, options)
|
45
|
+
@key = CGI.escape(options[:key])
|
46
|
+
end
|
47
|
+
|
48
|
+
# Geocodes an address from Geosack
|
49
|
+
#
|
50
|
+
# > geosack = Geosack::Base.new(:api_key => 'MY_API_KEY')
|
51
|
+
# > result, location = geosack.geo('San Jose')
|
52
|
+
#
|
53
|
+
# > result
|
54
|
+
# 200
|
55
|
+
# > location
|
56
|
+
# ... <kml xmlns='http://earth.google.com/kml/2.0'><Response><name>San Jose</name> ...
|
57
|
+
#
|
58
|
+
# === Required options
|
59
|
+
# :q - The query you wish to submit to Geosack, e.g. 'San Jose'
|
60
|
+
#
|
61
|
+
# === Optional options
|
62
|
+
# :output - The output format you are expecting - see Module Outputs
|
63
|
+
def geo(options = {})
|
64
|
+
|
65
|
+
# Check options
|
66
|
+
check_options(:geo, options)
|
67
|
+
q = CGI.escape(options[:q])
|
68
|
+
output = options[:output] ? CGI.escape(options[:output]) : Outputs::XML
|
69
|
+
|
70
|
+
# first we'll open the url
|
71
|
+
resp = open("#{GEOSACK_URL}?q=#{q}&output=#{output}&key=#{@key}").read
|
72
|
+
|
73
|
+
# then we'll check for the status
|
74
|
+
begin
|
75
|
+
doc = REXML::Document.new(resp)
|
76
|
+
result = doc.elements[STATUS_RESPONSE].text.to_i
|
77
|
+
rescue Exception # bad - too generic
|
78
|
+
if output == Outputs::JSON
|
79
|
+
# :{"code":200,"request":"geocode"}
|
80
|
+
result = resp.scan(/\d+/)[0].to_i
|
81
|
+
puts result
|
82
|
+
else
|
83
|
+
result = StatusCodes::G_GEO_SERVER_ERROR
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
[result, resp]
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# Checks options
|
93
|
+
def check_options(method_name, options = {})
|
94
|
+
required_options = REQUIRED_OPTIONS[method_name]
|
95
|
+
missing = []
|
96
|
+
required_options.each{|option| missing << option if options[option].nil?}
|
97
|
+
|
98
|
+
unless missing.empty?
|
99
|
+
raise GeosackError.new("Missing #{missing.collect{|m| ":#{m}"}.join(', ')}")
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
end # Base
|
104
|
+
|
105
|
+
# Allowed response formats
|
106
|
+
module Outputs
|
107
|
+
XML = "xml"
|
108
|
+
JSON = "json"
|
109
|
+
KML = "kml"
|
110
|
+
end
|
111
|
+
|
112
|
+
# http://code.google.com/apis/maps/documentation/reference.html#GGeoStatusCode
|
113
|
+
module StatusCodes
|
114
|
+
G_GEO_SUCCESS = 200
|
115
|
+
G_GEO_BAD_REQUEST = 400
|
116
|
+
G_GEO_SERVER_ERROR = 500
|
117
|
+
G_GEO_MISSING_QUERY = 601
|
118
|
+
G_GEO_MISSING_ADDRESS = 601
|
119
|
+
G_GEO_UNKNOWN_ADDRESS = 602
|
120
|
+
G_GEO_UNAVAILABLE_ADDRESS = 603
|
121
|
+
G_GEO_UNKNOWN_DIRECTIONS = 604
|
122
|
+
G_GEO_BAD_KEY = 610
|
123
|
+
G_GEO_TOO_MANY_QUERIES = 620
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'geosack'
|
3
|
+
require 'cgi'
|
4
|
+
require 'open-uri'
|
5
|
+
require 'rexml/document'
|
6
|
+
|
7
|
+
class GeosackTest < Test::Unit::TestCase
|
8
|
+
|
9
|
+
# sample google key
|
10
|
+
API_KEY = "ABQIAAAAEMOKUmwrte1WeNNUKp0ckxTlf0blA_rqbbsuTeo2-FuKFlnNphQEGVnMEOB5H-hLCg_bC_vszRN8Yw"
|
11
|
+
INVALID_KEY = "Invalid Key"
|
12
|
+
|
13
|
+
def test_valid_lookup
|
14
|
+
# sample google key
|
15
|
+
latitude, longitude = 0.0, 0.0
|
16
|
+
lookup = "San Jose"
|
17
|
+
geosack = Geosack::Base.new(:key => API_KEY)
|
18
|
+
result, resp = geosack.geo(:q => lookup)
|
19
|
+
assert_equal(Geosack::StatusCodes::G_GEO_SUCCESS, result)
|
20
|
+
doc = REXML::Document.new(resp)
|
21
|
+
doc.root.each_element('//Response') do |response|
|
22
|
+
response.each_element('//Placemark') do |place|
|
23
|
+
longitude,latitude = place.elements['//coordinates'].text.split(',')
|
24
|
+
end
|
25
|
+
end
|
26
|
+
assert_equal(37.316466, latitude.to_f)
|
27
|
+
assert_equal(-121.873881, longitude.to_f)
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_invalid_lookup
|
31
|
+
lookup = "invalid lookup"
|
32
|
+
geosack = Geosack::Base.new(:key => API_KEY)
|
33
|
+
result, resp = geosack.geo(:q => lookup)
|
34
|
+
assert_equal(Geosack::StatusCodes::G_GEO_UNKNOWN_ADDRESS, result)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_invalid_key
|
38
|
+
geosack = Geosack::Base.new(:key => INVALID_KEY)
|
39
|
+
lookup = "San Jose"
|
40
|
+
result, resp = geosack.geo(:q => lookup)
|
41
|
+
assert_equal(Geosack::StatusCodes::G_GEO_BAD_KEY, result)
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: geosack
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: "1.0"
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Philip Mcmahon
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2008-02-17 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies: []
|
15
|
+
|
16
|
+
description:
|
17
|
+
email: info@packetnode.com
|
18
|
+
executables: []
|
19
|
+
|
20
|
+
extensions: []
|
21
|
+
|
22
|
+
extra_rdoc_files:
|
23
|
+
- README
|
24
|
+
files:
|
25
|
+
- lib/geosack.rb
|
26
|
+
- README
|
27
|
+
has_rdoc: true
|
28
|
+
homepage: http://geosack.com
|
29
|
+
post_install_message:
|
30
|
+
rdoc_options: []
|
31
|
+
|
32
|
+
require_paths:
|
33
|
+
- lib
|
34
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
35
|
+
requirements:
|
36
|
+
- - ">="
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: "0"
|
39
|
+
version:
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
requirements: []
|
47
|
+
|
48
|
+
rubyforge_project: geosack_plugin
|
49
|
+
rubygems_version: 1.0.1
|
50
|
+
signing_key:
|
51
|
+
specification_version: 2
|
52
|
+
summary: This ruby on rails plugin enables you to utilize the geosack.com unique geocode caching service, which provides a persistent api that caches your google-map/geocode lookups.
|
53
|
+
test_files:
|
54
|
+
- test/geosack_test.rb
|