Exception: Booqable::Error
- Inherits:
-
StandardError
- Object
- StandardError
- Booqable::Error
- Defined in:
- lib/booqable/error.rb,
sig/booqable.rbs
Overview
Custom error class for rescuing from all Booqable errors
Direct Known Subclasses
Instance Attribute Summary collapse
-
#context ⇒ RateLimit?
readonly
Returns the value of attribute context.
Class Method Summary collapse
-
.error_class_from_response(response) ⇒ Booqable::Error?
Returns the appropriate Booqable::Error subclass based on status and response message.
-
.error_for_400(response) ⇒ singleton(Error)
Return most appropriate error for 400 HTTP status code rubocop:disable Metrics/CyclomaticComplexity.
-
.error_for_401(response) ⇒ Object
Return most appropriate error for 401 HTTP status code.
-
.error_for_402(body) ⇒ singleton(Error)
Return most appropriate error for 402 HTTP status code rubocop:disable Metrics/CyclomaticComplexity.
-
.error_for_404(body) ⇒ singleton(Error)
Return most appropriate error for 404 HTTP status code rubocop:disable Naming/VariableNumber.
-
.error_for_422(body) ⇒ singleton(Error)
Return most appropriate error for 422 HTTP status code rubocop:disable Naming/VariableNumber.
-
.error_for_503(body) ⇒ singleton(Error)
Return most appropriate error for 503 HTTP status code rubocop:disable Naming/VariableNumber.
-
.error_for_invalid_grant(response) ⇒ Class
Return most appropriate error for invalid_grant OAuth error.
-
.from_response(response) ⇒ nil
Create and raise an appropriate error from an HTTP response.
Instance Method Summary collapse
-
#build_error_context ⇒ void
rubocop:enable Metrics/CyclomaticComplexity.
- #build_error_message ⇒ String?
- #data ⇒ Object
-
#errors ⇒ Array<Hash>
Array of validation errors.
-
#initialize(response = nil) ⇒ Error
constructor
Initialize a new Error.
- #redact_url(url_string) ⇒ String
-
#response_body ⇒ String
Body returned by the Booqable server.
- #response_error ⇒ String?
- #response_error_summary ⇒ String?
-
#response_headers ⇒ Hash
Headers returned by the Booqable server.
- #response_message ⇒ String?
-
#response_status ⇒ Integer
Status code returned by the Booqable server.
Constructor Details
#initialize(response = nil) ⇒ Error
Initialize a new Error
79 80 81 82 83 |
# File 'lib/booqable/error.rb', line 79 def initialize(response = nil) @response = response super() build_error_context end |
Instance Attribute Details
#context ⇒ RateLimit? (readonly)
Returns the value of attribute context.
20 21 22 |
# File 'lib/booqable/error.rb', line 20 def context @context end |
Class Method Details
.error_class_from_response(response) ⇒ Booqable::Error?
Returns the appropriate Booqable::Error subclass based on status and response message
rubocop:disable Metrics/CyclomaticComplexity
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 |
# File 'lib/booqable/error.rb', line 39 def self.error_class_from_response(response) status = response[:status].to_i body = response[:body].to_s # headers = response[:response_headers] if klass = case status when 400 then error_for_400(response) when 401 then error_for_401(response) when 402 then error_for_402(body) when 403 then Booqable::Forbidden when 404 then error_for_404(body) when 405 then Booqable::MethodNotAllowed when 406 then Booqable::NotAcceptable when 409 then Booqable::Conflict when 410 then Booqable::Deprecated when 415 then Booqable::UnsupportedMediaType when 422 then error_for_422(body) when 423 then Booqable::Locked when 429 then Booqable::TooManyRequests when 400..499 then Booqable::ClientError when 500 then Booqable::InternalServerError when 501 then Booqable::NotImplemented when 502 then Booqable::BadGateway when 503 then error_for_503(body) when 500..599 then Booqable::ServerError end klass.new(response) end end |
.error_for_400(response) ⇒ singleton(Error)
Return most appropriate error for 400 HTTP status code rubocop:disable Metrics/CyclomaticComplexity
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
# File 'lib/booqable/error.rb', line 88 def self.error_for_400(response) case response.body when /unwrittable_attribute/i Booqable::ReadOnlyAttribute when /unknown_attribute/i Booqable::UnknownAttribute when /extra fields should be an object/i Booqable::ExtraFieldsInWrongFormat when /fields should be an object/i Booqable::FieldsInWrongFormat when /page should be an object/i Booqable::PageShouldBeAnObject when /failed typecasting/i Booqable::FailedTypecasting when /invalid filter/i Booqable::InvalidFilter when /required filter/i Booqable::RequiredFilter when /invalid_grant/i error_for_invalid_grant(response) else Booqable::BadRequest end end |
.error_for_401(response) ⇒ Object
Return most appropriate error for 401 HTTP status code
116 117 118 119 120 121 122 123 |
# File 'lib/booqable/error.rb', line 116 def self.error_for_401(response) case response.body when /token is invalid \(revoked\)/i Booqable::TokenRevoked else Booqable::Unauthorized end end |
.error_for_402(body) ⇒ singleton(Error)
Return most appropriate error for 402 HTTP status code rubocop:disable Metrics/CyclomaticComplexity
128 129 130 131 132 133 134 135 136 137 |
# File 'lib/booqable/error.rb', line 128 def self.error_for_402(body) case body when /feature_not_enabled/i Booqable::FeatureNotEnabled when /trial_expired/i Booqable::TrialExpired else Booqable::PaymentRequired end end |
.error_for_404(body) ⇒ singleton(Error)
Return most appropriate error for 404 HTTP status code rubocop:disable Naming/VariableNumber
142 143 144 145 146 147 148 149 150 |
# File 'lib/booqable/error.rb', line 142 def self.error_for_404(body) # rubocop:enable Naming/VariableNumber case body when /company not found/i Booqable::CompanyNotFound else Booqable::NotFound end end |
.error_for_422(body) ⇒ singleton(Error)
Return most appropriate error for 422 HTTP status code rubocop:disable Naming/VariableNumber
155 156 157 158 159 160 161 162 163 164 165 |
# File 'lib/booqable/error.rb', line 155 def self.error_for_422(body) # rubocop:enable Naming/VariableNumber case body when /is not a datetime/i Booqable::InvalidDateTimeFormat when /invalid date/i Booqable::InvalidDateFormat else Booqable::UnprocessableEntity end end |
.error_for_503(body) ⇒ singleton(Error)
Return most appropriate error for 503 HTTP status code rubocop:disable Naming/VariableNumber
170 171 172 173 174 175 176 177 |
# File 'lib/booqable/error.rb', line 170 def self.error_for_503(body) # rubocop:enable Naming/VariableNumber if body =~ /read-only/ Booqable::ReadOnlyMode else Booqable::ServiceUnavailable end end |
.error_for_invalid_grant(response) ⇒ Class
Return most appropriate error for invalid_grant OAuth error
Determines whether the invalid_grant error is due to a revoked refresh token or a different OAuth grant error by examining the grant_type parameter in the request body.
188 189 190 191 192 193 194 195 196 197 |
# File 'lib/booqable/error.rb', line 188 def self.error_for_invalid_grant(response) grant_type = CGI.parse(response.request_body).dig("grant_type", 0) case grant_type when /refresh_token/i Booqable::RefreshTokenRevoked else Booqable::InvalidGrant end end |
.from_response(response) ⇒ nil
Create and raise an appropriate error from an HTTP response
27 28 29 30 31 |
# File 'lib/booqable/error.rb', line 27 def self.from_response(response) if error = self.error_class_from_response(response) raise error end end |
Instance Method Details
#build_error_context ⇒ void
This method returns an undefined value.
rubocop:enable Metrics/CyclomaticComplexity
70 71 72 73 74 |
# File 'lib/booqable/error.rb', line 70 def build_error_context if RATE_LIMITED_ERRORS.include?(self.class) @context = Booqable::RateLimit.from_response(@response) end end |
#build_error_message ⇒ String?
276 277 278 279 280 281 282 283 284 285 286 |
# File 'lib/booqable/error.rb', line 276 def return nil if @response.nil? = +"#{@response[:method].to_s.upcase} " << "#{redact_url(@response[:url].to_s.dup)}: " << "#{@response[:status]} - " << .to_s unless .nil? << response_error.to_s unless response_error.nil? << response_error_summary.to_s unless response_error_summary.nil? end |
#data ⇒ Object
232 233 234 235 236 237 238 239 240 241 242 243 244 |
# File 'lib/booqable/error.rb', line 232 def data @data ||= if (body = @response[:body]) && !body.empty? if body.is_a?(String) && @response[:response_headers] && @response[:response_headers][:content_type] =~ /json/ Sawyer::Agent.serializer.decode(body) else body end end end |
#errors ⇒ Array<Hash>
Array of validation errors
201 202 203 204 205 206 207 |
# File 'lib/booqable/error.rb', line 201 def errors if data.is_a?(Hash) data[:errors] || [] else [] end end |
#redact_url(url_string) ⇒ String
288 289 290 291 292 293 294 295 |
# File 'lib/booqable/error.rb', line 288 def redact_url(url_string) Client::SECRETS.each do |token| if url_string.include? token url_string.gsub!(/#{token}=\S+/, "#{token}=(redacted)") end end url_string end |
#response_body ⇒ String
Body returned by the Booqable server.
226 227 228 |
# File 'lib/booqable/error.rb', line 226 def response_body @response[:body] end |
#response_error ⇒ String?
255 256 257 |
# File 'lib/booqable/error.rb', line 255 def response_error "Error: #{data[:error]}" if data.is_a?(Hash) && data[:error] end |
#response_error_summary ⇒ String?
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/booqable/error.rb', line 259 def response_error_summary return nil unless data.is_a?(Hash) && !Array(data[:errors]).empty? summary = +"\nError summary:\n" return summary << data[:errors] if data[:errors].is_a?(String) summary << data[:errors].map do |error| if error.is_a? Hash error.map { |k, v| " #{k}: #{v}" } else " #{error}" end end.join("\n") summary end |
#response_headers ⇒ Hash
Headers returned by the Booqable server.
219 220 221 |
# File 'lib/booqable/error.rb', line 219 def response_headers @response[:response_headers] end |
#response_message ⇒ String?
246 247 248 249 250 251 252 253 |
# File 'lib/booqable/error.rb', line 246 def case data when Hash data[:message] when String data end end |
#response_status ⇒ Integer
Status code returned by the Booqable server.
212 213 214 |
# File 'lib/booqable/error.rb', line 212 def response_status @response[:status] end |