/
resource.rb
106 lines (85 loc) · 2.61 KB
/
resource.rb
1
2
3
4
5
6
7
8
9
10
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# frozen_string_literal: true
module GithubFetcher
# Base class for resources accessible via GitHubBub
class Resource
attr_reader :error_message, :page
# Often over-ridden by subclasses in order to set @api_path. When over-ridden,
# it's preferable to call `super` so as to set options as below (and get any
# other changes made to this base call in the future)
def initialize(options)
@options = options
reset!
end
def call(retry_on_bad_token: false)
resp = response
return resp unless bad_token?
return resp unless retry_on_bad_token
unless retry_on_bad_token.is_a?(Integer)
raise "retry_on_bad_token must be a number but is #{retry_on_bad_token.class}: #{retry_on_bad_token.inspect}"
end
return resp if retry_on_bad_token <= 0
reset!
call(retry_on_bad_token: retry_on_bad_token - 1)
end
def status
response.status
end
# Generally not over-ridden
def as_json
@as_json ||= response.json_body
end
# Generally not over-ridden
def response
@response ||= begin
GitHubBub.get(api_path, options)
rescue GitHubBub::RequestError => e
@error = e
@error_message = e.message
null_response(e)
end
end
def success?
return true if status.to_s.start_with?("2")
@error = @error_message = "Status: #{status} body: #{response.body}"
false
end
def bad_token?
if status == 401 && response.body.match?(/Bad credentials/)
@error = @error_message = "Bad credentials"
return true
end
false
end
def error?
# Ensure API request has been made (by calling `as_json` before returning
# error if it happened. `as_json` should always evaluate truthily, but
# @error will be false unless there's an error in the API request
bad_token? || !success? || @error
end
def page=(number)
reset!
options[:page] = number
@page = number
end
def last_page?
response.last_page?
end
private
private def reset!
@response = nil
@as_json = nil
@error = nil
@error_message = nil
end
attr_reader :api_path, :options
# Sometimes over-ridden to use the error
private def null_response(_error)
GitHubBub::Response.new(body: null_response_body.to_json)
end
# Sometimes over-ridden to set a specific response when GitHubBub API call
# fails.
private def null_response_body
{}
end
end
end