fireeagle 0.6.1 → 0.6.2
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +7 -0
- data/config/requirements.rb +2 -1
- data/lib/fireeagle.rb +16 -4
- data/lib/fireeagle/client.rb +67 -102
- data/lib/fireeagle/version.rb +1 -1
- data/spec/fireeagle_location_spec.rb +5 -5
- data/spec/fireeagle_response_spec.rb +11 -11
- data/spec/fireeagle_spec.rb +70 -30
- data/spec/spec_helper.rb +231 -0
- data/tasks/rspec.rake +11 -0
- metadata +2 -2
data/History.txt
CHANGED
data/config/requirements.rb
CHANGED
@@ -2,10 +2,11 @@ require 'fileutils'
|
|
2
2
|
include FileUtils
|
3
3
|
|
4
4
|
require 'rubygems'
|
5
|
-
%w[rake hoe newgem rubigen].each do |req_gem|
|
5
|
+
%w[rake hoe newgem rubigen oauth geo_ruby].each do |req_gem|
|
6
6
|
begin
|
7
7
|
require req_gem
|
8
8
|
rescue LoadError
|
9
|
+
req_gem = 'GeoRuby' if req_gem == 'geo_ruby' # gem not the same name
|
9
10
|
puts "This Rakefile requires the '#{req_gem}' RubyGem."
|
10
11
|
puts "Installation: gem install #{req_gem} -y"
|
11
12
|
exit
|
data/lib/fireeagle.rb
CHANGED
@@ -20,7 +20,7 @@ class FireEagle
|
|
20
20
|
RECENT_API_PATH = "/api/0.1/recent"
|
21
21
|
WITHIN_API_PATH = "/api/0.1/within"
|
22
22
|
FORMAT_XML = "xml"
|
23
|
-
UPDATE_PARAMS = :lat, :lon, :woeid, :place_id, :address, :mnc, :mcc, :lac, :
|
23
|
+
UPDATE_PARAMS = :lat, :lon, :woeid, :place_id, :address, :mnc, :mcc, :lac, :cellid, :postal, :city, :state, :country, :q, :label
|
24
24
|
# not yet supported
|
25
25
|
#,:geom, :upcoming_venue_id, :yahoo_local_id, :plazes_id
|
26
26
|
|
@@ -34,9 +34,9 @@ class FireEagle
|
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
|
-
#FireEagle additions to the <code>Hash</code> class
|
37
|
+
# FireEagle additions to the <code>Hash</code> class
|
38
38
|
class Hash
|
39
|
-
#Returns <code>true</code> if the ALL or NONE of the given keys are present in <i>
|
39
|
+
# Returns <code>true</code> if the ALL or NONE of the given keys are present in <i>my_keys</i>.
|
40
40
|
def has_all_or_none_keys?(*my_keys)
|
41
41
|
size = my_keys.length
|
42
42
|
false_count = 0
|
@@ -47,7 +47,19 @@ class Hash
|
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
50
|
+
# FireEagle addition to the <code>OAuth::Consumer</code> class
|
51
|
+
class OAuth::Consumer
|
52
|
+
alias_method :create_http_with_verify, :create_http
|
53
|
+
# Monkey patch to silence the SSL warnings
|
54
|
+
def create_http_without_verify #:nodoc:
|
55
|
+
http_object = create_http_with_verify
|
56
|
+
http_object.verify_mode = OpenSSL::SSL::VERIFY_NONE if uri.scheme=="https"
|
57
|
+
http_object
|
58
|
+
end
|
59
|
+
alias_method :create_http, :create_http_without_verify
|
60
|
+
end
|
61
|
+
|
50
62
|
require File.dirname(__FILE__) + '/fireeagle/client'
|
51
63
|
require File.dirname(__FILE__) + '/fireeagle/location'
|
52
64
|
require File.dirname(__FILE__) + '/fireeagle/user'
|
53
|
-
require File.dirname(__FILE__) + '/fireeagle/response'
|
65
|
+
require File.dirname(__FILE__) + '/fireeagle/response'
|
data/lib/fireeagle/client.rb
CHANGED
@@ -76,23 +76,23 @@ class FireEagle
|
|
76
76
|
:debug => false,
|
77
77
|
:format => FireEagle::FORMAT_XML
|
78
78
|
}.merge(options)
|
79
|
-
|
79
|
+
|
80
80
|
# symbolize keys
|
81
81
|
options.map do |k,v|
|
82
82
|
options[k.to_sym] = v
|
83
83
|
end
|
84
84
|
raise FireEagle::ArgumentError, "OAuth Consumer Key and Secret required" if options[:consumer_key].nil? || options[:consumer_secret].nil?
|
85
|
-
@consumer = OAuth::Consumer.new(options[:consumer_key], options[:consumer_secret])
|
86
|
-
@debug
|
87
|
-
@format
|
88
|
-
@app_id
|
85
|
+
@consumer = OAuth::Consumer.new(options[:consumer_key], options[:consumer_secret], :site => FireEagle::API_SERVER, :authorize_url => FireEagle::AUTHORIZATION_URL)
|
86
|
+
@debug = options[:debug]
|
87
|
+
@format = options[:format]
|
88
|
+
@app_id = options[:app_id]
|
89
89
|
if options[:access_token] && options[:access_token_secret]
|
90
|
-
@access_token = OAuth::
|
90
|
+
@access_token = OAuth::AccessToken.new(@consumer, options[:access_token], options[:access_token_secret])
|
91
91
|
else
|
92
92
|
@access_token = nil
|
93
93
|
end
|
94
94
|
if options[:request_token] && options[:request_token_secret]
|
95
|
-
@request_token = OAuth::
|
95
|
+
@request_token = OAuth::RequestToken.new(@consumer, options[:request_token], options[:request_token_secret])
|
96
96
|
else
|
97
97
|
@request_token = nil
|
98
98
|
end
|
@@ -101,8 +101,7 @@ class FireEagle
|
|
101
101
|
# Obtain an <strong>new</strong> unauthorized OAuth Request token
|
102
102
|
def get_request_token(force_token_regeneration = false)
|
103
103
|
if force_token_regeneration || @request_token.nil?
|
104
|
-
|
105
|
-
@request_token = create_token(response)
|
104
|
+
@request_token = consumer.get_request_token
|
106
105
|
end
|
107
106
|
@request_token
|
108
107
|
end
|
@@ -116,14 +115,13 @@ class FireEagle
|
|
116
115
|
# The URL the user must access to authorize this token. request_token must be called first. For use by web-based and desktop-based applications.
|
117
116
|
def authorization_url
|
118
117
|
raise FireEagle::ArgumentError, "call #get_request_token first" if @request_token.nil?
|
119
|
-
|
118
|
+
request_token.authorize_url
|
120
119
|
end
|
121
120
|
|
122
121
|
#Exchange an authorized OAuth Request token for an access token. For use by desktop-based and mobile applications.
|
123
122
|
def convert_to_access_token
|
124
123
|
raise FireEagle::ArgumentError, "call #get_request_token and have user authorize the token first" if @request_token.nil?
|
125
|
-
|
126
|
-
@access_token = create_token(response)
|
124
|
+
@access_token = request_token.get_access_token
|
127
125
|
end
|
128
126
|
|
129
127
|
# Disambiguates potential values for update query. Results from lookup can be passed to
|
@@ -133,19 +131,19 @@ class FireEagle
|
|
133
131
|
#
|
134
132
|
# There is a specific order for looking up locations. For example, if you provide lat, lon, and address,
|
135
133
|
# FireEagle will use the the latitude and longitude geo-coordinates and ignore the address.
|
136
|
-
#
|
134
|
+
#
|
137
135
|
# Location Hash keys, in order of priority:
|
138
|
-
#
|
139
|
-
# [<tt>(:lat, :lon)</tt>]
|
140
|
-
# [<tt>(:woeid)</tt>]
|
141
|
-
# [<tt>:place_id</tt>]
|
142
|
-
# [<tt>:address</tt>]
|
143
|
-
# [<tt>(:mnc, :mcc, :lac, :
|
144
|
-
# [<tt>:postal</tt>]
|
145
|
-
# [<tt>:city</tt>]
|
146
|
-
# [<tt>:state</tt>]
|
147
|
-
# [<tt>:country</tt>]
|
148
|
-
# [<tt>:q</tt>]
|
136
|
+
#
|
137
|
+
# [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
|
138
|
+
# [<tt>(:woeid)</tt>] Where on Earth ID
|
139
|
+
# [<tt>:place_id</tt>] Place ID (via Flickr/Upcomoing); deprecated in favor of WOE IDs when possible
|
140
|
+
# [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
|
141
|
+
# [<tt>(:mnc, :mcc, :lac, :cellid)</tt>] cell tower information, all required (as integers) for a valid tower location
|
142
|
+
# [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
|
143
|
+
# [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
|
144
|
+
# [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
|
145
|
+
# [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
|
146
|
+
# [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
|
149
147
|
#
|
150
148
|
# Not yet supported:
|
151
149
|
#
|
@@ -154,9 +152,7 @@ class FireEagle
|
|
154
152
|
# * <tt>plazes_id</tt>
|
155
153
|
def lookup(params)
|
156
154
|
raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
|
157
|
-
|
158
155
|
response = get(FireEagle::LOOKUP_API_PATH + ".#{format}", :params => params)
|
159
|
-
|
160
156
|
FireEagle::Response.new(response.body).locations
|
161
157
|
end
|
162
158
|
|
@@ -167,18 +163,18 @@ class FireEagle
|
|
167
163
|
#
|
168
164
|
# There is a specific order for looking up locations. For example, if you provide lat, lon, and address,
|
169
165
|
# FireEagle will use the the latitude and longitude geo-coordinates and ignore the address.
|
170
|
-
#
|
166
|
+
#
|
171
167
|
# Location Hash keys, in order of priority:
|
172
|
-
#
|
173
|
-
# [<tt>(:lat, :lon)</tt>]
|
174
|
-
# [<tt>:place_id</tt>]
|
175
|
-
# [<tt>:address</tt>]
|
176
|
-
# [<tt>(:mnc, :mcc, :lac, :
|
177
|
-
# [<tt>:postal</tt>]
|
178
|
-
# [<tt>:city</tt>]
|
179
|
-
# [<tt>:state</tt>]
|
180
|
-
# [<tt>:country</tt>]
|
181
|
-
# [<tt>:q</tt>]
|
168
|
+
#
|
169
|
+
# [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
|
170
|
+
# [<tt>:place_id</tt>] Place ID - valid values decrypts to an integer value
|
171
|
+
# [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
|
172
|
+
# [<tt>(:mnc, :mcc, :lac, :cellid)</tt>] cell tower information, all required (as integers) for a valid tower location
|
173
|
+
# [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
|
174
|
+
# [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
|
175
|
+
# [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
|
176
|
+
# [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
|
177
|
+
# [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
|
182
178
|
#
|
183
179
|
# Not yet supported:
|
184
180
|
#
|
@@ -187,50 +183,48 @@ class FireEagle
|
|
187
183
|
# * <tt>plazes_id</tt>
|
188
184
|
def update(location = {})
|
189
185
|
raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
|
190
|
-
|
191
186
|
location = sanitize_location_hash(location)
|
192
|
-
|
193
187
|
response = post(FireEagle::UPDATE_API_PATH + ".#{format}", :params => location)
|
194
|
-
|
195
188
|
FireEagle::Response.new(response.body)
|
196
189
|
end
|
197
190
|
|
198
191
|
# Returns the Location of a User.
|
199
192
|
def user
|
200
193
|
raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
|
201
|
-
|
202
194
|
response = get(FireEagle::USER_API_PATH + ".#{format}")
|
203
|
-
|
204
195
|
FireEagle::Response.new(response.body).users.first
|
205
196
|
end
|
206
197
|
alias_method :location, :user
|
207
198
|
|
208
|
-
# Query for Users of an Application who have updated their Location recently. Returns a list of
|
199
|
+
# Query for Users of an Application who have updated their Location recently. Returns a list of
|
209
200
|
# Users for the Application with recently updated locations.
|
210
|
-
|
201
|
+
#
|
202
|
+
# == Optional parameters:
|
203
|
+
#
|
204
|
+
# <tt>count</tt> Number of users to return per page. (default: 10)
|
205
|
+
# <tt>start</tt> The page number at which to start returning the list of users. Pages are 0-indexed, each page contains the per_page number of users. (default: 0)
|
206
|
+
# <tt>time</tt> The time to start looking at recent updates from. Value is flexible, supported forms are 'now', 'yesterday', '12:00', '13:00', '1:00pm' and '2008-03-12 12:34:56'. (default: 'now')
|
207
|
+
def recent(count = 10, start = 0, time = 'now')
|
211
208
|
raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
|
212
|
-
|
213
|
-
params = { :count => count, :start => start }
|
214
|
-
|
209
|
+
params = { :count => count, :start => start, :time => time }
|
215
210
|
response = get(FireEagle::RECENT_API_PATH + ".#{format}", :params => params)
|
216
|
-
|
217
211
|
FireEagle::Response.new(response.body).users
|
218
212
|
end
|
219
213
|
|
220
214
|
# Takes a Place ID or a Location and returns a list of users of your application who are within the bounding box of that Location.
|
221
215
|
#
|
222
216
|
# Location Hash keys, in order of priority:
|
223
|
-
#
|
224
|
-
# [<tt>(:lat, :lon)</tt>]
|
225
|
-
# [<tt>:woeid</tt>]
|
226
|
-
# [<tt>:place_id</tt>]
|
227
|
-
# [<tt>:address</tt>]
|
228
|
-
# [<tt>(:mnc, :mcc, :lac, :
|
229
|
-
# [<tt>:postal</tt>]
|
230
|
-
# [<tt>:city</tt>]
|
231
|
-
# [<tt>:state</tt>]
|
232
|
-
# [<tt>:country</tt>]
|
233
|
-
# [<tt>:q</tt>]
|
217
|
+
#
|
218
|
+
# [<tt>(:lat, :lon)</tt>] both required, valid values are floats of -180 to 180 for lat and -90 to 90 for lon
|
219
|
+
# [<tt>:woeid</tt>] Where on Earth ID
|
220
|
+
# [<tt>:place_id</tt>] Place ID
|
221
|
+
# [<tt>:address</tt>] street address (may contain a full address, but will be combined with postal, city, state, and country when available)
|
222
|
+
# [<tt>(:mnc, :mcc, :lac, :cellid)</tt>] cell tower information, all required (as integers) for a valid tower location
|
223
|
+
# [<tt>:postal</tt>] a ZIP or postal code (combined with address, city, state, and country when available)
|
224
|
+
# [<tt>:city</tt>] city (combined with address, postal, state, and country when available)
|
225
|
+
# [<tt>:state</tt>] state (combined with address, postal, city, and country when available)
|
226
|
+
# [<tt>:country</tt>] country (combined with address, postal, city, and state when available)
|
227
|
+
# [<tt>:q</tt>] Free-text fallback containing user input. Lat/lon pairs and geometries will be extracted if possible, otherwise this string will be geocoded as-is.
|
234
228
|
#
|
235
229
|
# Not yet supported:
|
236
230
|
#
|
@@ -239,12 +233,9 @@ class FireEagle
|
|
239
233
|
# * <tt>plazes_id</tt>
|
240
234
|
def within(location = {}, count = 10, start = 0)
|
241
235
|
raise FireEagle::ArgumentError, "OAuth Access Token Required" unless @access_token
|
242
|
-
|
243
236
|
location = sanitize_location_hash(location)
|
244
237
|
params = { :count => count, :start => start }.merge(location)
|
245
|
-
|
246
238
|
response = get(FireEagle::WITHIN_API_PATH + ".#{format}", :params => params)
|
247
|
-
|
248
239
|
FireEagle::Response.new(response.body).users
|
249
240
|
end
|
250
241
|
|
@@ -257,24 +248,10 @@ class FireEagle
|
|
257
248
|
|
258
249
|
location = location.reject { |key, value| !FireEagle::UPDATE_PARAMS.include?(key) }
|
259
250
|
raise FireEagle::ArgumentError, "Requires all or none of :lat, :lon" unless location.has_all_or_none_keys?(:lat, :lon)
|
260
|
-
raise FireEagle::ArgumentError, "Requires all or none of :mnc, :mcc, :lac, :cellid" unless location.has_all_or_none_keys?(:mnc, :mcc, :lac, :
|
251
|
+
raise FireEagle::ArgumentError, "Requires all or none of :mnc, :mcc, :lac, :cellid" unless location.has_all_or_none_keys?(:mnc, :mcc, :lac, :cellid)
|
261
252
|
location
|
262
253
|
end
|
263
254
|
|
264
|
-
def xml? #:nodoc:
|
265
|
-
format == FireEagle::FORMAT_XML
|
266
|
-
end
|
267
|
-
|
268
|
-
def create_token(response) #:nodoc:
|
269
|
-
token = Hash[*response.body.split("&").map { |x| x.split("=") }.flatten]
|
270
|
-
OAuth::Token.new(token["oauth_token"], token["oauth_token_secret"])
|
271
|
-
end
|
272
|
-
|
273
|
-
# Is the Client in debug mode?
|
274
|
-
def debug?
|
275
|
-
@debug == true
|
276
|
-
end
|
277
|
-
|
278
255
|
def get(url, options = {}) #:nodoc:
|
279
256
|
request(:get, url, options)
|
280
257
|
end
|
@@ -284,33 +261,21 @@ class FireEagle
|
|
284
261
|
end
|
285
262
|
|
286
263
|
def request(method, url, options) #:nodoc:
|
287
|
-
|
288
|
-
|
289
|
-
:
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
if FireEagle::API_SERVER =~ /https:/
|
296
|
-
http.use_ssl = true
|
297
|
-
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
264
|
+
response = case method
|
265
|
+
when :post
|
266
|
+
access_token.request(:post, url, options[:params])
|
267
|
+
when :get
|
268
|
+
qs = options[:params].collect { |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&")
|
269
|
+
access_token.request(:get, "#{url}?#{qs}")
|
270
|
+
else
|
271
|
+
raise ArgumentError, "method #{method} not supported"
|
298
272
|
end
|
299
273
|
|
300
|
-
|
301
|
-
|
302
|
-
|
303
|
-
|
304
|
-
elsif method == :get
|
305
|
-
qs = options[:params].collect { |k,v| "#{CGI.escape(k.to_s)}=#{CGI.escape(v.to_s)}" }.join("&")
|
306
|
-
request = Net::HTTP::Get.new(request_uri.path + "?" + qs)
|
274
|
+
case response.code
|
275
|
+
when '500'; then raise FireEagle::FireEagleException, "Internal Server Error"
|
276
|
+
when '400'; then raise FireEagle::FireEagleException, "Method Not Implemented Yet"
|
277
|
+
else response
|
307
278
|
end
|
308
|
-
request.oauth!(http, consumer, options[:token])
|
309
|
-
response = http.request(request)
|
310
|
-
raise FireEagle::FireEagleException, "Internal Server Error" if response.code == '500'
|
311
|
-
raise FireEagle::FireEagleException, "Method Not Implemented Yet" if response.code == '400'
|
312
|
-
response
|
313
279
|
end
|
314
|
-
|
315
280
|
end
|
316
|
-
end
|
281
|
+
end
|
data/lib/fireeagle/version.rb
CHANGED
@@ -8,7 +8,7 @@ describe "FireEagle Location" do
|
|
8
8
|
end
|
9
9
|
|
10
10
|
it "should know if this is a best guess" do
|
11
|
-
@location.
|
11
|
+
@location.should_not be_best_guess
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should represent the level" do
|
@@ -30,7 +30,7 @@ describe "FireEagle Location" do
|
|
30
30
|
it "should represent the location's timestamp" do
|
31
31
|
@location.located_at.should == Time.parse("2008-01-22T14:23:11-08:00")
|
32
32
|
end
|
33
|
-
|
33
|
+
|
34
34
|
it "should use the name for #to_s" do
|
35
35
|
@location.to_s.should == @location.name
|
36
36
|
end
|
@@ -40,19 +40,19 @@ describe "FireEagle Location" do
|
|
40
40
|
it "should represent a bounding box as a GeoRuby Envelope" do
|
41
41
|
location = Hpricot.XML(XML_LOCATION_CHUNK)
|
42
42
|
@location = FireEagle::Location.new(location)
|
43
|
-
@location.geom.
|
43
|
+
@location.geom.should be_an_instance_of(GeoRuby::SimpleFeatures::Envelope)
|
44
44
|
end
|
45
45
|
|
46
46
|
it "should represent an exact point as a GeoRuby Point" do
|
47
47
|
location = Hpricot.XML(XML_EXACT_LOCATION_CHUNK)
|
48
48
|
@location = FireEagle::Location.new(location)
|
49
|
-
@location.geom.
|
49
|
+
@location.geom.should be_an_instance_of(GeoRuby::SimpleFeatures::Point)
|
50
50
|
end
|
51
51
|
|
52
52
|
it "should be aliased as 'geo'" do
|
53
53
|
location = Hpricot.XML(XML_EXACT_LOCATION_CHUNK)
|
54
54
|
@location = FireEagle::Location.new(location)
|
55
|
-
@location.geo.
|
55
|
+
@location.geo.should be_an_instance_of(GeoRuby::SimpleFeatures::Point)
|
56
56
|
end
|
57
57
|
|
58
58
|
end
|
@@ -7,29 +7,29 @@ describe "FireEagle Response" do
|
|
7
7
|
before(:each) do
|
8
8
|
@response = FireEagle::Response.new(XML_LOCATION_RESPONSE)
|
9
9
|
end
|
10
|
-
|
10
|
+
|
11
11
|
it "should indicate success" do
|
12
|
-
@response.
|
12
|
+
@response.should be_success
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should have an array of users" do
|
16
|
-
@response.
|
16
|
+
@response.should have(1).users
|
17
17
|
end
|
18
|
-
|
18
|
+
|
19
19
|
it "should have each users' token" do
|
20
20
|
@response.users.first.token.should == "16w3z6ysudxt"
|
21
21
|
end
|
22
|
-
|
22
|
+
|
23
23
|
it "should flag the best guess" do
|
24
24
|
@response.users.first.best_guess.name.should == "Yolo County, California"
|
25
25
|
end
|
26
|
-
|
27
|
-
it "should have users'
|
28
|
-
@response.users.first.
|
26
|
+
|
27
|
+
it "should have users' locations" do
|
28
|
+
@response.users.first.should have(4).locations
|
29
29
|
end
|
30
30
|
|
31
31
|
end
|
32
|
-
|
32
|
+
|
33
33
|
describe "location parsing" do
|
34
34
|
|
35
35
|
before(:each) do
|
@@ -37,11 +37,11 @@ describe "FireEagle Response" do
|
|
37
37
|
end
|
38
38
|
|
39
39
|
it "should indicate success" do
|
40
|
-
@response.
|
40
|
+
@response.should be_success
|
41
41
|
end
|
42
42
|
|
43
43
|
it "should have an array of locations" do
|
44
|
-
@response.
|
44
|
+
@response.should have(9).locations
|
45
45
|
end
|
46
46
|
|
47
47
|
it "should have each location's place_id" do
|
data/spec/fireeagle_spec.rb
CHANGED
@@ -12,7 +12,7 @@ describe "FireEagle" do
|
|
12
12
|
|
13
13
|
it "should initialize an OAuth::Consumer" do
|
14
14
|
@consumer = mock(OAuth::Consumer)
|
15
|
-
OAuth::Consumer.should_receive(:new).and_return(@consumer)
|
15
|
+
OAuth::Consumer.should_receive(:new).with('key', 'sekret', :site => FireEagle::API_SERVER, :authorize_url => FireEagle::AUTHORIZATION_URL).and_return(@consumer)
|
16
16
|
client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
|
17
17
|
end
|
18
18
|
|
@@ -20,16 +20,16 @@ describe "FireEagle" do
|
|
20
20
|
|
21
21
|
describe "web app authentication scenario" do
|
22
22
|
|
23
|
-
it "should initialize
|
24
|
-
@access_token = mock(OAuth::
|
25
|
-
OAuth::
|
23
|
+
it "should initialize an OAuth::AccessToken if given its token and secret" do
|
24
|
+
@access_token = mock(OAuth::AccessToken)
|
25
|
+
OAuth::AccessToken.stub!(:new).and_return(@access_token)
|
26
26
|
client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
|
27
27
|
client.access_token.should == @access_token
|
28
28
|
end
|
29
29
|
|
30
|
-
it "should initialize
|
31
|
-
@request_token = mock(OAuth::
|
32
|
-
OAuth::
|
30
|
+
it "should initialize an OAuth::RequestToken if given its token and secret" do
|
31
|
+
@request_token = mock(OAuth::RequestToken)
|
32
|
+
OAuth::RequestToken.stub!(:new).and_return(@request_token)
|
33
33
|
client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :request_token => 'toke', :request_token_secret => 'sekret')
|
34
34
|
client.request_token.should == @request_token
|
35
35
|
end
|
@@ -38,7 +38,7 @@ describe "FireEagle" do
|
|
38
38
|
describe "request token scenario" do
|
39
39
|
it "shouldn't initialize with a access_token" do
|
40
40
|
client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
|
41
|
-
client.access_token.should
|
41
|
+
client.access_token.should be_nil
|
42
42
|
end
|
43
43
|
|
44
44
|
it "should require token exchange before calling any API methods" do
|
@@ -49,12 +49,15 @@ describe "FireEagle" do
|
|
49
49
|
end
|
50
50
|
|
51
51
|
it "should generate a Request Token URL" do
|
52
|
+
consumer = mock(OAuth::Consumer)
|
53
|
+
token = mock(OAuth::RequestToken)
|
54
|
+
consumer.should_receive(:get_request_token).and_return(token)
|
55
|
+
token.should_receive(:authorize_url)
|
56
|
+
|
52
57
|
client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
|
53
|
-
|
54
|
-
client.stub!(:get).and_return('')
|
55
|
-
client.stub!(:create_token).and_return(@token)
|
58
|
+
client.should_receive(:consumer).and_return(consumer)
|
56
59
|
client.get_request_token
|
57
|
-
client.authorization_url
|
60
|
+
client.authorization_url
|
58
61
|
end
|
59
62
|
|
60
63
|
it "should require #get_request_token be called before #convert_to_access_token" do
|
@@ -71,14 +74,19 @@ describe "FireEagle" do
|
|
71
74
|
end.should raise_error(FireEagle::ArgumentError)
|
72
75
|
end
|
73
76
|
|
74
|
-
it "should generate
|
77
|
+
it "should generate an Access Token" do
|
78
|
+
consumer = mock(OAuth::Consumer)
|
79
|
+
req_token = mock(OAuth::RequestToken)
|
80
|
+
acc_token = mock(OAuth::AccessToken)
|
81
|
+
consumer.should_receive(:get_request_token).and_return(req_token)
|
82
|
+
req_token.should_receive(:get_access_token).and_return(acc_token)
|
83
|
+
|
75
84
|
client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret')
|
76
|
-
|
77
|
-
|
78
|
-
client.stub!(:create_token).and_return(@token)
|
85
|
+
client.should_receive(:consumer).and_return(consumer)
|
86
|
+
|
79
87
|
client.get_request_token
|
80
88
|
client.convert_to_access_token
|
81
|
-
client.access_token.should ==
|
89
|
+
client.access_token.should == acc_token
|
82
90
|
end
|
83
91
|
|
84
92
|
end
|
@@ -87,7 +95,7 @@ describe "FireEagle" do
|
|
87
95
|
|
88
96
|
before(:each) do
|
89
97
|
@client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
|
90
|
-
@response =
|
98
|
+
@response = stub('response', :body => XML_SUCCESS_RESPONSE)
|
91
99
|
@client.stub!(:request).and_return(@response)
|
92
100
|
end
|
93
101
|
|
@@ -96,13 +104,13 @@ describe "FireEagle" do
|
|
96
104
|
lambda { @client.update(:lat => 1, :lon => 2) }.should_not raise_error(FireEagle::ArgumentError)
|
97
105
|
end
|
98
106
|
|
99
|
-
it "requires all or none of :mnc, :mcc, :lac, :
|
100
|
-
lambda { @client.update(:mcc => 123, :lac => "whatever", :
|
101
|
-
lambda { @client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :
|
107
|
+
it "requires all or none of :mnc, :mcc, :lac, :cellid" do
|
108
|
+
lambda { @client.update(:mcc => 123, :lac => "whatever", :cellid => true) }.should raise_error(FireEagle::ArgumentError)
|
109
|
+
lambda { @client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :cellid => true) }.should_not raise_error(FireEagle::ArgumentError)
|
102
110
|
end
|
103
111
|
|
104
112
|
it "should wrap the result" do
|
105
|
-
@client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :
|
113
|
+
@client.update(:mcc => 123, :mnc => 123123, :lac => "whatever", :cellid => true).users.first.token.should == "16w3z6ysudxt"
|
106
114
|
end
|
107
115
|
|
108
116
|
end
|
@@ -110,9 +118,9 @@ describe "FireEagle" do
|
|
110
118
|
describe "user method" do
|
111
119
|
|
112
120
|
before(:each) do
|
113
|
-
@client
|
114
|
-
|
115
|
-
@client.stub!(:request).and_return(
|
121
|
+
@client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
|
122
|
+
response = stub('response', :body => XML_LOCATION_RESPONSE)
|
123
|
+
@client.stub!(:request).and_return(response)
|
116
124
|
end
|
117
125
|
|
118
126
|
it "should return a best guess" do
|
@@ -120,21 +128,21 @@ describe "FireEagle" do
|
|
120
128
|
end
|
121
129
|
|
122
130
|
it "should return several locations" do
|
123
|
-
@client.user.
|
131
|
+
@client.user.should have(4).locations
|
124
132
|
end
|
125
133
|
|
126
134
|
end
|
127
|
-
|
135
|
+
|
128
136
|
describe "lookup method" do
|
129
137
|
|
130
138
|
before(:each) do
|
131
139
|
@client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
|
132
|
-
@response =
|
140
|
+
@response = stub('response', :body => XML_LOOKUP_RESPONSE)
|
133
141
|
@client.stub!(:request).and_return(@response)
|
134
142
|
end
|
135
143
|
|
136
144
|
it "should return an array of Locations" do
|
137
|
-
@client.lookup(:q => "30022").
|
145
|
+
@client.lookup(:q => "30022").should have(9).items
|
138
146
|
end
|
139
147
|
|
140
148
|
it "should return a place id for each" do
|
@@ -147,4 +155,36 @@ describe "FireEagle" do
|
|
147
155
|
|
148
156
|
end
|
149
157
|
|
150
|
-
|
158
|
+
describe "within method" do
|
159
|
+
before do
|
160
|
+
@client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
|
161
|
+
@response = stub('response', :body => XML_WITHIN_RESPONSE)
|
162
|
+
@client.stub!(:request).and_return(@response)
|
163
|
+
end
|
164
|
+
|
165
|
+
it "should return an array of Users" do
|
166
|
+
@client.within(:woe => "12796255").should have(2).users
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should return an array of Locations for each" do
|
170
|
+
@client.within(:woe => "12796255").first.should have(5).locations
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
describe "recent method" do
|
175
|
+
before do
|
176
|
+
@client = FireEagle::Client.new(:consumer_key => 'key', :consumer_secret => 'sekret', :access_token => 'toke', :access_token_secret => 'sekret')
|
177
|
+
@response = stub('response', :body => XML_RECENT_RESPONSE)
|
178
|
+
@client.stub!(:request).and_return(@response)
|
179
|
+
end
|
180
|
+
|
181
|
+
it "should return an array of Users" do
|
182
|
+
@client.recent(2, 1, 'yesterday').should have(2).users
|
183
|
+
end
|
184
|
+
|
185
|
+
it "should return an array of Locations for each" do
|
186
|
+
@client.recent(2, 1, 'yesterday').first.should have(5).locations
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -124,5 +124,236 @@ XML_LOOKUP_RESPONSE = <<-RESPONSE
|
|
124
124
|
</rsp>
|
125
125
|
RESPONSE
|
126
126
|
|
127
|
+
XML_WITHIN_RESPONSE = <<-RESPONSE
|
128
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
129
|
+
<rsp stat="ok">
|
130
|
+
<users>
|
131
|
+
<user token="MQdDrJgXMNJi">
|
132
|
+
<location-hierarchy>
|
133
|
+
<location best-guess="true">
|
134
|
+
<id>111541</id>
|
135
|
+
<georss:point>32.7093315125 -117.1650772095</georss:point>
|
136
|
+
<level>0</level>
|
137
|
+
<level-name>exact</level-name>
|
138
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
139
|
+
<name>333 W Harbor Dr, San Diego, CA</name>
|
140
|
+
</location>
|
141
|
+
<location best-guess="false">
|
142
|
+
<id>111551</id>
|
143
|
+
<georss:box>
|
144
|
+
32.6916618347 -117.2174377441 32.744140625 -117.1458892822
|
145
|
+
</georss:box>
|
146
|
+
<level>1</level>
|
147
|
+
<level-name>postal</level-name>
|
148
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
149
|
+
<name>San Diego, CA 92101</name>
|
150
|
+
<place-id>NpiXqwmYA5viX3K3Ew</place-id>
|
151
|
+
<woeid>12796255</woeid>
|
152
|
+
</location>
|
153
|
+
<location best-guess="false">
|
154
|
+
<id>111561</id>
|
155
|
+
<georss:box>
|
156
|
+
32.5349388123 -117.2884292603 33.1128082275 -116.9142913818
|
157
|
+
</georss:box>
|
158
|
+
<level>3</level>
|
159
|
+
<level-name>city</level-name>
|
160
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
161
|
+
<name>San Diego, CA</name>
|
162
|
+
<place-id>Nm4O.DebBZTYKUsu</place-id>
|
163
|
+
<woeid>2487889</woeid>
|
164
|
+
</location>
|
165
|
+
<location best-guess="false">
|
166
|
+
<id>111571</id>
|
167
|
+
<georss:box>
|
168
|
+
32.5342788696 -124.4150238037 42.0093803406 -114.1308135986
|
169
|
+
</georss:box>
|
170
|
+
<level>5</level>
|
171
|
+
<level-name>state</level-name>
|
172
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
173
|
+
<name>California</name>
|
174
|
+
<place-id>SVrAMtCbAphCLAtP</place-id>
|
175
|
+
<woeid>2347563</woeid>
|
176
|
+
</location>
|
177
|
+
<location best-guess="false">
|
178
|
+
<id>111581</id>
|
179
|
+
<georss:box>
|
180
|
+
18.9108390808 -167.2764129639 72.8960571289 -66.6879425049
|
181
|
+
</georss:box>
|
182
|
+
<level>6</level>
|
183
|
+
<level-name>country</level-name>
|
184
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
185
|
+
<name>United States</name>
|
186
|
+
<place-id>4KO02SibApitvSBieQ</place-id>
|
187
|
+
<woeid>23424977</woeid>
|
188
|
+
</location>
|
189
|
+
</location-hierarchy>
|
190
|
+
</user>
|
191
|
+
<user token="MQdDrJgXMNJi">
|
192
|
+
<location-hierarchy>
|
193
|
+
<location best-guess="true">
|
194
|
+
<id>111541</id>
|
195
|
+
<georss:point>32.7093315125 -117.1650772095</georss:point>
|
196
|
+
<level>0</level>
|
197
|
+
<level-name>exact</level-name>
|
198
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
199
|
+
<name>333 W Harbor Dr, San Diego, CA</name>
|
200
|
+
</location>
|
201
|
+
<location best-guess="false">
|
202
|
+
<id>111551</id>
|
203
|
+
<georss:box>
|
204
|
+
32.6916618347 -117.2174377441 32.744140625 -117.1458892822
|
205
|
+
</georss:box>
|
206
|
+
<level>1</level>
|
207
|
+
<level-name>postal</level-name>
|
208
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
209
|
+
<name>San Diego, CA 92101</name>
|
210
|
+
<place-id>NpiXqwmYA5viX3K3Ew</place-id>
|
211
|
+
<woeid>12796255</woeid>
|
212
|
+
</location>
|
213
|
+
<location best-guess="false">
|
214
|
+
<id>111561</id>
|
215
|
+
<georss:box>
|
216
|
+
32.5349388123 -117.2884292603 33.1128082275 -116.9142913818
|
217
|
+
</georss:box>
|
218
|
+
<level>3</level>
|
219
|
+
<level-name>city</level-name>
|
220
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
221
|
+
<name>San Diego, CA</name>
|
222
|
+
<place-id>Nm4O.DebBZTYKUsu</place-id>
|
223
|
+
<woeid>2487889</woeid>
|
224
|
+
</location>
|
225
|
+
<location best-guess="false">
|
226
|
+
<id>111571</id>
|
227
|
+
<georss:box>
|
228
|
+
32.5342788696 -124.4150238037 42.0093803406 -114.1308135986
|
229
|
+
</georss:box>
|
230
|
+
<level>5</level>
|
231
|
+
<level-name>state</level-name>
|
232
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
233
|
+
<name>California</name>
|
234
|
+
<place-id>SVrAMtCbAphCLAtP</place-id>
|
235
|
+
<woeid>2347563</woeid>
|
236
|
+
</location>
|
237
|
+
<location best-guess="false">
|
238
|
+
<id>111581</id>
|
239
|
+
<georss:box>
|
240
|
+
18.9108390808 -167.2764129639 72.8960571289 -66.6879425049
|
241
|
+
</georss:box>
|
242
|
+
<level>6</level>
|
243
|
+
<level-name>country</level-name>
|
244
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
245
|
+
<name>United States</name>
|
246
|
+
<place-id>4KO02SibApitvSBieQ</place-id>
|
247
|
+
<woeid>23424977</woeid>
|
248
|
+
</location>
|
249
|
+
</location-hierarchy>
|
250
|
+
</user>
|
251
|
+
</users>
|
252
|
+
</rsp>
|
253
|
+
RESPONSE
|
254
|
+
|
255
|
+
XML_RECENT_RESPONSE = <<-RESPONSE
|
256
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
257
|
+
<rsp stat="ok" xmlns:georss="http://www.georss.org/georss">
|
258
|
+
<users>
|
259
|
+
<user token="MQdDrJgXMNJi">
|
260
|
+
<location-hierarchy>
|
261
|
+
<location best-guess="true">
|
262
|
+
<id>111541</id>
|
263
|
+
<georss:point>32.7093315125 -117.1650772095</georss:point>
|
264
|
+
<level>0</level>
|
265
|
+
<level-name>exact</level-name>
|
266
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
267
|
+
<name>333 W Harbor Dr, San Diego, CA</name>
|
268
|
+
</location>
|
269
|
+
<location best-guess="false">
|
270
|
+
<id>111551</id>
|
271
|
+
<georss:box>32.6916618347 -117.2174377441 32.744140625 -117.1458892822</georss:box>
|
272
|
+
<level>1</level>
|
273
|
+
<level-name>postal</level-name>
|
274
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
275
|
+
<name>San Diego, CA 92101</name>
|
276
|
+
<place-id>NpiXqwmYA5viX3K3Ew</place-id>
|
277
|
+
<woeid>12796255</woeid>
|
278
|
+
</location>
|
279
|
+
<location best-guess="false">
|
280
|
+
<id>111561</id>
|
281
|
+
<georss:box>32.5349388123 -117.2884292603 33.1128082275 -116.9142913818</georss:box>
|
282
|
+
<level>3</level>
|
283
|
+
<level-name>city</level-name>
|
284
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
285
|
+
<name>San Diego, CA</name>
|
286
|
+
<place-id>Nm4O.DebBZTYKUsu</place-id>
|
287
|
+
<woeid>2487889</woeid>
|
288
|
+
</location>
|
289
|
+
<location best-guess="false">
|
290
|
+
<id>111571</id>
|
291
|
+
<georss:box>32.5342788696 -124.4150238037 42.0093803406 -114.1308135986</georss:box>
|
292
|
+
<level>5</level>
|
293
|
+
<level-name>state</level-name>
|
294
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
295
|
+
<name>California</name>
|
296
|
+
<place-id>SVrAMtCbAphCLAtP</place-id>
|
297
|
+
<woeid>2347563</woeid>
|
298
|
+
</location>
|
299
|
+
<location best-guess="false">
|
300
|
+
<id>111581</id>
|
301
|
+
<georss:box>18.9108390808 -167.2764129639 72.8960571289 -66.6879425049</georss:box>
|
302
|
+
<level>6</level>
|
303
|
+
<level-name>country</level-name>
|
304
|
+
<located-at>2008-03-03T09:05:16-08:00</located-at>
|
305
|
+
<name>United States</name>
|
306
|
+
<place-id>4KO02SibApitvSBieQ</place-id>
|
307
|
+
<woeid>23424977</woeid>
|
308
|
+
</location>
|
309
|
+
</location-hierarchy>
|
310
|
+
</user>
|
311
|
+
<user token="XMoZaTjZJiOQ">
|
312
|
+
<location-hierarchy>
|
313
|
+
<location best-guess="true">
|
314
|
+
<id>113221</id>
|
315
|
+
<georss:box>32.8155899048 -96.8162918091 32.8511695862 -96.7717132568</georss:box>
|
316
|
+
<level>1</level>
|
317
|
+
<level-name>postal</level-name>
|
318
|
+
<located-at>2008-03-03T10:24:24-08:00</located-at>
|
319
|
+
<name>Dallas, TX 75205</name>
|
320
|
+
<place-id>1KTPxFCYA5vlcics6A</place-id>
|
321
|
+
<woeid>12790441</woeid>
|
322
|
+
</location>
|
323
|
+
<location best-guess="false">
|
324
|
+
<id>113231</id>
|
325
|
+
<georss:box>32.6209487915 -96.9988708496 33.0258712769 -96.4660263062</georss:box>
|
326
|
+
<level>3</level>
|
327
|
+
<level-name>city</level-name>
|
328
|
+
<located-at>2008-03-03T10:24:24-08:00</located-at>
|
329
|
+
<name>Dallas, TX</name>
|
330
|
+
<place-id>bgWooz.bApRFBRNK</place-id>
|
331
|
+
<woeid>2388929</woeid>
|
332
|
+
</location>
|
333
|
+
<location best-guess="false">
|
334
|
+
<id>113241</id>
|
335
|
+
<georss:box>25.8372898102 -106.645652771 36.5006904602 -93.5079269409</georss:box>
|
336
|
+
<level>5</level>
|
337
|
+
<level-name>state</level-name>
|
338
|
+
<located-at>2008-03-03T10:24:24-08:00</located-at>
|
339
|
+
<name>Texas</name>
|
340
|
+
<place-id>b1Yi6qubApjz6jWW</place-id>
|
341
|
+
<woeid>2347602</woeid>
|
342
|
+
</location>
|
343
|
+
<location best-guess="false">
|
344
|
+
<id>113251</id>
|
345
|
+
<georss:box>18.9108390808 -167.2764129639 72.8960571289 -66.6879425049</georss:box>
|
346
|
+
<level>6</level>
|
347
|
+
<level-name>country</level-name>
|
348
|
+
<located-at>2008-03-03T10:24:24-08:00</located-at>
|
349
|
+
<name>United States</name>
|
350
|
+
<place-id>4KO02SibApitvSBieQ</place-id>
|
351
|
+
<woeid>23424977</woeid>
|
352
|
+
</location>
|
353
|
+
</location-hierarchy>
|
354
|
+
</user>
|
355
|
+
</users>
|
356
|
+
</rsp>
|
357
|
+
RESPONSE
|
127
358
|
|
128
359
|
require File.dirname(__FILE__) + '/../lib/fireeagle'
|
data/tasks/rspec.rake
CHANGED
@@ -19,3 +19,14 @@ Spec::Rake::SpecTask.new do |t|
|
|
19
19
|
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
20
|
t.spec_files = FileList['spec/*_spec.rb']
|
21
21
|
end
|
22
|
+
|
23
|
+
# Make spec the default task
|
24
|
+
# from http://blog.subterfusion.net/2008/rake-hacks-overriding-tasks-quick-binary-run-intelligent-irb/
|
25
|
+
Rake::TaskManager.class_eval do
|
26
|
+
def remove_task(task_name)
|
27
|
+
@tasks.delete(task_name.to_s)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
Rake.application.remove_task :default
|
32
|
+
task :default => :spec
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fireeagle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.6.
|
4
|
+
version: 0.6.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jesse Newland
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2008-03-
|
12
|
+
date: 2008-03-13 00:00:00 -04:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|