angellist_api 1.0.5 → 1.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +8 -0
- data/lib/angellist_api/client/activity_feeds.rb +7 -0
- data/lib/angellist_api/client/follows.rb +19 -8
- data/lib/angellist_api/client/messages.rb +2 -1
- data/lib/angellist_api/client/paths.rb +1 -0
- data/lib/angellist_api/client/press.rb +1 -0
- data/lib/angellist_api/client/reviews.rb +1 -0
- data/lib/angellist_api/client/tags.rb +9 -4
- data/lib/angellist_api/client/users.rb +2 -0
- data/lib/angellist_api/error.rb +10 -6
- data/lib/angellist_api/error/too_many_requests.rb +26 -0
- data/lib/angellist_api/response/raise_client_error.rb +7 -4
- data/lib/angellist_api/version.rb +1 -1
- data/spec/fixtures/cassettes/errors/forbidden.yml +53 -0
- data/spec/fixtures/cassettes/errors/too_many_requests.yml +53 -0
- data/spec/integration/errors_spec.rb +24 -0
- data/spec/support/http_headers.rb +8 -0
- data/spec/unit/lib/angellist_api/client/follows_spec.rb +12 -4
- data/spec/unit/lib/angellist_api/client/tags_spec.rb +6 -2
- data/spec/unit/lib/angellist_api/error_spec.rb +92 -83
- metadata +13 -5
- data/lib/angellist_api/error/enhance_your_calm.rb +0 -13
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,13 @@
|
|
1
1
|
## Master
|
2
2
|
|
3
|
+
## 1.0.6 - 14 April, 2013
|
4
|
+
|
5
|
+
- Properly raise a `TooManyRequests` error when a 403 contains a JSON error
|
6
|
+
object indicating rate limit overage (`EnhanceYourCalm` error aliased for
|
7
|
+
backwards compatibility) ([Ches Martin])
|
8
|
+
- Add missing options parameters for passing pagination params to endpoints that
|
9
|
+
support them ([Ches Martin])
|
10
|
+
|
3
11
|
## 1.0.5 - 27 March, 2013
|
4
12
|
|
5
13
|
- Fix inability to pass direction param for startup_roles ([Ches Martin])
|
@@ -11,11 +11,18 @@ module AngellistApi
|
|
11
11
|
# paginated and ordered by most recent story first.
|
12
12
|
#
|
13
13
|
# @requires_authentication Optional
|
14
|
+
# @paginated By explicit timestamp cursor
|
14
15
|
#
|
15
16
|
# @param options [Hash] A customizable set of options.
|
16
17
|
# @option options [Integer] :personalized If set to 1 and a user is
|
17
18
|
# authenticated, only activity from the authenticated user's social graph
|
18
19
|
# is returned.
|
20
|
+
# @option options [Integer] :since If a Unix timestamp is passed in via
|
21
|
+
# this parameter, only activity since that timestamp will be returned. A
|
22
|
+
# maximum of 25 items will be returned, starting with the oldest item. A
|
23
|
+
# cursor variable is also returned, which is the timestamp of the last
|
24
|
+
# item. You may call /feed again with since set to this value to get the
|
25
|
+
# next page of activity.
|
19
26
|
#
|
20
27
|
# @example
|
21
28
|
# AngellistApi.get_feed
|
@@ -38,6 +38,7 @@ module AngellistApi
|
|
38
38
|
# follow ids, such as those from the activity feed.
|
39
39
|
#
|
40
40
|
# @requires_authentication Optional
|
41
|
+
# @paginated No
|
41
42
|
#
|
42
43
|
# @param ids [Array] IDs of the follows to fetch.
|
43
44
|
#
|
@@ -52,26 +53,30 @@ module AngellistApi
|
|
52
53
|
# follower first.
|
53
54
|
#
|
54
55
|
# @requires_authentication No
|
56
|
+
# @paginated Yes
|
55
57
|
#
|
56
58
|
# @param [Integer] id The id of the given user.
|
59
|
+
# @param [Hash] options A customizable set of options.
|
57
60
|
#
|
58
61
|
# @example Get followers of user with ID 12345.
|
59
62
|
# AngellistApi.get_user_followers(12345)
|
60
|
-
def get_user_followers(id)
|
61
|
-
get("1/users/#{id}/followers")
|
63
|
+
def get_user_followers(id, options={})
|
64
|
+
get("1/users/#{id}/followers", options)
|
62
65
|
end
|
63
66
|
|
64
67
|
# Return the ids of the given user's followers, paginated and ordered by
|
65
68
|
# most recent follower first.
|
66
69
|
#
|
67
70
|
# @requires_authentication No
|
71
|
+
# @paginated Yes
|
68
72
|
#
|
69
73
|
# @param [Integer] id The id of the given user.
|
74
|
+
# @param [Hash] options A customizable set of options.
|
70
75
|
#
|
71
76
|
# @example Get IDs of the followers of user with ID 12345.
|
72
77
|
# AngellistApi.get_user_follower_ids(12345)
|
73
|
-
def get_user_follower_ids(id)
|
74
|
-
get("1/users/#{id}/followers/ids")
|
78
|
+
def get_user_follower_ids(id, options={})
|
79
|
+
get("1/users/#{id}/followers/ids", options)
|
75
80
|
end
|
76
81
|
|
77
82
|
# Return objects that the given user is following, paginated and ordered
|
@@ -79,6 +84,7 @@ module AngellistApi
|
|
79
84
|
# class of objects to return.
|
80
85
|
#
|
81
86
|
# @requires_authentication Optional
|
87
|
+
# @paginated Yes
|
82
88
|
#
|
83
89
|
# @param [Integer] id The id of the given user.
|
84
90
|
# @param [Hash] options A customizable set of options.
|
@@ -96,6 +102,7 @@ module AngellistApi
|
|
96
102
|
# /users/:id/followers/ids.
|
97
103
|
#
|
98
104
|
# @requires_authentication Optional
|
105
|
+
# @paginated Yes
|
99
106
|
#
|
100
107
|
# @param [Integer] id The id of the given user.
|
101
108
|
# @param [Hash] options A customizable set of options.
|
@@ -111,26 +118,30 @@ module AngellistApi
|
|
111
118
|
# recent follower first. Responds like GET /users/:id/followers.
|
112
119
|
#
|
113
120
|
# @requires_authentication Optional
|
121
|
+
# @paginated Yes
|
114
122
|
#
|
115
123
|
# @param [Integer] id The id of the given startup.
|
124
|
+
# @param [Hash] options A customizable set of options.
|
116
125
|
#
|
117
126
|
# @example Get followers of startup with ID 1234.
|
118
127
|
# AngellistApi.get_startup_followers(1234)
|
119
|
-
def get_startup_followers(id)
|
120
|
-
get("1/startups/#{id}/followers")
|
128
|
+
def get_startup_followers(id, options={})
|
129
|
+
get("1/startups/#{id}/followers", options)
|
121
130
|
end
|
122
131
|
|
123
132
|
# Returns the ids of the given startup's followers, paginated and ordered
|
124
133
|
# by most recent follower first. Responds like GET /users/:id/followers.
|
125
134
|
#
|
126
135
|
# @requires_authentication Optional
|
136
|
+
# @paginated Yes
|
127
137
|
#
|
128
138
|
# @param [Integer] id The id of the given user.
|
139
|
+
# @param [Hash] options A customizable set of options.
|
129
140
|
#
|
130
141
|
# @example Get IDs of followers of startup with ID 1234.
|
131
142
|
# AngellistApi.get_startup_follower_ids(1234)
|
132
|
-
def get_startup_follower_ids(id)
|
133
|
-
get("1/startups/#{id}/followers/ids")
|
143
|
+
def get_startup_follower_ids(id, options={})
|
144
|
+
get("1/startups/#{id}/followers/ids", options)
|
134
145
|
end
|
135
146
|
end
|
136
147
|
end
|
@@ -8,7 +8,8 @@ module AngellistApi
|
|
8
8
|
# Returns threads that the authenticated user is involved in. A "thread"
|
9
9
|
# is a conversation between two users, where each message is tagged with
|
10
10
|
# the same thread_id. If the authenticated user has any unread messages
|
11
|
-
#in the thread, the viewed attribute will be false. Requires scope
|
11
|
+
# in the thread, the viewed attribute will be false. Requires scope
|
12
|
+
# "message".
|
12
13
|
#
|
13
14
|
# @requires_authentication Yes
|
14
15
|
# @paginated Yes
|
@@ -13,6 +13,7 @@ module AngellistApi
|
|
13
13
|
# - do not use user_ids and startup_ids at the same time
|
14
14
|
#
|
15
15
|
# @requires_authentication Yes
|
16
|
+
# @paginated No
|
16
17
|
#
|
17
18
|
# @param options [Hash] A customizable set of options.
|
18
19
|
# @option options [Array<Integer>] :user_ids Show paths between you and
|
@@ -9,6 +9,7 @@ module AngellistApi
|
|
9
9
|
# Also returns the total count of positive reviews.
|
10
10
|
#
|
11
11
|
# @requires_authentication Optional
|
12
|
+
# @paginated Yes
|
12
13
|
#
|
13
14
|
# @param [Hash] options A customizable set of options.
|
14
15
|
# @option options [Integer] :user_id user_id of the desired user. If none
|
@@ -21,28 +21,32 @@ module AngellistApi
|
|
21
21
|
# descending.
|
22
22
|
#
|
23
23
|
# @requires_authentication No
|
24
|
+
# @paginated Yes
|
24
25
|
#
|
25
26
|
# @param [Integer] id The id of the desired tag. Currently only works for
|
26
27
|
# tags of type MarketTag or LocationTag.
|
28
|
+
# @param [Hash] options A customizable set of options.
|
27
29
|
#
|
28
30
|
# @example Get children of a tag.
|
29
31
|
# AngellistApi.get_tag_children(1654)
|
30
|
-
def get_tag_children(id)
|
31
|
-
get("1/tags/#{id}/children")
|
32
|
+
def get_tag_children(id, options={})
|
33
|
+
get("1/tags/#{id}/children", options)
|
32
34
|
end
|
33
35
|
|
34
36
|
# Returns parents of the given tag. For more details, see the
|
35
37
|
# documentation for GET /tags/:id/children.
|
36
38
|
#
|
37
39
|
# @requires_authentication No
|
40
|
+
# @paginated Yes
|
38
41
|
#
|
39
42
|
# @param [Integer] id The id of the desired tag. Currently only works for
|
40
43
|
# tags of type MarketTag or LocationTag.
|
44
|
+
# @param [Hash] options A customizable set of options.
|
41
45
|
#
|
42
46
|
# @example Get parents of a tag.
|
43
47
|
# AngellistApi.get_tag_parents(1654)
|
44
|
-
def get_tag_parents(id)
|
45
|
-
get("1/tags/#{id}/parents")
|
48
|
+
def get_tag_parents(id, options={})
|
49
|
+
get("1/tags/#{id}/parents", options)
|
46
50
|
end
|
47
51
|
|
48
52
|
# Returns startups that are tagged with the given tag or a child of the
|
@@ -50,6 +54,7 @@ module AngellistApi
|
|
50
54
|
# parameter.
|
51
55
|
#
|
52
56
|
# @requires_authentication Optional
|
57
|
+
# @paginated Yes
|
53
58
|
#
|
54
59
|
# @param [Hash] options A customizable set of options.
|
55
60
|
# @option options [String] :order May be one of popularity, asc or desc.
|
@@ -19,6 +19,7 @@ module AngellistApi
|
|
19
19
|
# Get information for a batch of up to 50 users given a list of user IDs.
|
20
20
|
#
|
21
21
|
# @requires_authentication No
|
22
|
+
# @pagination No
|
22
23
|
#
|
23
24
|
# @param [Array] ids IDs of the users to fetch.
|
24
25
|
#
|
@@ -32,6 +33,7 @@ module AngellistApi
|
|
32
33
|
# Search for a user given a URL slug. Responds like GET /users/:id.
|
33
34
|
#
|
34
35
|
# @requires_authentication No
|
36
|
+
# @pagination No
|
35
37
|
#
|
36
38
|
# @param [Hash] options A customizable set of options.
|
37
39
|
# @option options [String] :slug The URL slug of the desired user.
|
data/lib/angellist_api/error.rb
CHANGED
@@ -8,29 +8,33 @@ module AngellistApi
|
|
8
8
|
# @param [String] message
|
9
9
|
# @param [Hash] http_headers
|
10
10
|
# @return [AngellistApi::Error]
|
11
|
-
def initialize(message, http_headers)
|
12
|
-
@http_headers =
|
11
|
+
def initialize(message, http_headers={})
|
12
|
+
@http_headers = http_headers
|
13
13
|
super message
|
14
14
|
end
|
15
15
|
|
16
16
|
# @return [Time]
|
17
17
|
def ratelimit_reset
|
18
|
-
|
18
|
+
reset = http_headers['x-ratelimit-reset']
|
19
|
+
Time.at(reset.to_i) if reset
|
19
20
|
end
|
20
21
|
|
21
22
|
# @return [Integer]
|
22
23
|
def ratelimit_limit
|
23
|
-
|
24
|
+
limit = http_headers['x-ratelimit-limit']
|
25
|
+
limit.to_i if limit
|
24
26
|
end
|
25
27
|
|
26
28
|
# @return [Integer]
|
27
29
|
def ratelimit_remaining
|
28
|
-
|
30
|
+
remaining = http_headers['x-ratelimit-remaining']
|
31
|
+
remaining.to_i if remaining
|
29
32
|
end
|
30
33
|
|
31
34
|
# @return [Integer]
|
32
35
|
def retry_after
|
33
|
-
[(ratelimit_reset - Time.now).ceil, 0].max
|
36
|
+
[(ratelimit_reset - Time.now).ceil, 0].max if ratelimit_reset
|
34
37
|
end
|
35
38
|
end
|
36
39
|
end
|
40
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'angellist_api/error'
|
2
|
+
|
3
|
+
module AngellistApi
|
4
|
+
# Raised when AngellistApi returns the HTTP status code 403 with "over_limit"
|
5
|
+
# in the response.
|
6
|
+
#
|
7
|
+
# @note We've inquired with the AngelList API team about using a 429 status
|
8
|
+
# in the future.
|
9
|
+
class Error
|
10
|
+
class TooManyRequests < AngellistApi::Error
|
11
|
+
# The number of seconds your application should wait before requesting data
|
12
|
+
# from the API again.
|
13
|
+
#
|
14
|
+
# This may not be supported by AngelList currently but is suggested in RFC
|
15
|
+
# 6585 for the 429 status code.
|
16
|
+
def retry_after
|
17
|
+
retry_after = http_headers['retry-after']
|
18
|
+
retry_after.to_i if retry_after
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
# Backwards compatability
|
23
|
+
EnhanceYourCalm = TooManyRequests
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'faraday'
|
2
2
|
require 'angellist_api/error/bad_request'
|
3
|
-
require 'angellist_api/error/
|
3
|
+
require 'angellist_api/error/too_many_requests'
|
4
4
|
require 'angellist_api/error/forbidden'
|
5
5
|
require 'angellist_api/error/not_acceptable'
|
6
6
|
require 'angellist_api/error/not_found'
|
@@ -16,13 +16,15 @@ module AngellistApi
|
|
16
16
|
when 401
|
17
17
|
raise AngellistApi::Error::Unauthorized.new(error_message(env), env[:response_headers])
|
18
18
|
when 403
|
19
|
-
|
19
|
+
if env[:body]['error'] == 'over_limit'
|
20
|
+
raise AngellistApi::Error::TooManyRequests.new(error_message(env), env[:response_headers])
|
21
|
+
else
|
22
|
+
raise AngellistApi::Error::Forbidden.new(error_message(env), env[:response_headers])
|
23
|
+
end
|
20
24
|
when 404
|
21
25
|
raise AngellistApi::Error::NotFound.new(error_message(env), env[:response_headers])
|
22
26
|
when 406
|
23
27
|
raise AngellistApi::Error::NotAcceptable.new(error_message(env), env[:response_headers])
|
24
|
-
when 420
|
25
|
-
raise AngellistApi::Error::EnhanceYourCalm.new(error_message(env), env[:response_headers])
|
26
28
|
end
|
27
29
|
end
|
28
30
|
|
@@ -49,3 +51,4 @@ module AngellistApi
|
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
54
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://api.angel.co/1/me
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
User-Agent:
|
13
|
+
- AngellistApi Ruby Gem 1.0.5
|
14
|
+
Authorization:
|
15
|
+
- Bearer <ANGELLIST_ACCESS_TOKEN>
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 403
|
19
|
+
message: !!null
|
20
|
+
headers:
|
21
|
+
server:
|
22
|
+
- nginx/1.0.6
|
23
|
+
date:
|
24
|
+
- Sun, 14 Apr 2013 06:45:44 GMT
|
25
|
+
content-type:
|
26
|
+
- application/json; charset=utf-8
|
27
|
+
transfer-encoding:
|
28
|
+
- chunked
|
29
|
+
connection:
|
30
|
+
- close
|
31
|
+
vary:
|
32
|
+
- Accept-Encoding, Accept-Encoding
|
33
|
+
status:
|
34
|
+
- '403'
|
35
|
+
x-ratelimit-limit:
|
36
|
+
- '2000'
|
37
|
+
x-ratelimit-remaining:
|
38
|
+
- '2000'
|
39
|
+
x-thanks:
|
40
|
+
- For using AngelList. Rock on.
|
41
|
+
x-runtime:
|
42
|
+
- '35'
|
43
|
+
etag:
|
44
|
+
- ! '"0c13384ccaf0ae7c9e1ff289e0070619"'
|
45
|
+
cache-control:
|
46
|
+
- private, max-age=0, must-revalidate
|
47
|
+
body:
|
48
|
+
encoding: ASCII-8BIT
|
49
|
+
string: ! '{"error":"forbidden","error_description":""}'
|
50
|
+
http_version: !!null
|
51
|
+
recorded_at: Sun, 14 Apr 2013 06:45:44 GMT
|
52
|
+
recorded_with: VCR 2.4.0
|
53
|
+
|
@@ -0,0 +1,53 @@
|
|
1
|
+
---
|
2
|
+
http_interactions:
|
3
|
+
- request:
|
4
|
+
method: get
|
5
|
+
uri: https://api.angel.co/1/me
|
6
|
+
body:
|
7
|
+
encoding: US-ASCII
|
8
|
+
string: ''
|
9
|
+
headers:
|
10
|
+
Accept:
|
11
|
+
- application/json
|
12
|
+
User-Agent:
|
13
|
+
- AngellistApi Ruby Gem 1.0.5
|
14
|
+
Authorization:
|
15
|
+
- Bearer <ANGELLIST_ACCESS_TOKEN>
|
16
|
+
response:
|
17
|
+
status:
|
18
|
+
code: 403
|
19
|
+
message: !!null
|
20
|
+
headers:
|
21
|
+
server:
|
22
|
+
- nginx/1.0.6
|
23
|
+
date:
|
24
|
+
- Sun, 14 Apr 2013 06:45:44 GMT
|
25
|
+
content-type:
|
26
|
+
- application/json; charset=utf-8
|
27
|
+
transfer-encoding:
|
28
|
+
- chunked
|
29
|
+
connection:
|
30
|
+
- close
|
31
|
+
vary:
|
32
|
+
- Accept-Encoding, Accept-Encoding
|
33
|
+
status:
|
34
|
+
- '403'
|
35
|
+
x-ratelimit-limit:
|
36
|
+
- '2000'
|
37
|
+
x-ratelimit-remaining:
|
38
|
+
- '0'
|
39
|
+
x-thanks:
|
40
|
+
- For using AngelList. Rock on.
|
41
|
+
x-runtime:
|
42
|
+
- '35'
|
43
|
+
etag:
|
44
|
+
- ! '"0c13384ccaf0ae7c9e1ff289e0070619"'
|
45
|
+
cache-control:
|
46
|
+
- private, max-age=0, must-revalidate
|
47
|
+
body:
|
48
|
+
encoding: ASCII-8BIT
|
49
|
+
string: ! '{"error":"over_limit","error_description":"You are currently over your rate limit."}'
|
50
|
+
http_version: !!null
|
51
|
+
recorded_at: Sun, 14 Apr 2013 06:45:44 GMT
|
52
|
+
recorded_with: VCR 2.4.0
|
53
|
+
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe 'Errors' do
|
4
|
+
let(:client) { AngellistApi::Client.new }
|
5
|
+
|
6
|
+
describe AngellistApi::Error::TooManyRequests do
|
7
|
+
context 'when response is an over rate limit error',
|
8
|
+
:vcr => { :cassette_name => 'errors/too_many_requests' } do
|
9
|
+
|
10
|
+
it 'is raised' do
|
11
|
+
expect { client.me }.to raise_error described_class
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
context 'when response is some other 403 Forbidden error',
|
16
|
+
:vcr => { :cassette_name => 'errors/forbidden' } do
|
17
|
+
|
18
|
+
it 'is not raised' do
|
19
|
+
expect { client.me }.to raise_error AngellistApi::Error::Forbidden
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
@@ -32,7 +32,9 @@ describe AngellistApi::Client::Follows do
|
|
32
32
|
describe "#get_user_followers" do
|
33
33
|
it "gets 1/users/<id>/followers" do
|
34
34
|
id = "123"
|
35
|
-
client.should_receive(:get).
|
35
|
+
client.should_receive(:get).
|
36
|
+
with("1/users/#{id}/followers", {}).
|
37
|
+
and_return("success")
|
36
38
|
client.get_user_followers(id).should == "success"
|
37
39
|
end
|
38
40
|
end
|
@@ -40,7 +42,9 @@ describe AngellistApi::Client::Follows do
|
|
40
42
|
describe "#get_user_follower_ids" do
|
41
43
|
it "gets 1/users/<id>/followers/ids" do
|
42
44
|
id = "123"
|
43
|
-
client.should_receive(:get).
|
45
|
+
client.should_receive(:get).
|
46
|
+
with("1/users/#{id}/followers/ids", {}).
|
47
|
+
and_return("success")
|
44
48
|
client.get_user_follower_ids(id).should == "success"
|
45
49
|
end
|
46
50
|
end
|
@@ -66,7 +70,9 @@ describe AngellistApi::Client::Follows do
|
|
66
70
|
describe "#get_startup_followers" do
|
67
71
|
it "gets 1/startups/<id>/followers" do
|
68
72
|
id = "123"
|
69
|
-
client.should_receive(:get).
|
73
|
+
client.should_receive(:get).
|
74
|
+
with("1/startups/#{id}/followers", {}).
|
75
|
+
and_return("success")
|
70
76
|
client.get_startup_followers(id).should == "success"
|
71
77
|
end
|
72
78
|
end
|
@@ -74,7 +80,9 @@ describe AngellistApi::Client::Follows do
|
|
74
80
|
describe "#get_startup_follower_ids" do
|
75
81
|
it "gets 1/startups/<id>/followers/ids" do
|
76
82
|
id = "123"
|
77
|
-
client.should_receive(:get).
|
83
|
+
client.should_receive(:get).
|
84
|
+
with("1/startups/#{id}/followers/ids", {}).
|
85
|
+
and_return("success")
|
78
86
|
client.get_startup_follower_ids(id).should == "success"
|
79
87
|
end
|
80
88
|
end
|
@@ -14,7 +14,9 @@ describe AngellistApi::Client::Tags do
|
|
14
14
|
describe "#get_tag_children" do
|
15
15
|
it "gets 1/tags/<id>/children" do
|
16
16
|
id = "123"
|
17
|
-
client.should_receive(:get).
|
17
|
+
client.should_receive(:get).
|
18
|
+
with("1/tags/#{id}/children", {}).
|
19
|
+
and_return("success")
|
18
20
|
client.get_tag_children(id).should == "success"
|
19
21
|
end
|
20
22
|
end
|
@@ -22,7 +24,9 @@ describe AngellistApi::Client::Tags do
|
|
22
24
|
describe "#get_tag_parents" do
|
23
25
|
it "gets 1/tags/<id>/parents" do
|
24
26
|
id = "123"
|
25
|
-
client.should_receive(:get).
|
27
|
+
client.should_receive(:get).
|
28
|
+
with("1/tags/#{id}/parents", {}).
|
29
|
+
and_return("success")
|
26
30
|
client.get_tag_parents(id).should == "success"
|
27
31
|
end
|
28
32
|
end
|
@@ -1,124 +1,133 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe AngellistApi::Error do
|
4
|
+
include HttpHeaders
|
4
5
|
|
5
|
-
describe
|
6
|
-
|
7
|
-
|
8
|
-
expect { AngellistApi::Error.new(nil, :header => "data") }.to_not raise_error
|
9
|
-
end
|
10
|
-
|
11
|
-
it "builds an error with the given message" do
|
12
|
-
error = AngellistApi::Error.new("bad data", :header => 'data')
|
13
|
-
error.message.should == "bad data"
|
14
|
-
end
|
6
|
+
describe '#new' do
|
7
|
+
specify 'message parameter can be nil' do
|
8
|
+
expect { AngellistApi::Error.new(nil, :header => 'data') }.to_not raise_error
|
15
9
|
end
|
16
10
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
it "raises an exception if the params cant be converted to a hash" do
|
23
|
-
expect { AngellistApi::Error.new("some message", "header") }.to raise_error(ArgumentError, "odd number of arguments for Hash")
|
24
|
-
end
|
11
|
+
it 'builds an error with the given message' do
|
12
|
+
error = AngellistApi::Error.new('bad data', :header => 'data')
|
13
|
+
error.message.should == 'bad data'
|
14
|
+
end
|
25
15
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
end
|
16
|
+
it 'sets http_headers attribute' do
|
17
|
+
error = AngellistApi::Error.new('some message', :some => 'value')
|
18
|
+
error.http_headers.should == { :some => 'value' }
|
30
19
|
end
|
31
20
|
end
|
32
21
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
22
|
+
# NOTE: AngelList doesn't actually support this yet...
|
23
|
+
describe '#ratelimit_reset' do
|
24
|
+
subject { described_class.new('message', headers).ratelimit_reset }
|
25
|
+
|
26
|
+
context 'with X-RateLimit-Reset header set' do
|
27
|
+
let(:unixtime) { Time.now.to_i }
|
28
|
+
let(:headers) { headerize('X-RateLimit-Reset' => unixtime) }
|
40
29
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
error.ratelimit_reset.should == Time.at(time)
|
30
|
+
it 'returns the time of reset' do
|
31
|
+
subject.should == Time.at(unixtime)
|
32
|
+
end
|
45
33
|
end
|
46
34
|
|
47
|
-
|
48
|
-
|
49
|
-
|
35
|
+
context 'with X-RateLimit-Reset unset' do
|
36
|
+
let(:headers) { headerize({}) }
|
37
|
+
it { should be_nil }
|
50
38
|
end
|
51
39
|
end
|
52
40
|
|
53
|
-
describe
|
54
|
-
|
55
|
-
error = AngellistApi::Error.new("message", {'x-ratelimit-limit' => 500, 'X-RateLimit-Limit' => 400})
|
56
|
-
error.ratelimit_limit.should == 500
|
57
|
-
end
|
41
|
+
describe '#ratelimit_limit' do
|
42
|
+
subject { described_class.new('message', headers).ratelimit_limit }
|
58
43
|
|
59
|
-
|
60
|
-
|
61
|
-
|
44
|
+
context 'with X-RateLimit-Limit header set' do
|
45
|
+
let(:limit) { '1000' }
|
46
|
+
let(:headers) { headerize('X-RateLimit-Limit' => limit) }
|
47
|
+
|
48
|
+
it 'returns the limit as an integer' do
|
49
|
+
subject.should eq 1000
|
50
|
+
end
|
62
51
|
end
|
63
52
|
|
64
|
-
|
65
|
-
|
66
|
-
|
53
|
+
context 'with X-RateLimit-Limit unset' do
|
54
|
+
let(:headers) { headerize({}) }
|
55
|
+
it { should be_nil }
|
67
56
|
end
|
68
57
|
end
|
69
58
|
|
70
|
-
describe
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
59
|
+
describe '#ratelimit_remaining' do
|
60
|
+
subject { described_class.new('message', headers).ratelimit_remaining }
|
61
|
+
|
62
|
+
context 'with X-RateLimit-Remaining header set' do
|
63
|
+
let(:remaining) { '22' }
|
64
|
+
let(:headers) { headerize('X-RateLimit-Remaining' => remaining) }
|
75
65
|
|
76
|
-
|
77
|
-
|
78
|
-
|
66
|
+
it 'returns remaining request count as an integer' do
|
67
|
+
subject.should eq 22
|
68
|
+
end
|
79
69
|
end
|
80
70
|
|
81
|
-
|
82
|
-
|
83
|
-
|
71
|
+
context 'with X-RateLimit-Remaining unset' do
|
72
|
+
let(:headers) { headerize({}) }
|
73
|
+
it { should be_nil }
|
84
74
|
end
|
85
75
|
end
|
86
76
|
|
87
|
-
|
88
|
-
|
89
|
-
|
77
|
+
# NOTE: AngelList doesn't actually support this yet...
|
78
|
+
describe '#retry_after' do
|
79
|
+
subject { described_class.new('message', headerize({})).retry_after }
|
80
|
+
let(:now) { Time.now }
|
81
|
+
|
82
|
+
before { Timecop.freeze(now) }
|
83
|
+
after { Timecop.return }
|
90
84
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
85
|
+
context 'when limit reset time is known' do
|
86
|
+
let(:reset_at) { now + 3600 }
|
87
|
+
|
88
|
+
before do
|
89
|
+
described_class.any_instance.stub(:ratelimit_reset).and_return(reset_at)
|
96
90
|
end
|
97
91
|
|
98
|
-
it
|
99
|
-
|
100
|
-
error.should_receive(:ratelimit_reset) { Time.now - 3600 }
|
101
|
-
error.retry_after.should == 0
|
102
|
-
end
|
92
|
+
it 'gives time in seconds until it is acceptable to make another call' do
|
93
|
+
subject.should eq reset_at - now
|
103
94
|
end
|
104
95
|
end
|
105
96
|
|
106
|
-
context
|
107
|
-
it
|
108
|
-
|
109
|
-
error.retry_after.should == 12
|
110
|
-
end
|
97
|
+
context 'when limit reset time is not known' do
|
98
|
+
it { should be_nil }
|
99
|
+
end
|
111
100
|
|
112
|
-
|
113
|
-
|
114
|
-
error.retry_after.should == 16
|
115
|
-
end
|
101
|
+
context 'when limit reset time is past' do
|
102
|
+
let(:reset_at) { now - 3600 }
|
116
103
|
|
117
|
-
|
118
|
-
|
119
|
-
error.retry_after.should == 0
|
104
|
+
before do
|
105
|
+
described_class.any_instance.stub(:ratelimit_reset).and_return(reset_at)
|
120
106
|
end
|
107
|
+
|
108
|
+
it { should be_zero }
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
# NOTE: AngelList doesn't actually support this yet...
|
114
|
+
describe AngellistApi::Error::TooManyRequests do
|
115
|
+
include HttpHeaders
|
116
|
+
|
117
|
+
subject { described_class.new('message', headers).retry_after }
|
118
|
+
|
119
|
+
context 'with Retry-After header set' do
|
120
|
+
let(:wait) { '12' }
|
121
|
+
let(:headers) { headerize('Retry-After' => wait) }
|
122
|
+
|
123
|
+
it 'returns the seconds to wait until retrying' do
|
124
|
+
subject.should == 12
|
121
125
|
end
|
122
126
|
end
|
127
|
+
|
128
|
+
context 'with Retry-After unset' do
|
129
|
+
let(:headers) { headerize({}) }
|
130
|
+
it { should be_nil }
|
131
|
+
end
|
123
132
|
end
|
124
133
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: angellist_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2013-
|
13
|
+
date: 2013-04-14 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: hashie
|
@@ -203,12 +203,12 @@ files:
|
|
203
203
|
- lib/angellist_api/core_ext/hash.rb
|
204
204
|
- lib/angellist_api/error/bad_gateway.rb
|
205
205
|
- lib/angellist_api/error/bad_request.rb
|
206
|
-
- lib/angellist_api/error/enhance_your_calm.rb
|
207
206
|
- lib/angellist_api/error/forbidden.rb
|
208
207
|
- lib/angellist_api/error/internal_server_error.rb
|
209
208
|
- lib/angellist_api/error/not_acceptable.rb
|
210
209
|
- lib/angellist_api/error/not_found.rb
|
211
210
|
- lib/angellist_api/error/service_unavailable.rb
|
211
|
+
- lib/angellist_api/error/too_many_requests.rb
|
212
212
|
- lib/angellist_api/error/unauthorized.rb
|
213
213
|
- lib/angellist_api/error.rb
|
214
214
|
- lib/angellist_api/request/angellist_api_oauth.rb
|
@@ -224,6 +224,8 @@ files:
|
|
224
224
|
- README.md
|
225
225
|
- CHANGELOG.md
|
226
226
|
- spec/fixtures/cassettes/activity_feeds.yml
|
227
|
+
- spec/fixtures/cassettes/errors/forbidden.yml
|
228
|
+
- spec/fixtures/cassettes/errors/too_many_requests.yml
|
227
229
|
- spec/fixtures/cassettes/follows.yml
|
228
230
|
- spec/fixtures/cassettes/jobs.yml
|
229
231
|
- spec/fixtures/cassettes/messages.yml
|
@@ -237,6 +239,7 @@ files:
|
|
237
239
|
- spec/fixtures/cassettes/tags.yml
|
238
240
|
- spec/fixtures/cassettes/users.yml
|
239
241
|
- spec/integration/activity_feeds_spec.rb
|
242
|
+
- spec/integration/errors_spec.rb
|
240
243
|
- spec/integration/follows_spec.rb
|
241
244
|
- spec/integration/jobs_spec.rb
|
242
245
|
- spec/integration/messages_spec.rb
|
@@ -251,6 +254,7 @@ files:
|
|
251
254
|
- spec/integration/users_spec.rb
|
252
255
|
- spec/spec_helper.rb
|
253
256
|
- spec/support/authentication.rb
|
257
|
+
- spec/support/http_headers.rb
|
254
258
|
- spec/support/vcr.rb
|
255
259
|
- spec/unit/lib/angellist_api/api_spec.rb
|
256
260
|
- spec/unit/lib/angellist_api/authentication_spec.rb
|
@@ -285,7 +289,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
285
289
|
version: '0'
|
286
290
|
segments:
|
287
291
|
- 0
|
288
|
-
hash:
|
292
|
+
hash: 74367016323838857
|
289
293
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
290
294
|
none: false
|
291
295
|
requirements:
|
@@ -294,7 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
294
298
|
version: '0'
|
295
299
|
segments:
|
296
300
|
- 0
|
297
|
-
hash:
|
301
|
+
hash: 74367016323838857
|
298
302
|
requirements: []
|
299
303
|
rubyforge_project:
|
300
304
|
rubygems_version: 1.8.25
|
@@ -303,6 +307,8 @@ specification_version: 3
|
|
303
307
|
summary: Ruby wrapper for the Angellist API.
|
304
308
|
test_files:
|
305
309
|
- spec/fixtures/cassettes/activity_feeds.yml
|
310
|
+
- spec/fixtures/cassettes/errors/forbidden.yml
|
311
|
+
- spec/fixtures/cassettes/errors/too_many_requests.yml
|
306
312
|
- spec/fixtures/cassettes/follows.yml
|
307
313
|
- spec/fixtures/cassettes/jobs.yml
|
308
314
|
- spec/fixtures/cassettes/messages.yml
|
@@ -316,6 +322,7 @@ test_files:
|
|
316
322
|
- spec/fixtures/cassettes/tags.yml
|
317
323
|
- spec/fixtures/cassettes/users.yml
|
318
324
|
- spec/integration/activity_feeds_spec.rb
|
325
|
+
- spec/integration/errors_spec.rb
|
319
326
|
- spec/integration/follows_spec.rb
|
320
327
|
- spec/integration/jobs_spec.rb
|
321
328
|
- spec/integration/messages_spec.rb
|
@@ -330,6 +337,7 @@ test_files:
|
|
330
337
|
- spec/integration/users_spec.rb
|
331
338
|
- spec/spec_helper.rb
|
332
339
|
- spec/support/authentication.rb
|
340
|
+
- spec/support/http_headers.rb
|
333
341
|
- spec/support/vcr.rb
|
334
342
|
- spec/unit/lib/angellist_api/api_spec.rb
|
335
343
|
- spec/unit/lib/angellist_api/authentication_spec.rb
|
@@ -1,13 +0,0 @@
|
|
1
|
-
require 'angellist_api/error'
|
2
|
-
|
3
|
-
module AngellistApi
|
4
|
-
# Raised when AngellistApi returns the HTTP status code 420
|
5
|
-
class Error::EnhanceYourCalm < AngellistApi::Error
|
6
|
-
# The number of seconds your application should wait before requesting date
|
7
|
-
# from the API again
|
8
|
-
def retry_after
|
9
|
-
@http_headers.values_at('retry-after', 'Retry-After').detect {|value| value }.to_i
|
10
|
-
end
|
11
|
-
end
|
12
|
-
end
|
13
|
-
|