rest-more 0.7.2.1 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/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
|
|