steflewandowski-geoapi 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +21 -0
- data/README +156 -0
- data/geoapi.gemspec +36 -0
- data/lib/geoapi/client.rb +32 -0
- data/lib/geoapi/entity.rb +308 -0
- data/lib/geoapi/entry.rb +12 -0
- data/lib/geoapi/geo_object.rb +126 -0
- data/lib/geoapi/geometry.rb +138 -0
- data/lib/geoapi/neighborhood.rb +17 -0
- data/lib/geoapi/query.rb +61 -0
- data/lib/geoapi/user_view.rb +11 -0
- data/lib/geoapi/version.rb +8 -0
- data/lib/geoapi/view.rb +100 -0
- data/lib/geoapi.rb +89 -0
- metadata +109 -0
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2009 Chris Bruce
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
= OVERVIEW
|
2
|
+
|
3
|
+
Unfortunately I've decided to 'fail fast' and am giving up on developing this gem:
|
4
|
+
The API isn't yet reliable enough to be able to develop with it - I'm consistently seeing the following:
|
5
|
+
|
6
|
+
* 504 bad gateway
|
7
|
+
* Connections that remain open
|
8
|
+
* Every other request giving a response, others just time out
|
9
|
+
* Search for user-entities doesn't appear to function (the reason for the app I am working on)
|
10
|
+
|
11
|
+
Sorry - if anyone wants to pick up where I left off, feel free.
|
12
|
+
|
13
|
+
|
14
|
+
|
15
|
+
== Code examples:
|
16
|
+
|
17
|
+
=== Setting the API KEY
|
18
|
+
|
19
|
+
There are three methods for setting the apikey variable which must be sent with all requests. They are:
|
20
|
+
|
21
|
+
Defining it. Easiest: sets the API Key for use globally. Use this method unless you need multiple API Keys:
|
22
|
+
|
23
|
+
GEOAPI_KEY = "<my-apikey>"
|
24
|
+
|
25
|
+
For Rails, put this in environment.rb
|
26
|
+
|
27
|
+
Using an Environment variable in your shell.
|
28
|
+
|
29
|
+
ENV["GEOAPI_KEY"] = <my-apikey>
|
30
|
+
|
31
|
+
Using a 'Client' so you can use more than one API Key per application:
|
32
|
+
|
33
|
+
@client = GeoAPI::Client.new("<my-apikey>")
|
34
|
+
@entity = GeoAPI::Entity.find_by_id('12345', :client=>@client)
|
35
|
+
|
36
|
+
@other_client = GeoAPI::Client.new("<my-other-apikey>")
|
37
|
+
@other_entity = GeoAPI::Entity.find_by_id('abcde', :client=>@other_client)
|
38
|
+
|
39
|
+
You can also send :apikey=>"<my-apikey>" in options for Entity methods:
|
40
|
+
|
41
|
+
@entity = GeoAPI::Entity.find_by_id('12345', :apikey=>"<my-apikey>")
|
42
|
+
|
43
|
+
=== Creating new Entities
|
44
|
+
|
45
|
+
@entity = Entity.create_at_lat_lng(:id=>"moseley",:name=>"Moseley", :lat=>52.446506, :lng=>1.888213)
|
46
|
+
|
47
|
+
Creates a new Entity object at the given latitude/longitude point.
|
48
|
+
|
49
|
+
Other ways of creating entities are not yet supported, but there are Polygon and Multipoint models which need building.
|
50
|
+
|
51
|
+
== Finding Entities
|
52
|
+
|
53
|
+
Entity.search(options)
|
54
|
+
Performs and Entity search on the API. Takes a hash of options as documented on GeoAPI.com
|
55
|
+
|
56
|
+
Entity.find(options)
|
57
|
+
Finds a specific entity - you must pass :guid or :id
|
58
|
+
|
59
|
+
== Standard CRUD methods
|
60
|
+
|
61
|
+
Entity.create_at_lat_lng(:id=>"moseley",:name=>"Moseley", :lat=>52.446506, :lng=>1.888213)
|
62
|
+
The easiest way to create a new User Entity - requires an ID and a name.
|
63
|
+
|
64
|
+
Entity.find_by_id("moseley")
|
65
|
+
Gets an entity and returns the result.
|
66
|
+
|
67
|
+
Entity.find_by_guid("user-abc123-moseley")
|
68
|
+
An ID is useful for your application, but its actual GUID can also be used to retrieve it.
|
69
|
+
|
70
|
+
Entity.delete({:id=>"moseley"}) and
|
71
|
+
@entity.delete
|
72
|
+
Destroys an entity, either via guid or id.
|
73
|
+
|
74
|
+
@entity.update
|
75
|
+
|
76
|
+
== Eager loading and caching
|
77
|
+
|
78
|
+
This gem does _not_ eager load all results of a search, nor does it cache them, In order to use an item retrieved from a request, you must first load it. Eg.:
|
79
|
+
|
80
|
+
@entities = Entity.find(options)
|
81
|
+
|
82
|
+
@entities.each do |e|
|
83
|
+
e.load
|
84
|
+
puts "#{e.name} is at #{e.lat},#{e.lng}"
|
85
|
+
end
|
86
|
+
|
87
|
+
=== Automatically generated accessor functions for all Views and UserViews
|
88
|
+
|
89
|
+
@entity.twitter_view
|
90
|
+
@entity.twitter_view_entries
|
91
|
+
|
92
|
+
@entity.flickr_view
|
93
|
+
@entity.flickr_view_entries
|
94
|
+
@entity.<my_application>_view_entries
|
95
|
+
|
96
|
+
|
97
|
+
= NOTE
|
98
|
+
|
99
|
+
This is still actively being developed and is very alpha. You can currently conduct a simple search and an MQL query. The results are returned as ruby hash.
|
100
|
+
|
101
|
+
== TODO
|
102
|
+
|
103
|
+
- Allow updates to views.
|
104
|
+
|
105
|
+
|
106
|
+
= GeoAPI
|
107
|
+
|
108
|
+
A Ruby wrapper for the GeoAPI.com APIs. This gem was almost entirely inspired by the various geoplanet gems.
|
109
|
+
|
110
|
+
== Usage
|
111
|
+
|
112
|
+
=== Reverse Geocoding:
|
113
|
+
|
114
|
+
require 'geoapi'
|
115
|
+
GeoAPI.apikey = [Your App ID Here]
|
116
|
+
|
117
|
+
# Location
|
118
|
+
latitude = -27.000
|
119
|
+
longitude = -131.000
|
120
|
+
|
121
|
+
# Non Required Options
|
122
|
+
optional_parameters = {:radius => '500m', :type => 'POI', "include-parents" => true, :limit => 5, :pretty => true}
|
123
|
+
|
124
|
+
# Simple Search
|
125
|
+
result = GeoAPI::Query.simple_search(latitude, longitude, optional_parameters)
|
126
|
+
|
127
|
+
# MQL Query
|
128
|
+
q = {:lat => 37.75629, :lon => -122.4213, :radius => "1km", :entity => [{:type => "business", :guid => nil}]}
|
129
|
+
results = GeoAPI::Query.query(q)
|
130
|
+
|
131
|
+
|
132
|
+
|
133
|
+
== REQUIREMENTS:
|
134
|
+
|
135
|
+
To use this library, you must have a valid GeoAPI.com API Key.
|
136
|
+
You can get one at http://api.geoapi.com
|
137
|
+
|
138
|
+
Additionally, geoapi has the following gem dependencies:
|
139
|
+
|
140
|
+
* rest-client >= 0.9
|
141
|
+
* json >= 1.1.3
|
142
|
+
|
143
|
+
Please note that if you have ActiveSupport::JSON defined (either by
|
144
|
+
manually having loaded it or when you use geoapi within a Rails
|
145
|
+
application) the json dependency will be ignored and geoapi uses
|
146
|
+
ActiveSupport::JSON instead.
|
147
|
+
|
148
|
+
== INSTALL:
|
149
|
+
|
150
|
+
This gem is hosted on Gemcutter. To install gemcutter:
|
151
|
+
gem install gemcutter
|
152
|
+
gem tumble
|
153
|
+
|
154
|
+
To install geoapi after gemcutter:
|
155
|
+
gem install geoapi
|
156
|
+
|
data/geoapi.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
Gem::Specification.new do |s|
|
2
|
+
s.name = "steflewandowski-geoapi"
|
3
|
+
s.version = "0.2.1"
|
4
|
+
s.date = "2009-11-10"
|
5
|
+
s.summary = "A Ruby wrapper for the GeoAPI.com API."
|
6
|
+
s.email = "stef@stef.io"
|
7
|
+
s.homepage = "http://github.com/steflewandowski/GeoAPI/"
|
8
|
+
s.description = "A Ruby wrapper for the GeoAPI.com API based on the work of Chris Bruce. See http://api.geoapi.com for more information about the API."
|
9
|
+
s.authors = ["Stef Lewandowski","Chris Bruce"]
|
10
|
+
|
11
|
+
s.files = [
|
12
|
+
"README",
|
13
|
+
"LICENSE",
|
14
|
+
"geoapi.gemspec",
|
15
|
+
"lib/geoapi.rb",
|
16
|
+
"lib/geoapi/geo_object.rb",
|
17
|
+
"lib/geoapi/geometry.rb",
|
18
|
+
"lib/geoapi/query.rb",
|
19
|
+
"lib/geoapi/entity.rb",
|
20
|
+
"lib/geoapi/entry.rb",
|
21
|
+
"lib/geoapi/view.rb",
|
22
|
+
"lib/geoapi/user_view.rb",
|
23
|
+
"lib/geoapi/version.rb",
|
24
|
+
"lib/geoapi/client",
|
25
|
+
"lib/geoapi/neighborhood"
|
26
|
+
]
|
27
|
+
|
28
|
+
s.add_dependency("rest-client", [">= 0.9"])
|
29
|
+
s.add_dependency("crack")
|
30
|
+
s.add_dependency("httparty")
|
31
|
+
s.add_dependency("uuidtools")
|
32
|
+
|
33
|
+
|
34
|
+
s.has_rdoc = false
|
35
|
+
s.rdoc_options = ["--main", "README.rdoc"]
|
36
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module GeoAPI
|
2
|
+
class Client
|
3
|
+
|
4
|
+
# To connect to GeoAPI, either:
|
5
|
+
#
|
6
|
+
# Add export GEOAPI_KEY=<your-api-key> in your .bashrc file
|
7
|
+
#
|
8
|
+
# @client = GeoAPI::Client.new
|
9
|
+
#
|
10
|
+
# OR
|
11
|
+
#
|
12
|
+
# @client = GeoAPI::Client.new('<your-api-key>')
|
13
|
+
#
|
14
|
+
# OR set GEOAPI_KEY='<your-api-key>' before including GeoAPI
|
15
|
+
#
|
16
|
+
# @client = GeoAPI::Client.new
|
17
|
+
|
18
|
+
def initialize(api_key=nil)
|
19
|
+
@api_key = api_key || ENV['GEOAPI_KEY'] || GeoAPI::GEOAPI_KEY
|
20
|
+
end
|
21
|
+
|
22
|
+
def api_key
|
23
|
+
@api_key
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.id_from_guid(guid,apikey)
|
27
|
+
id = guid.sub('user-','')
|
28
|
+
id = id.sub("#{apikey}-",'')
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,308 @@
|
|
1
|
+
module GeoAPI
|
2
|
+
class Entity < GeoAPI::GeoObject
|
3
|
+
|
4
|
+
attr_accessor :guid, :id, :name, :entity_type, :geom, :url, :views, :userviews, :raw_json, :errors, :shorturl, :raw_json
|
5
|
+
|
6
|
+
|
7
|
+
alias_method :geometry, :geom
|
8
|
+
|
9
|
+
def latitude
|
10
|
+
@latitude ||= geometry.latitude unless geometry.blank?
|
11
|
+
end
|
12
|
+
|
13
|
+
def longitude
|
14
|
+
@longitude ||= geometry.longitude unless geometry.blank?
|
15
|
+
end
|
16
|
+
|
17
|
+
alias_method :lat, :latitude
|
18
|
+
alias_method :lon, :longitude
|
19
|
+
alias_method :lng, :longitude
|
20
|
+
|
21
|
+
# Class methods
|
22
|
+
|
23
|
+
|
24
|
+
def self.create(params)
|
25
|
+
puts "GEOAPI::Entity.create #{params.to_json}"
|
26
|
+
#required: name, geom
|
27
|
+
#optional: pass id and it will create a new guid for you as user-<apikey>-<id>
|
28
|
+
|
29
|
+
raise ArgumentError, "A name is required (pass :name in parameters)" unless params.has_key?(:name)
|
30
|
+
raise ArgumentError, "A geometry is required (pass :geom in parameters)" unless params.has_key?(:geom)
|
31
|
+
|
32
|
+
api_key = self.api_key_from_parameters(params)
|
33
|
+
|
34
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
35
|
+
|
36
|
+
id = params[:id] || UUIDTools::UUID.timestamp_create().to_s
|
37
|
+
|
38
|
+
post_url = "/e"
|
39
|
+
post_url = "/e/user-#{api_key}-#{id}?apikey=#{api_key}" unless id.blank?
|
40
|
+
post_url = "/e/#{params[:guid]}?apikey=#{api_key}" unless params[:guid].blank?
|
41
|
+
|
42
|
+
puts post_url
|
43
|
+
|
44
|
+
params.delete(:id) if params.has_key?(:id)
|
45
|
+
params.delete(:guid) if params.has_key?(:guid)
|
46
|
+
|
47
|
+
begin
|
48
|
+
results = Entity.post(post_url, {:body=> params.to_json})
|
49
|
+
rescue
|
50
|
+
raise BadRequest, "There was a problem communicating with the API"
|
51
|
+
end
|
52
|
+
|
53
|
+
raise BadRequest, results['error'] unless results['error'].blank?
|
54
|
+
|
55
|
+
#todo the result does not contain the guid, so merge it back in. Possible point of failure here?
|
56
|
+
|
57
|
+
guid = results['query']['params']['guid']
|
58
|
+
Entity.new(results['result'].merge({'guid'=>guid, 'id'=>GeoAPI::Client.id_from_guid(guid,api_key)}))
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.destroy(params)
|
62
|
+
|
63
|
+
puts "GEOAPI::Entity.destroy #{params.to_json}"
|
64
|
+
|
65
|
+
raise ArgumentError, "An id or guid is required (pass :id or :guid in parameters)" unless params.has_key?(:id) || params.has_key?(:guid)
|
66
|
+
|
67
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
68
|
+
|
69
|
+
begin
|
70
|
+
unless params[:guid].blank?
|
71
|
+
delete("/e/#{params[:guid]}?apikey=#{api_key}")
|
72
|
+
else
|
73
|
+
delete("/e/user-#{api_key}-#{params[:id]}?apikey=#{api_key}") unless params[:id].blank?
|
74
|
+
end
|
75
|
+
|
76
|
+
rescue
|
77
|
+
raise BadRequest, "There was a problem communicating with the API"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.create_at_lat_lng(*args)
|
82
|
+
|
83
|
+
params = args.extract_options!
|
84
|
+
params = params == {} ? nil : params
|
85
|
+
|
86
|
+
puts "GEOAPI::Entity.create_at_lat_lng #{params.to_json}"
|
87
|
+
|
88
|
+
raise ArgumentError, ":lat must be sent as a parameter" unless params.has_key?(:lat)
|
89
|
+
raise ArgumentError, ":lng must be sent as a parameter" unless params.has_key?(:lng)
|
90
|
+
puts "test API key #{api_key}"
|
91
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
92
|
+
|
93
|
+
p = GeoAPI::Point.new(:lat => params[:lat],:lng => params[:lng])
|
94
|
+
|
95
|
+
params.delete(:lat)
|
96
|
+
params.delete(:lng)
|
97
|
+
|
98
|
+
self.create(params.merge({:geom=>p}))
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.find(*args)
|
102
|
+
|
103
|
+
puts "GEOAPI::Entity.find #{args.to_s}"
|
104
|
+
|
105
|
+
raise ArgumentError, "First argument must be symbol (:all or :get)" unless args.first.kind_of?(Symbol)
|
106
|
+
|
107
|
+
params = args.extract_options!
|
108
|
+
params = params == {} ? nil : params
|
109
|
+
|
110
|
+
api_key = self.api_key_from_parameters(params)
|
111
|
+
|
112
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
113
|
+
|
114
|
+
case args.first
|
115
|
+
|
116
|
+
when :all
|
117
|
+
results = []
|
118
|
+
else
|
119
|
+
results = nil
|
120
|
+
|
121
|
+
raise ArgumentError, "Arguments should include a :guid or :id" if params[:guid].blank? && params[:id].blank?
|
122
|
+
|
123
|
+
params[:guid] = "user-#{api_key}-#{the_id}" unless params[:id].blank?
|
124
|
+
|
125
|
+
response = get("/e/#{params[:guid]}?apikey=#{api_key}")
|
126
|
+
|
127
|
+
begin
|
128
|
+
|
129
|
+
rescue
|
130
|
+
raise BadRequest, "There was a problem communicating with the API"
|
131
|
+
end
|
132
|
+
|
133
|
+
results = Entity.new(response['result'].merge({'guid'=>params[:guid]})) unless response['result'].blank? #the api doesn't return a guid in json?!
|
134
|
+
end
|
135
|
+
|
136
|
+
results
|
137
|
+
|
138
|
+
end
|
139
|
+
|
140
|
+
def self.find_by_id(the_id, options={})
|
141
|
+
puts "GEOAPI::Entity.find_by_id #{the_id}"
|
142
|
+
|
143
|
+
api_key = self.api_key_from_parameters(options)
|
144
|
+
|
145
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
146
|
+
|
147
|
+
self.find(:get, :guid=>"user-#{api_key}-#{the_id}")
|
148
|
+
end
|
149
|
+
|
150
|
+
def self.find_by_guid(the_guid, options={})
|
151
|
+
puts "GEOAPI::Entity.find_by_guid #{the_guid}"
|
152
|
+
|
153
|
+
api_key = self.api_key_from_parameters(options)
|
154
|
+
|
155
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
156
|
+
|
157
|
+
self.find(:get, :guid=>the_guid)
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
# Instance methods
|
162
|
+
def initialize(attrs)
|
163
|
+
super attrs
|
164
|
+
self.setup(attrs) unless attrs.blank?
|
165
|
+
end
|
166
|
+
|
167
|
+
def setup(attrs)
|
168
|
+
puts "Setup Entity with attributes: #{attrs.to_json}"
|
169
|
+
api_key = @api_key
|
170
|
+
api_key ||= self.api_key_from_parameters(params)
|
171
|
+
|
172
|
+
self.guid = attrs['guid'] if attrs.has_key?('guid')
|
173
|
+
self.guid = "user-#{@api_key}-#{attrs['id']}" if attrs.has_key?('id')
|
174
|
+
puts "GEOAPI::Entity.setup #{self.guid}"
|
175
|
+
self.id = attrs['id'] if attrs.has_key?('id')
|
176
|
+
self.id = GeoAPI::Client.id_from_guid(self.guid,api_key) if self.id.blank?
|
177
|
+
self.errors = attrs['error']
|
178
|
+
self.name = attrs['name']
|
179
|
+
self.name ||= attrs['meta']['name'] unless attrs['meta'].blank?
|
180
|
+
self.entity_type = attrs['type']
|
181
|
+
self.shorturl = attrs['shorturl']
|
182
|
+
|
183
|
+
self.geom = GeoAPI::Geometry.from_hash(attrs['geom']) unless attrs['geom'].blank?
|
184
|
+
self.geom ||= GeoAPI::Geometry.from_hash(attrs['meta']['geom']) unless attrs['meta'].blank?
|
185
|
+
|
186
|
+
|
187
|
+
self.views = []
|
188
|
+
unless attrs['views'].blank?
|
189
|
+
if attrs['views'].size > 0
|
190
|
+
attrs['views'].each do |view|
|
191
|
+
self.views << GeoAPI::View.new({'name'=>view, 'guid'=>self.guid})
|
192
|
+
|
193
|
+
# Dynamically create methods like twitter_view
|
194
|
+
|
195
|
+
(class <<self; self; end).send :define_method, :"#{view}_view" do
|
196
|
+
find_view("#{view}")
|
197
|
+
end
|
198
|
+
|
199
|
+
(class <<self; self; end).send :define_method, :"#{view}_view_entries" do
|
200
|
+
find_view_entries("#{view}")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
self.userviews = []
|
207
|
+
unless attrs['userviews'].blank?
|
208
|
+
if attrs['userviews'].size > 0
|
209
|
+
attrs['userviews'].each do |view|
|
210
|
+
self.userviews << GeoAPI::UserView.new({'name'=>view, 'guid'=>self.guid})
|
211
|
+
|
212
|
+
# Dynamically create methods like myapp_userview
|
213
|
+
class << self
|
214
|
+
define_method "#{view}_userview" do
|
215
|
+
find_view("#{view}")
|
216
|
+
end
|
217
|
+
|
218
|
+
define_method :"#{view}_entries" do
|
219
|
+
#todo needs caching here
|
220
|
+
find_view("#{view}").entries
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
self
|
229
|
+
|
230
|
+
end
|
231
|
+
|
232
|
+
def type #type is a reserved word
|
233
|
+
self.entity_type
|
234
|
+
end
|
235
|
+
|
236
|
+
def update
|
237
|
+
puts "GEOAPI::Entity.update #{self.guid}"
|
238
|
+
|
239
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
240
|
+
|
241
|
+
self.setup(post("/e/#{guid}?apikey=#{api_key}", {:body=>self.to_json}))
|
242
|
+
end
|
243
|
+
|
244
|
+
def load
|
245
|
+
puts "GEOAPI::Entity.load #{self.guid}"
|
246
|
+
|
247
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
248
|
+
|
249
|
+
raise ArgumentError, "Properties should include a .guid or .id" if self.guid.blank? && self.id.blank?
|
250
|
+
|
251
|
+
the_guid = self.guid
|
252
|
+
the_guid ||= "user-#{api_key}-#{self.id}"
|
253
|
+
|
254
|
+
begin
|
255
|
+
response = self.class.get("/e/#{the_guid}?apikey=#{api_key}")
|
256
|
+
rescue
|
257
|
+
raise BadRequest, "There was a problem communicating with the API"
|
258
|
+
end
|
259
|
+
|
260
|
+
self.setup(response['result'].merge({'guid'=>self.guid }))
|
261
|
+
|
262
|
+
self
|
263
|
+
end
|
264
|
+
|
265
|
+
def delete
|
266
|
+
puts "GEOAPI::Entity.delete #{self.guid}"
|
267
|
+
|
268
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
269
|
+
|
270
|
+
raise ArgumentError, "Object has no :guid" if self.guid.blank?
|
271
|
+
begin
|
272
|
+
Entity.destroy(:guid=>self.guid)
|
273
|
+
rescue
|
274
|
+
raise BadRequest, "There was a problem communicating with the API"
|
275
|
+
end
|
276
|
+
|
277
|
+
end
|
278
|
+
|
279
|
+
def destroy
|
280
|
+
self.delete
|
281
|
+
end
|
282
|
+
|
283
|
+
def save
|
284
|
+
update
|
285
|
+
end
|
286
|
+
|
287
|
+
def to_s
|
288
|
+
self.name
|
289
|
+
end
|
290
|
+
|
291
|
+
def to_json options=nil
|
292
|
+
{:name=>name, :guid=>guid, :type=>entity_type, :geom=>geom, :views=>views, :userviews=>userviews, :shorturl=>shorturl}.to_json
|
293
|
+
end
|
294
|
+
|
295
|
+
# Common facility methods
|
296
|
+
|
297
|
+
def find_view view_name
|
298
|
+
views.each do |view|
|
299
|
+
return view if view.name == view_name
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def find_view_entries view_name
|
304
|
+
find_view(view_name).load.entries
|
305
|
+
end
|
306
|
+
|
307
|
+
end
|
308
|
+
end
|
data/lib/geoapi/entry.rb
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
module GeoAPI
|
2
|
+
class GeoObject
|
3
|
+
|
4
|
+
include HTTParty
|
5
|
+
|
6
|
+
format :json
|
7
|
+
|
8
|
+
class << self
|
9
|
+
attr_accessor :api_key
|
10
|
+
end
|
11
|
+
|
12
|
+
#default_params Proc.new { :apikey => api_key} }
|
13
|
+
|
14
|
+
base_uri GeoAPI::API_URL
|
15
|
+
|
16
|
+
# Allow users to set the API key explicitly, or gain it from other sources.
|
17
|
+
# Makes for more readable code, and allows multiple keys to be used in the one application.
|
18
|
+
|
19
|
+
def initialize(attrs)
|
20
|
+
#raise ArgumentError, "A :client must be passed to when creating a GeoObject, unless unless ENV['GEOAPI_KEY'] or is set"
|
21
|
+
|
22
|
+
@api_key = self.class.api_key_from_parameters(attrs)
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.api_key
|
27
|
+
@api_key ||= GeoAPI::GEOAPI_KEY
|
28
|
+
@api_key ||= ENV["GEOAPI_KEY"]
|
29
|
+
puts "API KEY: #{@api_key}"
|
30
|
+
@api_key
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.api_key_from_parameters(attrs)
|
34
|
+
unless attrs.blank?
|
35
|
+
the_api_key = attrs[:client].api_key if attrs.has_key?(:client)
|
36
|
+
the_api_key ||= attrs[:apikey] if attrs.has_key?(:apikey)
|
37
|
+
the_api_key ||= attrs[:api_key] if attrs.has_key?(:api_key)
|
38
|
+
the_api_key ||= attrs[:api_key] if attrs.has_key?(:api_key)
|
39
|
+
end
|
40
|
+
the_api_key ||= self.api_key
|
41
|
+
puts "API Key from parameters: #{the_api_key}"
|
42
|
+
@api_key = the_api_key
|
43
|
+
the_api_key
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.post path, options={}
|
47
|
+
puts "Post: #{path} : #{options.to_s}"
|
48
|
+
timeout = options[:timeout] || 5
|
49
|
+
options.delete(:timeout)
|
50
|
+
retryable( :tries => 2 ) do
|
51
|
+
Timeout::timeout(timeout) do |t|
|
52
|
+
super path, options
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.get path, options={}
|
58
|
+
puts "Get: #{path} : #{options.to_s}"
|
59
|
+
timeout = options[:timeout] || 5
|
60
|
+
options.delete(:timeout)
|
61
|
+
puts options.to_s
|
62
|
+
puts "Timeout #{timeout}"
|
63
|
+
retryable( :tries => 2 ) do
|
64
|
+
Timeout::timeout(timeout) do |t|
|
65
|
+
super path, options
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.delete path, options={}
|
71
|
+
puts "Delete: #{path} : #{options.to_s}"
|
72
|
+
timeout = options[:timeout] || 5
|
73
|
+
options.delete(:timeout)
|
74
|
+
retryable( :tries => 2 ) do
|
75
|
+
Timeout::timeout(timeout) do |t|
|
76
|
+
super path, options
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.search(conditions, options={})
|
82
|
+
puts "GEOAPI::Entity.search #{conditions.to_s}"
|
83
|
+
|
84
|
+
raise ArgumentError, ":lat and :lng are required for search" unless conditions.has_key?(:lat) && conditions.has_key?(:lng)
|
85
|
+
|
86
|
+
api_key = self.api_key_from_parameters(options)
|
87
|
+
|
88
|
+
raise ArgumentError, "An API Key is required" if api_key.blank?
|
89
|
+
|
90
|
+
# Accepts all conditions from the API and passes them through - http://docs.geoapi.com/Simple-Search
|
91
|
+
|
92
|
+
conditions.merge!({:lat=>conditions[:lat],:lon=>conditions[:lng],:apikey=>api_key})
|
93
|
+
conditions.delete(:lng)
|
94
|
+
|
95
|
+
response = get("/search", {:timeout=>60, :query=>conditions})
|
96
|
+
|
97
|
+
begin
|
98
|
+
|
99
|
+
rescue
|
100
|
+
raise BadRequest, "There was a problem communicating with the API"
|
101
|
+
end
|
102
|
+
|
103
|
+
results = []
|
104
|
+
unless response['result'].blank?
|
105
|
+
response['result'].each do |result|
|
106
|
+
results << self.new(result)
|
107
|
+
end
|
108
|
+
results.reverse!
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def self.find params
|
113
|
+
# Find a given object by location passed as :lat, :lng
|
114
|
+
raise ArgumentError, ":lat must be sent as a parameter" unless params.has_key?(:lat)
|
115
|
+
raise ArgumentError, ":lng must be sent as a parameter" unless params.has_key?(:lng)
|
116
|
+
|
117
|
+
self.search({:lat=>params[:lat], :lng=>params[:lng],:type=>self.entity_type})
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.entity_type
|
121
|
+
"user-entity"
|
122
|
+
end
|
123
|
+
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module GeoAPI
|
2
|
+
class Geometry
|
3
|
+
|
4
|
+
class << self
|
5
|
+
attr_accessor :coords, :geometry_type
|
6
|
+
end
|
7
|
+
|
8
|
+
|
9
|
+
# Class methods
|
10
|
+
|
11
|
+
def self.new_from_class_name class_name
|
12
|
+
geom = case class_name.downcase.gsub('_','')
|
13
|
+
|
14
|
+
when "point" then GeoAPI::Point.new
|
15
|
+
|
16
|
+
when "polygon" then GeoAPI::Polygon.new
|
17
|
+
|
18
|
+
when "multipoint" then GeoAPI::Polygon.new
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.from_json json
|
25
|
+
unless json.blank?
|
26
|
+
attrs = Crack::JSON.parse(json)
|
27
|
+
|
28
|
+
geom = Geometry.new_from_class_name json['type']
|
29
|
+
|
30
|
+
unless geom.blank?
|
31
|
+
|
32
|
+
geom.geometry_type = attrs['type']
|
33
|
+
|
34
|
+
geom.coords = attrs['coordinates']
|
35
|
+
|
36
|
+
geom
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.from_hash hash
|
43
|
+
|
44
|
+
unless hash.blank?
|
45
|
+
geom = Geometry.new_from_class_name hash['type']
|
46
|
+
|
47
|
+
unless geom.blank?
|
48
|
+
|
49
|
+
geom.geometry_type = hash['type']
|
50
|
+
|
51
|
+
geom.coords = hash['coordinates']
|
52
|
+
|
53
|
+
puts "Got geometry: #{geom}"
|
54
|
+
|
55
|
+
geom
|
56
|
+
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# Instance methods
|
63
|
+
|
64
|
+
def coordinates
|
65
|
+
coords
|
66
|
+
end
|
67
|
+
|
68
|
+
def type
|
69
|
+
geometry_type
|
70
|
+
end
|
71
|
+
|
72
|
+
def to_json options=nil
|
73
|
+
{:type=>self.geometry_type, :coordinates=>self.coords}.to_json
|
74
|
+
end
|
75
|
+
|
76
|
+
def initialize attrs
|
77
|
+
@geometry_type = self.class.name.split('::').last
|
78
|
+
end
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
class Point < GeoAPI::Geometry
|
83
|
+
|
84
|
+
attr_accessor :geometry_type, :coords
|
85
|
+
|
86
|
+
def latitude
|
87
|
+
coords[0]
|
88
|
+
end
|
89
|
+
|
90
|
+
def longitude
|
91
|
+
coords[1]
|
92
|
+
end
|
93
|
+
|
94
|
+
def initialize *args
|
95
|
+
|
96
|
+
params = args.extract_options!
|
97
|
+
params = params == {} ? nil : params
|
98
|
+
|
99
|
+
puts "GEOAPI::Point.new #{params.to_json}"
|
100
|
+
|
101
|
+
#raise ArgumentError, ":lat (latitude) must be sent as a parameter to the GeoAPI::Point constructor" unless params.has_key?(:lat)
|
102
|
+
#raise ArgumentError, ":lng (longitude) must be sent as a parameter to the GeoAPI::Point constructor" unless params.has_key?(:lng)
|
103
|
+
|
104
|
+
self.coords = [params[:lng].to_f, params[:lat].to_f] unless params.blank? || params[:lat].blank?
|
105
|
+
super args
|
106
|
+
end
|
107
|
+
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
class Multipoint < GeoAPI::Geometry
|
112
|
+
|
113
|
+
attr_accessor :geometry_type, :coords
|
114
|
+
|
115
|
+
def initialize attrs
|
116
|
+
|
117
|
+
self.coords = []
|
118
|
+
super attrs
|
119
|
+
end
|
120
|
+
|
121
|
+
|
122
|
+
end
|
123
|
+
|
124
|
+
class Polygon < GeoAPI::Geometry
|
125
|
+
|
126
|
+
attr_accessor :geometry_type, :coords
|
127
|
+
|
128
|
+
def initialize attrs
|
129
|
+
self.coords = []
|
130
|
+
super attrs
|
131
|
+
end
|
132
|
+
|
133
|
+
|
134
|
+
end
|
135
|
+
|
136
|
+
#todo add additional classes
|
137
|
+
|
138
|
+
end
|
data/lib/geoapi/query.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
module GeoAPI
|
2
|
+
class Query
|
3
|
+
|
4
|
+
class << self
|
5
|
+
# Uses GeoAPI's simple search method
|
6
|
+
def simple_search(lat, lon, options = {})
|
7
|
+
options[:lat] = lat
|
8
|
+
options[:lon] = lon
|
9
|
+
url = build_url('search', options)
|
10
|
+
get_then_parse(url)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Uses GeoAPI's MQL query method
|
14
|
+
def query(query)
|
15
|
+
q = JSON.generate(query)
|
16
|
+
url = build_url('q', {:q => URI.escape(q)})
|
17
|
+
get_then_parse(url)
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def get_then_parse(url)
|
22
|
+
JSON.parse(get(url))
|
23
|
+
end
|
24
|
+
|
25
|
+
def build_url(resource_path, options = {})
|
26
|
+
|
27
|
+
options[:apikey] ||= GeoAPI.apikey
|
28
|
+
query_string = build_query_params(options)
|
29
|
+
|
30
|
+
"#{GeoAPI::API_URL}#{resource_path}#{query_string}"
|
31
|
+
end
|
32
|
+
|
33
|
+
def get(url)
|
34
|
+
RestClient.get(url)
|
35
|
+
rescue RestClient::RequestFailed
|
36
|
+
raise BadRequest, "Parameter invalid"
|
37
|
+
rescue RestClient::ResourceNotFound
|
38
|
+
raise NotFound, "GUID invalid"
|
39
|
+
end
|
40
|
+
|
41
|
+
protected
|
42
|
+
|
43
|
+
# Take options and build query string
|
44
|
+
def build_query_params(options)
|
45
|
+
query = {}
|
46
|
+
|
47
|
+
#convert True/False
|
48
|
+
options.each_pair do |key, value|
|
49
|
+
new_key = key.to_s
|
50
|
+
new_val = case value
|
51
|
+
when TrueClass then 1
|
52
|
+
when FalseClass then 0
|
53
|
+
else value
|
54
|
+
end
|
55
|
+
query[new_key] = new_val
|
56
|
+
end
|
57
|
+
"?" + query.map{|k,v| "#{k}=#{v}"}.join('&')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
data/lib/geoapi/view.rb
ADDED
@@ -0,0 +1,100 @@
|
|
1
|
+
module GeoAPI
|
2
|
+
class View < GeoAPI::GeoObject
|
3
|
+
|
4
|
+
attr_accessor :name, :guid, :view_type, :id, :entries
|
5
|
+
|
6
|
+
class << self
|
7
|
+
attr_accessor :path_prefix
|
8
|
+
end
|
9
|
+
|
10
|
+
GeoAPI::VIEW_PATH_PREFIX = "view"
|
11
|
+
GeoAPI::USERVIEW_PATH_PREFIX = "userview"
|
12
|
+
|
13
|
+
|
14
|
+
# Class methods
|
15
|
+
|
16
|
+
def self.path_prefix
|
17
|
+
case self.to_s
|
18
|
+
when "GeoAPI::View" then VIEW_PATH_PREFIX
|
19
|
+
|
20
|
+
when "GeoAPI::UserView" then USERVIEW_PATH_PREFIX
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.find(*args)
|
25
|
+
|
26
|
+
#raise ArgumentError, "First argument must be symbol (:all or :get)" unless args.first.kind_of?(Symbol)
|
27
|
+
|
28
|
+
params = args.extract_options!
|
29
|
+
params = params == {} ? nil : params
|
30
|
+
|
31
|
+
results = nil
|
32
|
+
params[:guid] = "user-#{GeoAPI::API_KEY}-#{params[:id]}" unless params[:id].blank?
|
33
|
+
raise ArgumentError, "Arguments should include a entity :guid or an :id" if params[:guid].blank? && params[:id].blank?
|
34
|
+
raise ArgumentError, "Arguments should include a view :name" if params[:name].blank?
|
35
|
+
|
36
|
+
begin
|
37
|
+
debugger
|
38
|
+
|
39
|
+
response = get("/e/#{params[:guid]}/#{self.class.path_prefix}/#{params[:name]}")
|
40
|
+
rescue
|
41
|
+
raise BadRequest, "There was a problem communicating with the API"
|
42
|
+
end
|
43
|
+
|
44
|
+
entries = {'entries' => response['result']} # There are no entries in this view
|
45
|
+
|
46
|
+
results = View.new(entries.merge({'guid'=>params[:guid], 'name'=>params[:name]})) unless response['result'].blank? #the api doesn't return a guid in json?!
|
47
|
+
|
48
|
+
results
|
49
|
+
end
|
50
|
+
|
51
|
+
|
52
|
+
# Instance methods
|
53
|
+
def initialize attrs
|
54
|
+
setup(attrs)
|
55
|
+
end
|
56
|
+
|
57
|
+
def setup attrs
|
58
|
+
self.name = attrs['name']
|
59
|
+
self.guid = attrs['guid']
|
60
|
+
self.view_type = attrs['type']
|
61
|
+
|
62
|
+
self.entries = []
|
63
|
+
unless attrs['entries'].blank?
|
64
|
+
if attrs['entries'].size > 0
|
65
|
+
attrs['entries'].each do |entry|
|
66
|
+
self.entries << GeoAPI::Entry.new({'properties'=>entry})
|
67
|
+
end
|
68
|
+
self.entries.reverse!
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
def load
|
75
|
+
raise ArgumentError, "Properties should include a .guid or .id" if self.guid.blank? && self.id.blank?
|
76
|
+
raise ArgumentError, "Properties should include a .name" if self.name.blank?
|
77
|
+
|
78
|
+
the_guid = self.guid
|
79
|
+
|
80
|
+
the_guid ||= "user-#{GeoAPI::API_KEY}-#{self.id}"
|
81
|
+
|
82
|
+
begin
|
83
|
+
response = self.class.get("/e/#{the_guid}/#{self.class.path_prefix}/#{self.name}")
|
84
|
+
rescue
|
85
|
+
raise BadRequest, "There was a problem communicating with the API"
|
86
|
+
end
|
87
|
+
|
88
|
+
entries = {'entries' => response['result']} # There are no entries in this view
|
89
|
+
|
90
|
+
self.setup(entries.merge({'guid'=>self.guid, 'name'=>self.name }))
|
91
|
+
|
92
|
+
self
|
93
|
+
end
|
94
|
+
|
95
|
+
def to_json options=nil
|
96
|
+
{:name=>name, :guid=>guid, :type=>view_type}.to_json
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
data/lib/geoapi.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
%w{rubygems rest_client httparty json crack/json uuidtools}.each { |x| require x }
|
3
|
+
|
4
|
+
# Patch HTTParty to debug
|
5
|
+
HTTParty::Request.class_eval do
|
6
|
+
class << self
|
7
|
+
attr_accessor :debug
|
8
|
+
end
|
9
|
+
self.debug = true
|
10
|
+
|
11
|
+
def perform_with_debug
|
12
|
+
if self.class.debug
|
13
|
+
puts "HTTParty making #{http_method::METHOD} request to:"
|
14
|
+
puts uri
|
15
|
+
puts "With Body: #{body}"
|
16
|
+
end
|
17
|
+
perform_without_debug
|
18
|
+
end
|
19
|
+
|
20
|
+
alias_method :perform_without_debug, :perform
|
21
|
+
alias_method :perform, :perform_with_debug
|
22
|
+
end
|
23
|
+
|
24
|
+
# monkey patch HTTParty to use a configurable timeout
|
25
|
+
module HTTParty
|
26
|
+
class Request
|
27
|
+
private
|
28
|
+
def http
|
29
|
+
http = Net::HTTP.new(uri.host, uri.port, options[:http_proxyaddr], options[:http_proxyport])
|
30
|
+
http.use_ssl = (uri.port == 443)
|
31
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
32
|
+
http.open_timeout = http.read_timeout = options[:timeout].to_i if options[:timeout].to_i > 0
|
33
|
+
http
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def retryable(options = {}, &block)
|
39
|
+
opts = { :tries => 1, :on => Exception }.merge(options)
|
40
|
+
|
41
|
+
retry_exception, retries = opts[:on], opts[:tries]
|
42
|
+
|
43
|
+
begin
|
44
|
+
return yield
|
45
|
+
rescue retry_exception
|
46
|
+
retry if (retries -= 1) > 0
|
47
|
+
end
|
48
|
+
|
49
|
+
yield
|
50
|
+
end
|
51
|
+
|
52
|
+
class Array
|
53
|
+
# Extract options from a set of arguments. Removes and returns the last element in the array if it's a hash, otherwise returns a blank hash.
|
54
|
+
#
|
55
|
+
# def options(*args)
|
56
|
+
# args.extract_options!
|
57
|
+
# end
|
58
|
+
#
|
59
|
+
# options(1, 2) # => {}
|
60
|
+
# options(1, 2, :a => :b) # => {:a=>:b}
|
61
|
+
def extract_options!
|
62
|
+
last.is_a?(::Hash) ? pop : {}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module GeoAPI
|
67
|
+
API_VERSION = "v1"
|
68
|
+
API_URL = "http://api.geoapi.com/#{API_VERSION}/"
|
69
|
+
|
70
|
+
class ArgumentError < StandardError; end
|
71
|
+
class BadRequest < StandardError; end
|
72
|
+
class NotFound < StandardError; end
|
73
|
+
class NotAcceptable < StandardError; end
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
$:.unshift(File.dirname(__FILE__)) unless
|
78
|
+
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
79
|
+
|
80
|
+
require 'geoapi/geo_object'
|
81
|
+
require 'geoapi/geometry'
|
82
|
+
require 'geoapi/version'
|
83
|
+
require 'geoapi/entity'
|
84
|
+
require 'geoapi/entry'
|
85
|
+
require 'geoapi/view'
|
86
|
+
require 'geoapi/user_view'
|
87
|
+
require 'geoapi/query'
|
88
|
+
require 'geoapi/client'
|
89
|
+
require 'geoapi/neighborhood'
|
metadata
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: steflewandowski-geoapi
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stef Lewandowski
|
8
|
+
- Chris Bruce
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2009-11-10 00:00:00 +00:00
|
14
|
+
default_executable:
|
15
|
+
dependencies:
|
16
|
+
- !ruby/object:Gem::Dependency
|
17
|
+
name: rest-client
|
18
|
+
type: :runtime
|
19
|
+
version_requirement:
|
20
|
+
version_requirements: !ruby/object:Gem::Requirement
|
21
|
+
requirements:
|
22
|
+
- - ">="
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: "0.9"
|
25
|
+
version:
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: crack
|
28
|
+
type: :runtime
|
29
|
+
version_requirement:
|
30
|
+
version_requirements: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: "0"
|
35
|
+
version:
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: httparty
|
38
|
+
type: :runtime
|
39
|
+
version_requirement:
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: "0"
|
45
|
+
version:
|
46
|
+
- !ruby/object:Gem::Dependency
|
47
|
+
name: uuidtools
|
48
|
+
type: :runtime
|
49
|
+
version_requirement:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: "0"
|
55
|
+
version:
|
56
|
+
description: A Ruby wrapper for the GeoAPI.com API based on the work of Chris Bruce. See http://api.geoapi.com for more information about the API.
|
57
|
+
email: stef@stef.io
|
58
|
+
executables: []
|
59
|
+
|
60
|
+
extensions: []
|
61
|
+
|
62
|
+
extra_rdoc_files: []
|
63
|
+
|
64
|
+
files:
|
65
|
+
- README
|
66
|
+
- LICENSE
|
67
|
+
- geoapi.gemspec
|
68
|
+
- lib/geoapi.rb
|
69
|
+
- lib/geoapi/geo_object.rb
|
70
|
+
- lib/geoapi/geometry.rb
|
71
|
+
- lib/geoapi/query.rb
|
72
|
+
- lib/geoapi/entity.rb
|
73
|
+
- lib/geoapi/entry.rb
|
74
|
+
- lib/geoapi/view.rb
|
75
|
+
- lib/geoapi/user_view.rb
|
76
|
+
- lib/geoapi/version.rb
|
77
|
+
- lib/geoapi/client.rb
|
78
|
+
- lib/geoapi/neighborhood.rb
|
79
|
+
has_rdoc: true
|
80
|
+
homepage: http://github.com/steflewandowski/GeoAPI/
|
81
|
+
licenses: []
|
82
|
+
|
83
|
+
post_install_message:
|
84
|
+
rdoc_options:
|
85
|
+
- --main
|
86
|
+
- README.rdoc
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: "0"
|
94
|
+
version:
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: "0"
|
100
|
+
version:
|
101
|
+
requirements: []
|
102
|
+
|
103
|
+
rubyforge_project:
|
104
|
+
rubygems_version: 1.3.5
|
105
|
+
signing_key:
|
106
|
+
specification_version: 3
|
107
|
+
summary: A Ruby wrapper for the GeoAPI.com API.
|
108
|
+
test_files: []
|
109
|
+
|