rest-more 0.7.2.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES.md +65 -0
- data/README.md +1 -1
- data/example/rails2/app/controllers/application_controller.rb +2 -2
- data/example/rails2/test/functional/application_controller_test.rb +26 -0
- data/example/rails3/app/controllers/application_controller.rb +2 -2
- data/example/rails3/test/functional/application_controller_test.rb +26 -0
- data/lib/rest-core/client/bing.rb +19 -17
- data/lib/rest-core/client/facebook.rb +14 -5
- data/lib/rest-core/client/facebook/rails_util.rb +29 -22
- data/lib/rest-core/client/flurry.rb +41 -21
- data/lib/rest-core/client/github.rb +11 -1
- data/lib/rest-core/client/linkedin.rb +6 -21
- data/lib/rest-core/client/mixi.rb +11 -3
- data/lib/rest-core/client/twitter.rb +13 -25
- data/lib/rest-core/client/twitter/rails_util.rb +150 -2
- data/lib/rest-more/version.rb +1 -1
- data/rest-more.gemspec +2 -2
- data/test/client/facebook/test_oauth.rb +5 -3
- data/test/client/flurry/test_metrics.rb +74 -63
- metadata +4 -4
data/CHANGES.md
CHANGED
@@ -1,5 +1,70 @@
|
|
1
1
|
# CHANGES
|
2
2
|
|
3
|
+
## rest-more 0.8.0 -- 2011-11-29
|
4
|
+
|
5
|
+
### Incompatible changes
|
6
|
+
|
7
|
+
* [Facebook::RailsUtil] Some methods are renamed. For example,
|
8
|
+
`rc_facebook_write_rg_fbs` is renamed to `rc_facebook_write_fbs`.
|
9
|
+
All renamed methods are considered private, so we're not listing them here.
|
10
|
+
|
11
|
+
* [Facebook::RailsUtil] `rc_facebook_storage_key` is changed to:
|
12
|
+
`"rc_facebook_#{rc_facebook.app_id}"`, your users might need to
|
13
|
+
login again in order to save the access_token into the new place.
|
14
|
+
|
15
|
+
### Bugs fixes
|
16
|
+
|
17
|
+
* [Github] Fixed usage of Oauth2Query.
|
18
|
+
|
19
|
+
* [Facebook] Now we're using POST in `authorize!` to exchange the
|
20
|
+
access_token with the code instead of GET. If we're using GET,
|
21
|
+
we would run into a risk where a user might use the code to
|
22
|
+
get other people's access_token via the cache. Using POST would
|
23
|
+
prevent this because POSTs are not cached.
|
24
|
+
|
25
|
+
* [Facebook::RailsUtil] Fixed a serious bug. The bug would jump up if
|
26
|
+
you're using :write_session or :write_cookies or :write_handler along
|
27
|
+
with :auto_authorize, for example:
|
28
|
+
`rc_facebook_setup(:auto_authorize => true, :write_session => true)`
|
29
|
+
The problem is that Facebook::RailsUtil is not removing the invalid
|
30
|
+
access_token stored in session or cookie, and yet it is considered
|
31
|
+
authorized, making redirecting to Facebook and redirecting back doesn't
|
32
|
+
update the access_token. `rc_facebook_cleanup` is introduced to remove
|
33
|
+
all invalid access_tokens, which would get called once the user is
|
34
|
+
redirected to Facebook, fixing this bug.
|
35
|
+
|
36
|
+
### Enhancement
|
37
|
+
|
38
|
+
* [Facebook] Now we use `default_data` to get the default data,
|
39
|
+
instead of relying `Defaults` middleware.
|
40
|
+
|
41
|
+
* [Facebook] Protected methods are changed to private.
|
42
|
+
|
43
|
+
* [Flurry] `app_info` now accepts opts.
|
44
|
+
* [Flurry] `event_metrics` is renamed to `event_summary`
|
45
|
+
* [Flurry] `event_metrics` is now the API for accessing 'eventMetrics/Event'
|
46
|
+
* [Flurry] If you didn't pass dates, now default to for 7 days.
|
47
|
+
* [Flurry] Instead of overriding `query`, defining `default_query`
|
48
|
+
|
49
|
+
* [Linkedin+Twitter] Removed `Defaults` middleware because now we're using
|
50
|
+
the data from `Oauth1Client` instead.
|
51
|
+
|
52
|
+
* [Linkedin+Twitter] Removed `oauth_token`, `oauth_token=`,
|
53
|
+
`oauth_token_secret`, and `oauth_token_secret=` because we're using them
|
54
|
+
from `Oauth1Client` instead.
|
55
|
+
|
56
|
+
* [Linkedin+Twitter] Removed `set_token` because it's handled in
|
57
|
+
`Oauth1Client` now.
|
58
|
+
|
59
|
+
* [Twitter::RailsUtil] Now `rc_twitter_setup` accepts options like
|
60
|
+
`rc_facebook_setup`: `auto_authorize`, `ensure_authorized`,
|
61
|
+
`write_session`, `write_cookies`, `write_handler`, and `check_handler`.
|
62
|
+
|
63
|
+
* [Mixi] Removed `Defaults` middleware in favor of `default_data`.
|
64
|
+
|
65
|
+
* [Facebook+Github+Mixi+Twitter] Added a `me` method for accessing current
|
66
|
+
user information.
|
67
|
+
|
3
68
|
## rest-more 0.7.2.1 -- 2011-11-05
|
4
69
|
|
5
70
|
### Bugs fixes
|
data/README.md
CHANGED
@@ -5,7 +5,7 @@ by Cardinal Blue <http://cardinalblue.com>
|
|
5
5
|
## LINKS:
|
6
6
|
|
7
7
|
* [github](https://github.com/cardinalblue/rest-more)
|
8
|
-
* [rubygems](
|
8
|
+
* [rubygems](https://rubygems.org/gems/rest-more)
|
9
9
|
* [rdoc](http://rdoc.info/projects/cardinalblue/rest-more)
|
10
10
|
* [mailing list](http://groups.google.com/group/rest-core/topics)
|
11
11
|
|
@@ -125,10 +125,10 @@ class ApplicationController < ActionController::Base
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def filter_session
|
128
|
-
rc_facebook_setup(:write_session => true)
|
128
|
+
rc_facebook_setup(:write_session => true, :auto_authorize => true)
|
129
129
|
end
|
130
130
|
|
131
131
|
def filter_cookies
|
132
|
-
rc_facebook_setup(:write_cookies => true)
|
132
|
+
rc_facebook_setup(:write_cookies => true, :auto_authorize => true)
|
133
133
|
end
|
134
134
|
end
|
@@ -166,6 +166,32 @@ class ApplicationControllerTest < ActionController::TestCase
|
|
166
166
|
assert_equal '["yeti"]', @response.body
|
167
167
|
end
|
168
168
|
|
169
|
+
def test_wrong_session
|
170
|
+
WebMock.reset!
|
171
|
+
stub_request(:get, 'https://graph.facebook.com/me').
|
172
|
+
to_return(:body => '{"error":{"type":"OAuthException"}}')
|
173
|
+
|
174
|
+
session = @request.session
|
175
|
+
key = @controller.send(:rc_facebook_storage_key)
|
176
|
+
session[key] = 'bad'
|
177
|
+
|
178
|
+
get(:session_)
|
179
|
+
assert_equal nil, session[key]
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_wrong_cookies
|
183
|
+
WebMock.reset!
|
184
|
+
stub_request(:get, 'https://graph.facebook.com/me').
|
185
|
+
to_return(:body => '{"error":{"type":"OAuthException"}}')
|
186
|
+
|
187
|
+
cookies = @request.cookies
|
188
|
+
key = @controller.send(:rc_facebook_storage_key)
|
189
|
+
session[key] = 'bad'
|
190
|
+
|
191
|
+
get(:cookies_)
|
192
|
+
assert_equal nil, cookies[key]
|
193
|
+
end
|
194
|
+
|
169
195
|
def test_error
|
170
196
|
get(:error)
|
171
197
|
rescue => e
|
@@ -125,10 +125,10 @@ class ApplicationController < ActionController::Base
|
|
125
125
|
end
|
126
126
|
|
127
127
|
def filter_session
|
128
|
-
rc_facebook_setup(:write_session => true)
|
128
|
+
rc_facebook_setup(:write_session => true, :auto_authorize => true)
|
129
129
|
end
|
130
130
|
|
131
131
|
def filter_cookies
|
132
|
-
rc_facebook_setup(:write_cookies => true)
|
132
|
+
rc_facebook_setup(:write_cookies => true, :auto_authorize => true)
|
133
133
|
end
|
134
134
|
end
|
@@ -166,6 +166,32 @@ class ApplicationControllerTest < ActionController::TestCase
|
|
166
166
|
assert_equal '["yeti"]', @response.body
|
167
167
|
end
|
168
168
|
|
169
|
+
def test_wrong_session
|
170
|
+
WebMock.reset!
|
171
|
+
stub_request(:get, 'https://graph.facebook.com/me').
|
172
|
+
to_return(:body => '{"error":{"type":"OAuthException"}}')
|
173
|
+
|
174
|
+
session = @request.session
|
175
|
+
key = @controller.send(:rc_facebook_storage_key)
|
176
|
+
session[key] = 'bad'
|
177
|
+
|
178
|
+
get(:session_)
|
179
|
+
assert_equal nil, session[key]
|
180
|
+
end
|
181
|
+
|
182
|
+
def test_wrong_cookies
|
183
|
+
WebMock.reset!
|
184
|
+
stub_request(:get, 'https://graph.facebook.com/me').
|
185
|
+
to_return(:body => '{"error":{"type":"OAuthException"}}')
|
186
|
+
|
187
|
+
cookies = @request.cookies
|
188
|
+
key = @controller.send(:rc_facebook_storage_key)
|
189
|
+
session[key] = 'bad'
|
190
|
+
|
191
|
+
get(:cookies_)
|
192
|
+
assert_equal nil, cookies[key]
|
193
|
+
end
|
194
|
+
|
169
195
|
def test_error
|
170
196
|
get(:error)
|
171
197
|
rescue => e
|
@@ -1,6 +1,7 @@
|
|
1
1
|
|
2
2
|
require 'rest-core'
|
3
3
|
|
4
|
+
# http://msdn.microsoft.com/en-us/library/dd250846.aspx
|
4
5
|
RestCore::Bing = RestCore::Builder.client(:AppId) do
|
5
6
|
s = self.class # this is only for ruby 1.8!
|
6
7
|
use s::Timeout , 10
|
@@ -22,23 +23,7 @@ RestCore::Bing = RestCore::Builder.client(:AppId) do
|
|
22
23
|
end
|
23
24
|
end
|
24
25
|
|
25
|
-
|
26
|
-
def query
|
27
|
-
{'AppId' => self.AppId,
|
28
|
-
'JsonType' => 'raw' ,
|
29
|
-
'Version' => '2.2' }
|
30
|
-
end
|
31
|
-
|
32
|
-
def search_image term, query={}, opts={}
|
33
|
-
get('', {:Query => term, :Sources => 'Image'}.merge(query), opts)[
|
34
|
-
'SearchResponse']['Image']['Results'] || []
|
35
|
-
end
|
36
|
-
|
37
|
-
def search_image_urls term, query={}, opts={}
|
38
|
-
search_image(term, query, opts).map{ |i| i['MediaUrl'] }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
26
|
+
# http://msdn.microsoft.com/en-us/library/dd251042.aspx
|
42
27
|
class RestCore::Bing::Error < RestCore::Error
|
43
28
|
include RestCore
|
44
29
|
class MissingParameter < Bing::Error; end
|
@@ -87,6 +72,23 @@ class RestCore::Bing::Error < RestCore::Error
|
|
87
72
|
end
|
88
73
|
end
|
89
74
|
|
75
|
+
module RestCore::Bing::Client
|
76
|
+
def query
|
77
|
+
{'AppId' => self.AppId,
|
78
|
+
'JsonType' => 'raw' ,
|
79
|
+
'Version' => '2.2' }
|
80
|
+
end
|
81
|
+
|
82
|
+
def search_image term, query={}, opts={}
|
83
|
+
get('', {:Query => term, :Sources => 'Image'}.merge(query), opts)[
|
84
|
+
'SearchResponse']['Image']['Results'] || []
|
85
|
+
end
|
86
|
+
|
87
|
+
def search_image_urls term, query={}, opts={}
|
88
|
+
search_image(term, query, opts).map{ |i| i['MediaUrl'] }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
90
92
|
RestCore::Bing.send(:include, RestCore::Bing::Client)
|
91
93
|
require 'rest-core/client/bing/rails_util' if
|
92
94
|
Object.const_defined?(:Rails)
|
@@ -2,6 +2,8 @@
|
|
2
2
|
require 'rest-core'
|
3
3
|
require 'rest-core/util/hmac'
|
4
4
|
|
5
|
+
# https://developers.facebook.com/docs/reference/api
|
6
|
+
# https://developers.facebook.com/tools/explorer
|
5
7
|
RestCore::Facebook = RestCore::Builder.client(
|
6
8
|
:data, :app_id, :secret, :old_site) do
|
7
9
|
|
@@ -26,8 +28,7 @@ RestCore::Facebook = RestCore::Builder.client(
|
|
26
28
|
use s::JsonDecode , true
|
27
29
|
end
|
28
30
|
|
29
|
-
use s::Defaults , :
|
30
|
-
:old_site => 'https://api.facebook.com/'
|
31
|
+
use s::Defaults , :old_site => 'https://api.facebook.com/'
|
31
32
|
end
|
32
33
|
|
33
34
|
class RestCore::Facebook::Error < RestCore::Error
|
@@ -69,6 +70,10 @@ end
|
|
69
70
|
module RestCore::Facebook::Client
|
70
71
|
include RestCore
|
71
72
|
|
73
|
+
def me query={}, opts={}
|
74
|
+
get('me', query, opts)
|
75
|
+
end
|
76
|
+
|
72
77
|
def access_token
|
73
78
|
data['access_token'] || data['oauth_token'] if data.kind_of?(Hash)
|
74
79
|
end
|
@@ -179,9 +184,9 @@ module RestCore::Facebook::Client
|
|
179
184
|
end
|
180
185
|
|
181
186
|
def authorize! opts={}
|
182
|
-
|
187
|
+
payload = {:client_id => app_id, :client_secret => secret}.merge(opts)
|
183
188
|
self.data = ParseQuery.parse_query(
|
184
|
-
|
189
|
+
post('oauth/access_token', payload, {},
|
185
190
|
{:json_decode => false}.merge(opts)))
|
186
191
|
end
|
187
192
|
|
@@ -222,7 +227,11 @@ module RestCore::Facebook::Client
|
|
222
227
|
{}, {}, opts, &cb)
|
223
228
|
end
|
224
229
|
|
225
|
-
|
230
|
+
private
|
231
|
+
def default_data
|
232
|
+
{}
|
233
|
+
end
|
234
|
+
|
226
235
|
def build_env env={}
|
227
236
|
super(env.inject({}){ |r, (k, v)|
|
228
237
|
case k.to_s
|
@@ -44,7 +44,7 @@ module RestCore::Facebook::RailsUtil
|
|
44
44
|
# before, in that case, the fbs would be inside session,
|
45
45
|
# as we just saved it there
|
46
46
|
|
47
|
-
|
47
|
+
rc_facebook_check_fbs # check rc_facebook storage
|
48
48
|
|
49
49
|
if rc_options_get(RestCore::Facebook, :ensure_authorized) &&
|
50
50
|
!rc_facebook.authorized?
|
@@ -65,6 +65,8 @@ module RestCore::Facebook::RailsUtil
|
|
65
65
|
logger.warn("WARN: Facebook: #{error.inspect}")
|
66
66
|
|
67
67
|
if force_redirect || rc_facebook_auto_authorize?
|
68
|
+
rc_facebook_cleanup
|
69
|
+
|
68
70
|
@rc_facebook_authorize_url = rc_facebook.authorize_url(
|
69
71
|
{:redirect_uri => rc_facebook_normalized_request_uri,
|
70
72
|
:scope =>
|
@@ -72,9 +74,8 @@ module RestCore::Facebook::RailsUtil
|
|
72
74
|
merge(rc_options_get(RestCore::Facebook, :auto_authorize_options)))
|
73
75
|
|
74
76
|
logger.debug(
|
75
|
-
|
77
|
+
"DEBUG: Facebook: redirect to #{@rc_facebook_authorize_url}")
|
76
78
|
|
77
|
-
cookies.delete("fbs_#{rc_facebook.app_id}")
|
78
79
|
rc_facebook_authorize_redirect
|
79
80
|
end
|
80
81
|
end
|
@@ -132,7 +133,7 @@ module RestCore::Facebook::RailsUtil
|
|
132
133
|
" parsed: #{rc_facebook.data.inspect}")
|
133
134
|
|
134
135
|
if rc_facebook.authorized?
|
135
|
-
|
136
|
+
rc_facebook_write_fbs
|
136
137
|
else
|
137
138
|
logger.warn(
|
138
139
|
"WARN: Facebook: bad signed_request: #{params[:signed_request]}")
|
@@ -151,7 +152,7 @@ module RestCore::Facebook::RailsUtil
|
|
151
152
|
" #{rc_facebook.data.inspect}")
|
152
153
|
|
153
154
|
if rc_facebook.authorized?
|
154
|
-
|
155
|
+
rc_facebook_write_fbs
|
155
156
|
else
|
156
157
|
logger.warn("WARN: Facebook: bad session: #{params[:session]}")
|
157
158
|
end
|
@@ -182,7 +183,7 @@ module RestCore::Facebook::RailsUtil
|
|
182
183
|
"#{rc_facebook_normalized_request_uri}," \
|
183
184
|
" parsed: #{rc_facebook.data.inspect}")
|
184
185
|
|
185
|
-
|
186
|
+
rc_facebook_write_fbs if rc_facebook.authorized?
|
186
187
|
end
|
187
188
|
# ==================== end facebook check ======================
|
188
189
|
|
@@ -190,16 +191,16 @@ module RestCore::Facebook::RailsUtil
|
|
190
191
|
|
191
192
|
# ==================== begin check ================================
|
192
193
|
def rc_facebook_storage_key
|
193
|
-
"
|
194
|
+
"rc_facebook_#{rc_facebook.app_id}"
|
194
195
|
end
|
195
196
|
|
196
|
-
def
|
197
|
-
|
198
|
-
|
199
|
-
|
197
|
+
def rc_facebook_check_fbs
|
198
|
+
rc_facebook_check_handler # custom method to store fbs
|
199
|
+
rc_facebook_check_session # prefered way to store fbs
|
200
|
+
rc_facebook_check_cookies # in canvas, session might not work..
|
200
201
|
end
|
201
202
|
|
202
|
-
def
|
203
|
+
def rc_facebook_check_handler handler=
|
203
204
|
rc_options_get(RestCore::Facebook, :check_handler)
|
204
205
|
|
205
206
|
return if rc_facebook.authorized? || !handler
|
@@ -208,7 +209,7 @@ module RestCore::Facebook::RailsUtil
|
|
208
209
|
" #{rc_facebook.data.inspect}")
|
209
210
|
end
|
210
211
|
|
211
|
-
def
|
212
|
+
def rc_facebook_check_session
|
212
213
|
return if rc_facebook.authorized? ||
|
213
214
|
!rc_options_get(RestCore::Facebook, :write_session) ||
|
214
215
|
!(fbs = session[rc_facebook_storage_key])
|
@@ -218,7 +219,7 @@ module RestCore::Facebook::RailsUtil
|
|
218
219
|
" #{rc_facebook.data.inspect}")
|
219
220
|
end
|
220
221
|
|
221
|
-
def
|
222
|
+
def rc_facebook_check_cookies
|
222
223
|
return if rc_facebook.authorized? ||
|
223
224
|
!rc_options_get(RestCore::Facebook, :write_cookies) ||
|
224
225
|
!(fbs = cookies[rc_facebook_storage_key])
|
@@ -229,14 +230,13 @@ module RestCore::Facebook::RailsUtil
|
|
229
230
|
end
|
230
231
|
# ==================== end check ================================
|
231
232
|
# ==================== begin write ================================
|
232
|
-
def
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
rc_facebook_write_rg_cookies
|
233
|
+
def rc_facebook_write_fbs
|
234
|
+
rc_facebook_write_handler
|
235
|
+
rc_facebook_write_session
|
236
|
+
rc_facebook_write_cookies
|
237
237
|
end
|
238
238
|
|
239
|
-
def
|
239
|
+
def rc_facebook_write_handler handler=
|
240
240
|
rc_options_get(RestCore::Facebook, :write_handler)
|
241
241
|
|
242
242
|
return if !handler
|
@@ -244,13 +244,13 @@ module RestCore::Facebook::RailsUtil
|
|
244
244
|
logger.debug("DEBUG: Facebook: called write_handler: fbs => #{fbs}")
|
245
245
|
end
|
246
246
|
|
247
|
-
def
|
247
|
+
def rc_facebook_write_session
|
248
248
|
return if !rc_options_get(RestCore::Facebook, :write_session)
|
249
249
|
session[rc_facebook_storage_key] = fbs = rc_facebook.fbs
|
250
250
|
logger.debug("DEBUG: Facebook: wrote session: fbs => #{fbs}")
|
251
251
|
end
|
252
252
|
|
253
|
-
def
|
253
|
+
def rc_facebook_write_cookies
|
254
254
|
return if !rc_options_get(RestCore::Facebook, :write_cookies)
|
255
255
|
cookies[rc_facebook_storage_key] = fbs = rc_facebook.fbs
|
256
256
|
logger.debug("DEBUG: Facebook: wrote cookies: fbs => #{fbs}")
|
@@ -260,6 +260,13 @@ module RestCore::Facebook::RailsUtil
|
|
260
260
|
|
261
261
|
|
262
262
|
# ==================== begin misc ================================
|
263
|
+
def rc_facebook_cleanup
|
264
|
+
cookies.delete("fbs_#{rc_facebook.app_id}")
|
265
|
+
cookies.delete("fbsr_#{rc_facebook.app_id}")
|
266
|
+
cookies.delete(rc_facebook_storage_key)
|
267
|
+
session.delete(rc_facebook_storage_key)
|
268
|
+
end
|
269
|
+
|
263
270
|
def rc_facebook_normalized_request_uri
|
264
271
|
uri = if rc_facebook_in_canvas?
|
265
272
|
# rails 3 uses newer rack which has fullpath
|
@@ -3,6 +3,7 @@ require 'rest-core'
|
|
3
3
|
|
4
4
|
require 'time' # for Time.parse
|
5
5
|
|
6
|
+
# http://wiki.flurry.com
|
6
7
|
RestCore::Flurry = RestCore::Builder.client(:apiKey, :apiAccessCode) do
|
7
8
|
s = self.class # this is only for ruby 1.8!
|
8
9
|
use s::Timeout , 10
|
@@ -26,34 +27,47 @@ module RestCore::Flurry::Client
|
|
26
27
|
# "@createdDate"=>"2011-07-24", "@category"=>"Photography",
|
27
28
|
# "@version"=>"1.0", "@generatedDate"=>"9/15/11 7:08 AM",
|
28
29
|
# "version"=>[{"@name"=>"2.1", ...
|
29
|
-
def app_info query={}
|
30
|
-
get('appInfo/getApplication', query)
|
30
|
+
def app_info query={}, opts={}
|
31
|
+
get('appInfo/getApplication', query, opts)
|
31
32
|
end
|
32
33
|
|
33
34
|
# see: http://wiki.flurry.com/index.php?title=EventMetrics
|
34
|
-
# >> f.
|
35
|
-
# =>
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
35
|
+
# >> f.event_names
|
36
|
+
# => ["Products", "Save To Photo Library", ...]
|
37
|
+
def event_names query={}, opts={}
|
38
|
+
event_summary(query, opts).keys
|
39
|
+
end
|
40
|
+
|
41
|
+
# see: http://wiki.flurry.com/index.php?title=EventMetrics
|
42
|
+
# >> f.event_summary({}, :days => 7)
|
43
|
+
# => {"Products" => {"@usersLastWeek" => "948" ,
|
44
|
+
# "@usersLastMonth" => "2046",
|
45
|
+
# "@usersLastDay" => "4" , ...}}
|
46
|
+
def event_summary query={}, opts={}
|
47
|
+
array2hash(get('eventMetrics/Summary',
|
48
|
+
*calculate_query_and_opts(query, opts))['event'],
|
49
|
+
'@eventName')
|
50
|
+
end
|
51
|
+
|
52
|
+
# see: http://wiki.flurry.com/index.php?title=EventMetrics
|
53
|
+
# >> f.event_metrics('Products', {}, :days => 7)
|
54
|
+
# => [["2011-11-23", {"@uniqueUsers" => "12" ,
|
55
|
+
# "@totalSessions" => "108392" ,
|
56
|
+
# "@totalCount" => "30" ,
|
57
|
+
# "@duration" => "9754723"}],
|
58
|
+
# ["2011-11-22", {...}]]
|
59
|
+
def event_metrics name, query={}, opts={}
|
60
|
+
array2hash(get('eventMetrics/Event',
|
61
|
+
*calculate_query_and_opts(
|
62
|
+
{'eventName' => name}.merge(query), opts))['day'],
|
63
|
+
'@date').sort{ |a, b| b <=> a }
|
43
64
|
end
|
44
65
|
|
45
66
|
# see: http://wiki.flurry.com/index.php?title=AppMetrics
|
46
67
|
# >> f.metrics('ActiveUsers', {}, :weeks => 4)
|
47
68
|
# => [["2011-09-19", 6516], ["2011-09-18", 43920], ["2011-09-17", 45412],
|
48
69
|
# ["2011-09-16", 40972], ["2011-09-15", 37587], ["2011-09-14", 34918],
|
49
|
-
#
|
50
|
-
# ["2011-09-10", 44077], ["2011-09-09", 36683], ["2011-09-08", 34871],
|
51
|
-
# ["2011-09-07", 35960], ["2011-09-06", 35829], ["2011-09-05", 37777],
|
52
|
-
# ["2011-09-04", 40233], ["2011-09-03", 39306], ["2011-09-02", 33467],
|
53
|
-
# ["2011-09-01", 31558], ["2011-08-31", 32096], ["2011-08-30", 34076],
|
54
|
-
# ["2011-08-29", 34950], ["2011-08-28", 40456], ["2011-08-27", 41332],
|
55
|
-
# ["2011-08-26", 37737], ["2011-08-25", 34392], ["2011-08-24", 33560],
|
56
|
-
# ["2011-08-23", 34722]]
|
70
|
+
# ...]
|
57
71
|
def metrics path, query={}, opts={}
|
58
72
|
get("appMetrics/#{path}", *calculate_query_and_opts(query, opts)
|
59
73
|
)['day'].map{ |i| [i['@date'], i['@value'].to_i] }.reverse
|
@@ -80,7 +94,7 @@ module RestCore::Flurry::Client
|
|
80
94
|
}.reverse
|
81
95
|
end
|
82
96
|
|
83
|
-
def
|
97
|
+
def default_query
|
84
98
|
{'apiKey' => apiKey ,
|
85
99
|
'apiAccessCode' => apiAccessCode}
|
86
100
|
end
|
@@ -88,7 +102,7 @@ module RestCore::Flurry::Client
|
|
88
102
|
private
|
89
103
|
def calculate_query_and_opts query, opts
|
90
104
|
days = opts[:days] || (opts[:weeks] && opts[:weeks] * 7) ||
|
91
|
-
(opts[:months] && opts[:months] * 30)
|
105
|
+
(opts[:months] && opts[:months] * 30) || 7
|
92
106
|
|
93
107
|
startDate = query[:startDate] || (Time.now + 86400 - 86400*days).
|
94
108
|
strftime('%Y-%m-%d')
|
@@ -100,6 +114,12 @@ module RestCore::Flurry::Client
|
|
100
114
|
:endDate => endDate),
|
101
115
|
opts.reject{ |k, _| [:days, :weeks, :months].include?(k) }]
|
102
116
|
end
|
117
|
+
|
118
|
+
def array2hash array, key
|
119
|
+
array.inject({}){ |r, i|
|
120
|
+
r[i[key]] = i.reject{ |k, _| k == key }
|
121
|
+
r }
|
122
|
+
end
|
103
123
|
end
|
104
124
|
|
105
125
|
RestCore::Flurry.send(:include, RestCore::Flurry::Client)
|
@@ -1,13 +1,14 @@
|
|
1
1
|
|
2
2
|
require 'rest-core'
|
3
3
|
|
4
|
+
# http://developer.github.com/v3/
|
4
5
|
RestCore::Github = RestCore::Builder.client do
|
5
6
|
s = self.class # this is only for ruby 1.8!
|
6
7
|
use s::Timeout , 10
|
7
8
|
|
8
9
|
use s::DefaultSite , 'https://api.github.com/'
|
9
10
|
use s::DefaultHeaders, {'Accept' => 'application/json'}
|
10
|
-
use s::Oauth2Query ,
|
11
|
+
use s::Oauth2Query , nil
|
11
12
|
|
12
13
|
use s::CommonLogger , nil
|
13
14
|
use s::Cache , nil, 600 do
|
@@ -17,5 +18,14 @@ RestCore::Github = RestCore::Builder.client do
|
|
17
18
|
end
|
18
19
|
end
|
19
20
|
|
21
|
+
module RestCore::Github::Client
|
22
|
+
include RestCore
|
23
|
+
|
24
|
+
def me query={}, opts={}
|
25
|
+
get('user', query, opts)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
RestCore::Github.send(:include, RestCore::Github::Client)
|
20
30
|
require 'rest-core/client/github/rails_util' if
|
21
31
|
Object.const_defined?(:Rails)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
|
2
2
|
require 'rest-core'
|
3
3
|
|
4
|
-
|
4
|
+
# http://developer.linkedin.com/documents/linkedin-api-resource-map
|
5
|
+
RestCore::Linkedin = RestCore::Builder.client do
|
5
6
|
s = self.class # this is only for ruby 1.8!
|
6
7
|
use s::Timeout , 10
|
7
8
|
|
@@ -25,33 +26,17 @@ RestCore::Linkedin = RestCore::Builder.client(:data) do
|
|
25
26
|
use s::ErrorDetectorHttp
|
26
27
|
use s::JsonDecode , true
|
27
28
|
end
|
28
|
-
|
29
|
-
use s::Defaults , :data => lambda{{}}
|
30
29
|
end
|
31
30
|
|
32
31
|
module RestCore::Linkedin::Client
|
33
32
|
include RestCore
|
34
33
|
|
35
|
-
def
|
36
|
-
|
37
|
-
end
|
38
|
-
def oauth_token= token
|
39
|
-
data['oauth_token'] = token if data.kind_of?(Hash)
|
40
|
-
end
|
41
|
-
def oauth_token_secret
|
42
|
-
data['oauth_token_secret'] if data.kind_of?(Hash)
|
43
|
-
end
|
44
|
-
def oauth_token_secret= secret
|
45
|
-
data['oauth_token_secret'] = secret if data.kind_of?(Hash)
|
46
|
-
end
|
47
|
-
|
48
|
-
def me queries={}, opts={}
|
49
|
-
get('v1/people/~', queries, opts)
|
34
|
+
def me query={}, opts={}
|
35
|
+
get('v1/people/~', query, opts)
|
50
36
|
end
|
51
37
|
|
52
|
-
|
53
|
-
|
54
|
-
self.data = query
|
38
|
+
def authorize_url
|
39
|
+
url(authorize_path, :oauth_token => oauth_token, :format => false)
|
55
40
|
end
|
56
41
|
end
|
57
42
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
|
2
|
+
# http://developer.mixi.co.jp/connect/mixi_graph_api/
|
2
3
|
RestCore::Mixi = RestCore::Builder.client(
|
3
4
|
:data, :consumer_key, :consumer_secret, :redirect_uri) do
|
4
5
|
s = self.class # this is only for ruby 1.8!
|
@@ -7,7 +8,7 @@ RestCore::Mixi = RestCore::Builder.client(
|
|
7
8
|
use s::DefaultSite , 'http://api.mixi-platform.com/'
|
8
9
|
use s::DefaultHeaders, {'Accept' => 'application/json'}
|
9
10
|
|
10
|
-
use s::Oauth2Header , nil
|
11
|
+
use s::Oauth2Header , 'OAuth', nil
|
11
12
|
|
12
13
|
use s::CommonLogger , nil
|
13
14
|
use s::Cache , nil, 600 do
|
@@ -15,13 +16,15 @@ RestCore::Mixi = RestCore::Builder.client(
|
|
15
16
|
use s::ErrorDetectorHttp
|
16
17
|
use s::JsonDecode , true
|
17
18
|
end
|
18
|
-
|
19
|
-
use s::Defaults , :data => lambda{{}}
|
20
19
|
end
|
21
20
|
|
22
21
|
module RestCore::Mixi::Client
|
23
22
|
include RestCore
|
24
23
|
|
24
|
+
def me query={}, opts={}
|
25
|
+
get('2/people/@me/@self', query, opts)
|
26
|
+
end
|
27
|
+
|
25
28
|
def access_token
|
26
29
|
data['access_token'] if data.kind_of?(Hash)
|
27
30
|
end
|
@@ -45,6 +48,11 @@ module RestCore::Mixi::Client
|
|
45
48
|
|
46
49
|
self.data = post('https://secure.mixi-platform.com/2/token', pl, {}, opts)
|
47
50
|
end
|
51
|
+
|
52
|
+
private
|
53
|
+
def default_data
|
54
|
+
{}
|
55
|
+
end
|
48
56
|
end
|
49
57
|
|
50
58
|
RestCore::Mixi.send(:include, RestCore::Mixi::Client)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
|
2
2
|
require 'rest-core'
|
3
3
|
|
4
|
-
|
4
|
+
# https://dev.twitter.com/docs
|
5
|
+
RestCore::Twitter = RestCore::Builder.client do
|
5
6
|
s = self.class # this is only for ruby 1.8!
|
6
7
|
use s::Timeout , 10
|
7
8
|
|
@@ -18,10 +19,9 @@ RestCore::Twitter = RestCore::Builder.client(:data) do
|
|
18
19
|
use s::ErrorDetectorHttp
|
19
20
|
use s::JsonDecode , true
|
20
21
|
end
|
21
|
-
|
22
|
-
use s::Defaults , :data => lambda{{}}
|
23
22
|
end
|
24
23
|
|
24
|
+
# https://dev.twitter.com/docs/error-codes-responses
|
25
25
|
class RestCore::Twitter::Error < RestCore::Error
|
26
26
|
include RestCore
|
27
27
|
class ServerError < Twitter::Error; end
|
@@ -64,36 +64,24 @@ end
|
|
64
64
|
module RestCore::Twitter::Client
|
65
65
|
include RestCore
|
66
66
|
|
67
|
-
def
|
68
|
-
|
69
|
-
end
|
70
|
-
def oauth_token= token
|
71
|
-
data['oauth_token'] = token if data.kind_of?(Hash)
|
72
|
-
end
|
73
|
-
def oauth_token_secret
|
74
|
-
data['oauth_token_secret'] if data.kind_of?(Hash)
|
75
|
-
end
|
76
|
-
def oauth_token_secret= secret
|
77
|
-
data['oauth_token_secret'] = secret if data.kind_of?(Hash)
|
67
|
+
def me query={}, opts={}
|
68
|
+
get('1/account/verify_credentials.json', query, opts)
|
78
69
|
end
|
79
70
|
|
80
|
-
def tweet status, media=nil, opts={}
|
71
|
+
def tweet status, media=nil, payload={}, query={}, opts={}
|
81
72
|
if media
|
82
73
|
post('https://upload.twitter.com/1/statuses/update_with_media.json',
|
83
|
-
{:status => status, 'media[]' => media},
|
84
|
-
|
74
|
+
{:status => status, 'media[]' => media}.merge(payload),
|
75
|
+
query, opts)
|
85
76
|
else
|
86
|
-
post('1/statuses/update.json',
|
77
|
+
post('1/statuses/update.json',
|
78
|
+
{:status => status}.merge(payload),
|
79
|
+
query, opts)
|
87
80
|
end
|
88
81
|
end
|
89
82
|
|
90
|
-
def statuses user,
|
91
|
-
get('1/statuses/user_timeline.json', {:id => user}.merge(
|
92
|
-
end
|
93
|
-
|
94
|
-
private
|
95
|
-
def set_token query
|
96
|
-
self.data = query
|
83
|
+
def statuses user, query={}, opts={}
|
84
|
+
get('1/statuses/user_timeline.json', {:id => user}.merge(query), opts)
|
97
85
|
end
|
98
86
|
end
|
99
87
|
|
@@ -2,12 +2,160 @@
|
|
2
2
|
require 'rest-core/util/rails_util_util'
|
3
3
|
|
4
4
|
module RestCore::Twitter::DefaultAttributes
|
5
|
-
def default_log_method; Rails.logger.method(:debug); end
|
6
|
-
def default_cache
|
5
|
+
def default_log_method ; Rails.logger.method(:debug); end
|
6
|
+
def default_cache ; Rails.cache ; end
|
7
|
+
def default_auto_authorize ; false ; end
|
8
|
+
def default_ensure_authorized; false ; end
|
9
|
+
def default_write_session ; false ; end
|
10
|
+
def default_write_cookies ; false ; end
|
11
|
+
def default_write_handler ; nil ; end
|
12
|
+
def default_check_handler ; nil ; end
|
7
13
|
end
|
8
14
|
|
9
15
|
module RestCore::Twitter::RailsUtil
|
10
16
|
include RestCore::RailsUtilUtil
|
17
|
+
|
18
|
+
def self.included controller
|
19
|
+
# skip if included already, any better way to detect this?
|
20
|
+
return if controller.respond_to?(:rc_twitter, true)
|
21
|
+
super
|
22
|
+
controller.rescue_from(RestCore::Twitter::Error::Unauthorized,
|
23
|
+
:with => :rc_twitter_on_unauthorized)
|
24
|
+
end
|
25
|
+
|
26
|
+
def rc_twitter_setup options={}
|
27
|
+
super
|
28
|
+
|
29
|
+
rc_twitter_check_handler
|
30
|
+
rc_twitter_check_session
|
31
|
+
rc_twitter_check_cookies
|
32
|
+
rc_twitter_check_oauth_verifier
|
33
|
+
|
34
|
+
if rc_options_get(RestCore::Twitter, :ensure_authorized) &&
|
35
|
+
!rc_twitter.authorized?
|
36
|
+
|
37
|
+
rc_twitter_authorize('ensure authorized')
|
38
|
+
false # action halt, redirect to do authorize,
|
39
|
+
# eagerly, as opposed to auto_authorize
|
40
|
+
else
|
41
|
+
true # keep going
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def rc_twitter_on_unauthorized error=nil
|
46
|
+
rc_twitter_authorize(error, false)
|
47
|
+
end
|
48
|
+
|
49
|
+
def rc_twitter_authorize error=nil, force_redirect=true
|
50
|
+
logger.warn("WARN: Twitter: #{error.inspect}")
|
51
|
+
|
52
|
+
if force_redirect || rc_options_get(RestCore::Twitter, :auto_authorize)
|
53
|
+
rc_twitter_cleanup
|
54
|
+
|
55
|
+
callback = rc_twitter_normalized_request_uri
|
56
|
+
redirect_url = rc_twitter.authorize_url!(:oauth_callback => callback)
|
57
|
+
rc_twitter.oauth_callback = callback
|
58
|
+
rc_twitter_write_data_json
|
59
|
+
|
60
|
+
logger.debug(
|
61
|
+
"DEBUG: Twitter: redirect to #{redirect_url} from #{callback}")
|
62
|
+
|
63
|
+
redirect_to redirect_url
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# ==================== begin check ================================
|
68
|
+
def rc_twitter_storage_key
|
69
|
+
"rc_twitter_#{rc_twitter.consumer_key}"
|
70
|
+
end
|
71
|
+
|
72
|
+
def rc_twitter_check_oauth_verifier
|
73
|
+
return if !rc_twitter.oauth_callback || !params[:oauth_verifier]
|
74
|
+
|
75
|
+
rc_twitter.authorize!(:oauth_verifier => params[:oauth_verifier])
|
76
|
+
rc_twitter.data.delete('oauth_callback')
|
77
|
+
|
78
|
+
logger.debug(
|
79
|
+
"DEBUG: Twitter: detected oauth_verifier with #{request.url}," \
|
80
|
+
" parsed: #{rc_twitter.data.inspect}")
|
81
|
+
|
82
|
+
rc_twitter_write_data_json if rc_twitter.authorized?
|
83
|
+
end
|
84
|
+
|
85
|
+
def rc_twitter_check_handler handler=
|
86
|
+
rc_options_get(RestCore::Twitter, :check_handler)
|
87
|
+
|
88
|
+
return if rc_twitter.authorized? || !handler
|
89
|
+
rc_twitter.data_json = handler.call
|
90
|
+
logger.debug("DEBUG: Twitter: called check_handler, parsed:" \
|
91
|
+
" #{rc_twitter.data.inspect}")
|
92
|
+
end
|
93
|
+
|
94
|
+
def rc_twitter_check_session
|
95
|
+
return if rc_twitter.authorized? ||
|
96
|
+
!rc_options_get(RestCore::Twitter, :write_session) ||
|
97
|
+
!(data_json = session[rc_twitter_storage_key])
|
98
|
+
|
99
|
+
rc_twitter.data_json = data_json
|
100
|
+
logger.debug("DEBUG: Twitter: detected rc_twitter session, parsed:" \
|
101
|
+
" #{rc_twitter.data.inspect}")
|
102
|
+
end
|
103
|
+
|
104
|
+
def rc_twitter_check_cookies
|
105
|
+
return if rc_twitter.authorized? ||
|
106
|
+
!rc_options_get(RestCore::Twitter, :write_cookies) ||
|
107
|
+
!(data_json = cookies[rc_twitter_storage_key])
|
108
|
+
|
109
|
+
rc_twitter.data_json = data_json
|
110
|
+
logger.debug("DEBUG: Twitter: detected rc_twitter cookies, parsed:" \
|
111
|
+
" #{rc_twitter.data.inspect}")
|
112
|
+
end
|
113
|
+
# ==================== end check ================================
|
114
|
+
# ==================== begin write ================================
|
115
|
+
def rc_twitter_write_data_json
|
116
|
+
rc_twitter_write_handler
|
117
|
+
rc_twitter_write_session
|
118
|
+
rc_twitter_write_cookies
|
119
|
+
end
|
120
|
+
|
121
|
+
def rc_twitter_write_handler handler=
|
122
|
+
rc_options_get(RestCore::Twitter, :write_handler)
|
123
|
+
|
124
|
+
return if !handler
|
125
|
+
handler.call(data_json = rc_twitter.data_json)
|
126
|
+
logger.debug("DEBUG: Twitter: write_handler: data_json => #{data_json}")
|
127
|
+
end
|
128
|
+
|
129
|
+
def rc_twitter_write_session
|
130
|
+
return if !rc_options_get(RestCore::Twitter, :write_session)
|
131
|
+
session[rc_twitter_storage_key] = data_json = rc_twitter.data_json
|
132
|
+
logger.debug("DEBUG: Twitter: wrote session: data_json => #{data_json}")
|
133
|
+
end
|
134
|
+
|
135
|
+
def rc_twitter_write_cookies
|
136
|
+
return if !rc_options_get(RestCore::Twitter, :write_cookies)
|
137
|
+
cookies[rc_twitter_storage_key] = data_json = rc_twitter.data_json
|
138
|
+
logger.debug("DEBUG: Twitter: wrote cookies: data_json => #{data_json}")
|
139
|
+
end
|
140
|
+
# ==================== end write ================================
|
141
|
+
|
142
|
+
|
143
|
+
|
144
|
+
# ==================== begin misc ================================
|
145
|
+
def rc_twitter_cleanup
|
146
|
+
session.delete(rc_twitter_storage_key)
|
147
|
+
cookies.delete(rc_twitter_storage_key)
|
148
|
+
end
|
149
|
+
|
150
|
+
def rc_twitter_normalized_request_uri
|
151
|
+
URI.parse(request.url).tap{ |uri|
|
152
|
+
uri.query = uri.query.split('&').reject{ |q|
|
153
|
+
q =~ /^(oauth_verifier|oauth_token)\=/
|
154
|
+
}.join('&') if uri.query
|
155
|
+
uri.query = nil if uri.query.blank?
|
156
|
+
}.to_s
|
157
|
+
end
|
158
|
+
# ==================== end misc ================================
|
11
159
|
end
|
12
160
|
|
13
161
|
RestCore::Twitter::RailsUtil.init(Rails)
|
data/lib/rest-more/version.rb
CHANGED
data/rest-more.gemspec
CHANGED
@@ -2,13 +2,13 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = "rest-more"
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.8.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = [
|
9
9
|
"Cardinal Blue",
|
10
10
|
"Lin Jen-Shin (godfat)"]
|
11
|
-
s.date = "2011-11-
|
11
|
+
s.date = "2011-11-29"
|
12
12
|
s.description = "Various REST clients such as Facebook and Twitter built with [rest-core][]\n\n[rest-core]: https://github.com/cardinalblue/rest-core"
|
13
13
|
s.email = ["dev (XD) cardinalblue.com"]
|
14
14
|
s.executables = ["rib-rest-core"]
|
@@ -18,9 +18,11 @@ describe RC::Facebook do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
should 'do authorizing and parse result and save it in data' do
|
21
|
-
stub_request(:
|
22
|
-
|
23
|
-
|
21
|
+
stub_request(:post, 'https://graph.facebook.com/oauth/access_token'). \
|
22
|
+
with(:body => {'client_id' => '29' ,
|
23
|
+
'client_secret' => '18' ,
|
24
|
+
'redirect_uri' => 'http://zzz.tw',
|
25
|
+
'code' => 'zzz'}).
|
24
26
|
to_return(:body => 'access_token=baken&expires=2918')
|
25
27
|
|
26
28
|
result = {'access_token' => 'baken', 'expires' => '2918'}
|
@@ -9,74 +9,85 @@ describe RC::Flurry do
|
|
9
9
|
RR.verify
|
10
10
|
end
|
11
11
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
"@
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
12
|
+
describe 'metrics' do
|
13
|
+
before do
|
14
|
+
startDate = '2011-08-23'
|
15
|
+
endDate = '2011-09-19'
|
16
|
+
@flurry = RestCore::Flurry.new
|
17
|
+
stub(Time).now{ Time.parse(endDate, nil) }
|
18
|
+
stub_request(:get,
|
19
|
+
"http://api.flurry.com/appMetrics/ActiveUsers?" \
|
20
|
+
"startDate=#{startDate}&endDate=#{endDate}").
|
21
|
+
to_return(:body =>
|
22
|
+
'{"@startDate":"2011-08-23",
|
23
|
+
"@metric":"ActiveUsersByDay",
|
24
|
+
"@endDate":"2011-09-19",
|
25
|
+
"@version":"1.0",
|
26
|
+
"@generatedDate":"9/19/11 5:54 AM",
|
27
|
+
"day":
|
28
|
+
[{"@value":"34722","@date":"2011-08-23"},
|
29
|
+
{"@value":"33560","@date":"2011-08-24"},
|
30
|
+
{"@value":"34392","@date":"2011-08-25"},
|
31
|
+
{"@value":"37737","@date":"2011-08-26"},
|
32
|
+
{"@value":"41332","@date":"2011-08-27"},
|
33
|
+
{"@value":"40456","@date":"2011-08-28"},
|
34
|
+
{"@value":"34950","@date":"2011-08-29"},
|
35
|
+
{"@value":"34076","@date":"2011-08-30"},
|
36
|
+
{"@value":"32096","@date":"2011-08-31"},
|
37
|
+
{"@value":"31558","@date":"2011-09-01"},
|
38
|
+
{"@value":"33467","@date":"2011-09-02"},
|
39
|
+
{"@value":"39306","@date":"2011-09-03"},
|
40
|
+
{"@value":"40233","@date":"2011-09-04"},
|
41
|
+
{"@value":"37777","@date":"2011-09-05"},
|
42
|
+
{"@value":"35829","@date":"2011-09-06"},
|
43
|
+
{"@value":"35960","@date":"2011-09-07"},
|
44
|
+
{"@value":"34871","@date":"2011-09-08"},
|
45
|
+
{"@value":"36683","@date":"2011-09-09"},
|
46
|
+
{"@value":"44077","@date":"2011-09-10"},
|
47
|
+
{"@value":"45057","@date":"2011-09-11"},
|
48
|
+
{"@value":"37750","@date":"2011-09-12"},
|
49
|
+
{"@value":"35223","@date":"2011-09-13"},
|
50
|
+
{"@value":"34918","@date":"2011-09-14"},
|
51
|
+
{"@value":"37587","@date":"2011-09-15"},
|
52
|
+
{"@value":"40972","@date":"2011-09-16"},
|
53
|
+
{"@value":"45412","@date":"2011-09-17"},
|
54
|
+
{"@value":"43920","@date":"2011-09-18"},
|
55
|
+
{"@value":"6516","@date":"2011-09-19"}]}')
|
55
56
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
57
|
+
@active_users =
|
58
|
+
[["2011-09-19", 6516], ["2011-09-18", 43920], ["2011-09-17", 45412],
|
59
|
+
["2011-09-16", 40972], ["2011-09-15", 37587], ["2011-09-14", 34918],
|
60
|
+
["2011-09-13", 35223], ["2011-09-12", 37750], ["2011-09-11", 45057],
|
61
|
+
["2011-09-10", 44077], ["2011-09-09", 36683], ["2011-09-08", 34871],
|
62
|
+
["2011-09-07", 35960], ["2011-09-06", 35829], ["2011-09-05", 37777],
|
63
|
+
["2011-09-04", 40233], ["2011-09-03", 39306], ["2011-09-02", 33467],
|
64
|
+
["2011-09-01", 31558], ["2011-08-31", 32096], ["2011-08-30", 34076],
|
65
|
+
["2011-08-29", 34950], ["2011-08-28", 40456], ["2011-08-27", 41332],
|
66
|
+
["2011-08-26", 37737], ["2011-08-25", 34392], ["2011-08-24", 33560],
|
67
|
+
["2011-08-23", 34722]]
|
67
68
|
|
68
|
-
|
69
|
-
|
69
|
+
@weekly = [244548, 270227, 248513, 257149]
|
70
|
+
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
|
72
|
+
should 'metrics("ActiveUsers")' do
|
73
|
+
@flurry.metrics('ActiveUsers', {}, :weeks => 4).should.eq @active_users
|
74
|
+
end
|
74
75
|
|
75
|
-
|
76
|
-
|
76
|
+
should 'weekly(metrics("ActiveUsers"))' do
|
77
|
+
@flurry.weekly(@active_users).should.eq @weekly
|
78
|
+
end
|
79
|
+
|
80
|
+
should 'sum(weekly(metrics("ActiveUsers")))' do
|
81
|
+
@flurry.sum(@weekly).should.eq [1020437, 775889, 505662, 257149]
|
82
|
+
end
|
77
83
|
end
|
78
84
|
|
79
|
-
should '
|
80
|
-
|
85
|
+
should 'bring apiKey and apiAccessCode' do
|
86
|
+
stub_request(:get,
|
87
|
+
"http://api.flurry.com/?apiKey=a&apiAccessCode=b").
|
88
|
+
to_return(:body => '["ok"]')
|
89
|
+
|
90
|
+
f = RC::Flurry.new(:apiKey => 'a', :apiAccessCode => 'b')
|
91
|
+
f.get('').should.eq ['ok']
|
81
92
|
end
|
82
93
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rest-more
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-11-
|
13
|
+
date: 2011-11-29 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rest-core
|
17
|
-
requirement: &
|
17
|
+
requirement: &2158239560 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,7 +22,7 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2158239560
|
26
26
|
description: ! 'Various REST clients such as Facebook and Twitter built with [rest-core][]
|
27
27
|
|
28
28
|
|