Class: D4H::API::Resource

Inherits:
Object
  • Object
show all
Defined in:
lib/d4h/api/resource.rb

Overview

Public: Base class for all D4H API resource endpoints.

Provides HTTP verb helpers (GET, POST, PUT, PATCH, DELETE), automatic Bearer token authentication, error handling, and a pagination helper for fetching all pages of a list endpoint.

Subclasses must define a SUB_URL constant (e.g. “members”, “tags”) and implement whichever CRUD methods the API supports for that resource.

Examples

class TagResource < Resource
  SUB_URL = "tags"

  def list(**params)
    Collection.new(get_request(resource_url, params: params).body, model_class: Tag)
  end

  def show(id:)
    Tag.new(get_request("#{resource_url}/#{id}").body)
  end
end

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client) ⇒ Resource

Public: Initialize a Resource bound to a Client.

client - A D4H::API::Client instance.



34
35
36
# File 'lib/d4h/api/resource.rb', line 34

def initialize(client)
  @client = client
end

Instance Attribute Details

#clientObject (readonly)

Public: Returns the Client instance this resource is bound to.



29
30
31
# File 'lib/d4h/api/resource.rb', line 29

def client
  @client
end

Instance Method Details

#base_pathObject

Public: Returns the context-scoped base path (e.g. “v3/team/42”).



39
40
41
# File 'lib/d4h/api/resource.rb', line 39

def base_path
  client.base_path
end

#default_headersObject

Internal: Returns the default Authorization header for all requests.



115
116
117
# File 'lib/d4h/api/resource.rb', line 115

def default_headers
  {Authorization: "Bearer #{client.api_key}"}
end

#delete_request(url, params: {}, headers: {}) ⇒ Object

Public: Perform a DELETE request.

url - The URL path to request. params - Optional Hash of query parameters (default: {}). headers - Optional Hash of additional HTTP headers (default: {}).

Returns the Faraday::Response on success. Raises D4H::API::Error on non-2xx status.



110
111
112
# File 'lib/d4h/api/resource.rb', line 110

def delete_request(url, params: {}, headers: {})
  handle_response(client.connection.delete(url, params, default_headers.merge(headers)))
end

#get_request(url, params: {}, headers: {}) ⇒ Object

Public: Perform a GET request.

url - The URL path to request. params - Optional Hash of query parameters (default: {}). headers - Optional Hash of additional HTTP headers (default: {}).

Returns the Faraday::Response on success. Raises D4H::API::Error on non-2xx status.



58
59
60
# File 'lib/d4h/api/resource.rb', line 58

def get_request(url, params: {}, headers: {})
  handle_response(client.connection.get(url, params, default_headers.merge(headers)))
end

#handle_response(response) ⇒ Object

Internal: Check the HTTP response status and raise on errors.

response - A Faraday::Response object.

Returns the response if status is 2xx. Raises D4H::API::RetriableError for transient errors (429, 5xx) after all retry attempts have been exhausted by the Faraday retry middleware. Raises D4H::API::Error for all other non-2xx responses.

Raises:



127
128
129
130
131
132
133
134
135
136
137
138
139
140
# File 'lib/d4h/api/resource.rb', line 127

def handle_response(response)
  return response if (200..299).cover?(response.status)

  body = response.body || {}
  parts = [body["title"], body["detail"], body["error"], body["message"]].compact.uniq
  if (issues = body.dig("detailObj", "data", "issues"))
    issues.each { |issue| parts << "#{issue["path"]&.join(".")}: #{issue["message"]}" }
  end
  message = parts.join(": ")

  raise RetriableError, message if Client::RETRIABLE_STATUSES.include?(response.status)

  raise Error, message
end

#patch_request(url, body: {}, headers: {}) ⇒ Object

Public: Perform a PATCH request.

Used by most resources for updates.

url - The URL path to request. body - The Hash request body to send (default: {}). headers - Optional Hash of additional HTTP headers (default: {}).

Returns the Faraday::Response on success. Raises D4H::API::Error on non-2xx status.



98
99
100
# File 'lib/d4h/api/resource.rb', line 98

def patch_request(url, body: {}, headers: {})
  handle_response(client.connection.patch(url, body, default_headers.merge(headers)))
end

#post_request(url, body:, headers: {}) ⇒ Object

Public: Perform a POST request.

url - The URL path to request. body - The Hash request body to send. headers - Optional Hash of additional HTTP headers (default: {}).

Returns the Faraday::Response on success. Raises D4H::API::Error on non-2xx status.



70
71
72
# File 'lib/d4h/api/resource.rb', line 70

def post_request(url, body:, headers: {})
  handle_response(client.connection.post(url, body, default_headers.merge(headers)))
end

#put_request(url, body:, headers: {}) ⇒ Object

Public: Perform a PUT request.

Used by DocumentResource, which requires PUT for updates per the D4H API.

url - The URL path to request. body - The Hash request body to send. headers - Optional Hash of additional HTTP headers (default: {}).

Returns the Faraday::Response on success. Raises D4H::API::Error on non-2xx status.



84
85
86
# File 'lib/d4h/api/resource.rb', line 84

def put_request(url, body:, headers: {})
  handle_response(client.connection.put(url, body, default_headers.merge(headers)))
end

#resource_urlObject

Public: Returns the full resource URL path (e.g. “v3/team/42/tags”).

Built from the client’s base_path and the subclass’s SUB_URL constant.



46
47
48
# File 'lib/d4h/api/resource.rb', line 46

def resource_url
  "#{base_path}/#{self.class::SUB_URL}"
end