Class: SmilyCli::Result
- Inherits:
-
Object
- Object
- SmilyCli::Result
- Defined in:
- lib/smily_cli/result.rb
Overview
A normalized view over one or more API v3 responses. It pulls the record
array out of the JSON:API envelope (the single top-level key that isn't
links/linked/meta), while keeping the raw envelope, meta, sideloaded
linked records, pagination relations and rate-limit headers available for
formatters and verbose output.
Constant Summary collapse
- SPECIAL_KEYS =
%w[links linked meta].freeze
Instance Attribute Summary collapse
-
#envelope ⇒ Hash?
readonly
The raw parsed envelope of the last response.
-
#headers ⇒ Hash
readonly
Response headers of the last response.
-
#key ⇒ String?
readonly
Resolved JSON:API key the records live under.
-
#linked ⇒ Hash?
readonly
Sideloaded associations (
linked). -
#meta ⇒ Hash?
readonly
JSON:API
meta. -
#records ⇒ Array<Hash>
readonly
The resource records (always an array).
-
#status ⇒ Integer?
readonly
HTTP status of the last response.
Class Method Summary collapse
-
.empty(single: false, status: nil, headers: {}) ⇒ Result
An empty result (e.g. a 204 delete).
- .extract_records(body, key) ⇒ Object private
-
.from_body(body, single: false) ⇒ Result
Build a Result from an already-parsed JSON:API envelope (e.g. the payload an MCP tool returns), rather than an HTTP response.
-
.from_response(response, single: false) ⇒ Result
Build a Result from a single BookingSync::API::Response.
- .parse(raw) ⇒ Object private
- .resource_key(body) ⇒ Object private
Instance Method Summary collapse
- #count ⇒ Integer
- #empty? ⇒ Boolean
-
#initialize(records:, single: false, envelope: nil, key: nil, status: nil, headers: {}) ⇒ Result
constructor
A new instance of Result.
-
#rate_limit_remaining ⇒ Integer?
Remaining requests in the current rate-limit window, if reported.
-
#record ⇒ Hash?
The sole record, when #single?.
-
#single? ⇒ Boolean
Whether this result represents a single member.
-
#total_pages ⇒ Integer?
Total number of pages reported by the API, if any.
Constructor Details
#initialize(records:, single: false, envelope: nil, key: nil, status: nil, headers: {}) ⇒ Result
Returns a new instance of Result.
35 36 37 38 39 40 41 42 43 44 |
# File 'lib/smily_cli/result.rb', line 35 def initialize(records:, single: false, envelope: nil, key: nil, status: nil, headers: {}) @records = records @single = single @envelope = envelope @key = key @meta = envelope.is_a?(Hash) ? envelope["meta"] : nil @linked = envelope.is_a?(Hash) ? envelope["linked"] : nil @status = status @headers = headers || {} end |
Instance Attribute Details
#envelope ⇒ Hash? (readonly)
Returns the raw parsed envelope of the last response.
17 18 19 |
# File 'lib/smily_cli/result.rb', line 17 def envelope @envelope end |
#headers ⇒ Hash (readonly)
Returns response headers of the last response.
25 26 27 |
# File 'lib/smily_cli/result.rb', line 25 def headers @headers end |
#key ⇒ String? (readonly)
Returns resolved JSON:API key the records live under.
27 28 29 |
# File 'lib/smily_cli/result.rb', line 27 def key @key end |
#linked ⇒ Hash? (readonly)
Returns sideloaded associations (linked).
21 22 23 |
# File 'lib/smily_cli/result.rb', line 21 def linked @linked end |
#meta ⇒ Hash? (readonly)
Returns JSON:API meta.
19 20 21 |
# File 'lib/smily_cli/result.rb', line 19 def @meta end |
#records ⇒ Array<Hash> (readonly)
Returns the resource records (always an array).
15 16 17 |
# File 'lib/smily_cli/result.rb', line 15 def records @records end |
#status ⇒ Integer? (readonly)
Returns HTTP status of the last response.
23 24 25 |
# File 'lib/smily_cli/result.rb', line 23 def status @status end |
Class Method Details
.empty(single: false, status: nil, headers: {}) ⇒ Result
An empty result (e.g. a 204 delete). records is empty.
70 71 72 |
# File 'lib/smily_cli/result.rb', line 70 def self.empty(single: false, status: nil, headers: {}) new(records: [], single: single, envelope: nil, key: nil, status: status, headers: headers) end |
.extract_records(body, key) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
138 139 140 141 142 143 144 145 146 147 |
# File 'lib/smily_cli/result.rb', line 138 def self.extract_records(body, key) return [] unless body.is_a?(Hash) && key # v3 always wraps records in an array, but tolerate a bare object too. case (value = body[key]) when Array then value when nil then [] else [value] end end |
.from_body(body, single: false) ⇒ Result
Build a Result from an already-parsed JSON:API envelope (e.g. the payload an MCP tool returns), rather than an HTTP response.
80 81 82 83 |
# File 'lib/smily_cli/result.rb', line 80 def self.from_body(body, single: false) key = resource_key(body) new(records: extract_records(body, key), single: single, envelope: body, key: key) end |
.from_response(response, single: false) ⇒ Result
Build a Result from a single BookingSync::API::Response.
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
# File 'lib/smily_cli/result.rb', line 51 def self.from_response(response, single: false) return empty(single: single) if response.nil? body = parse(response.body) key = resource_key(body) records = extract_records(body, key) new( records: records, single: single, envelope: body, key: key, status: response.status, headers: response.headers ) end |
.parse(raw) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
122 123 124 125 126 127 128 |
# File 'lib/smily_cli/result.rb', line 122 def self.parse(raw) return {} if raw.nil? || raw.to_s.empty? JSON.parse(raw) rescue JSON::ParserError {} end |
.resource_key(body) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
131 132 133 134 135 |
# File 'lib/smily_cli/result.rb', line 131 def self.resource_key(body) return nil unless body.is_a?(Hash) (body.keys.map(&:to_s) - SPECIAL_KEYS).first end |
Instance Method Details
#count ⇒ Integer
101 102 103 |
# File 'lib/smily_cli/result.rb', line 101 def count records.length end |
#empty? ⇒ Boolean
96 97 98 |
# File 'lib/smily_cli/result.rb', line 96 def empty? records.empty? end |
#rate_limit_remaining ⇒ Integer?
Remaining requests in the current rate-limit window, if reported.
108 109 110 111 |
# File 'lib/smily_cli/result.rb', line 108 def rate_limit_remaining value = headers["X-RateLimit-Remaining"] || headers["x-ratelimit-remaining"] value&.to_i end |
#record ⇒ Hash?
Returns the sole record, when #single?.
91 92 93 |
# File 'lib/smily_cli/result.rb', line 91 def record records.first end |
#single? ⇒ Boolean
Returns whether this result represents a single member.
86 87 88 |
# File 'lib/smily_cli/result.rb', line 86 def single? @single end |
#total_pages ⇒ Integer?
Total number of pages reported by the API, if any.
116 117 118 119 |
# File 'lib/smily_cli/result.rb', line 116 def total_pages value = headers["X-Total-Pages"] || headers["x-total-pages"] value&.to_i end |