Class: X::Page
- Inherits:
-
Object
- Object
- X::Page
- Includes:
- Enumerable
- Defined in:
- x-objects/lib/x/objects/page.rb
Overview
One page of results from a paginated endpoint
Instance Attribute Summary collapse
-
#items ⇒ Array<Resource>
readonly
The resources on this page.
-
#meta ⇒ Hash{String => Object}
readonly
The pagination metadata returned with this page.
-
#problems ⇒ Array<Problem>
readonly
The problems the response of this page reported.
Instance Method Summary collapse
-
#==(other) ⇒ Boolean
(also: #eql?)
Check whether another page is the same page.
-
#[](*args) ⇒ Resource, ...
The resource at an index, or the resources of a range, as Array#[] reads them.
-
#as_json ⇒ Hash{String => Object}
This page, as a JSON encoder reads it, in the shape of the response it came from.
-
#each {|Resource| ... } ⇒ Enumerator, Page
Iterate over the resources on this page.
-
#empty? ⇒ Boolean
Check whether this page holds no resources.
-
#encode_with(coder) ⇒ void
Write the state Marshal writes as YAML, without the clients of the resources.
-
#hash ⇒ Integer
The hash of the page, which equal pages share.
-
#init_with(coder) ⇒ void
Restore a page YAML read, frozen, as Marshal restores one.
-
#initialize(items, meta: {}, problems: []) ⇒ Page
constructor
Initialize a new page.
-
#last(*args) ⇒ Resource, ...
The last resource on this page, or the last few.
-
#marshal_dump ⇒ Array
The state Marshal writes.
-
#marshal_load(state) ⇒ void
Restore a page Marshal read, frozen as the page that was written was.
-
#next_token ⇒ String?
The token used to fetch the next page.
-
#previous_token ⇒ String?
The token used to fetch the page before this one.
-
#result_count ⇒ Integer?
The number of results reported by the API.
-
#size ⇒ Integer
(also: #length)
The number of resources on this page.
-
#to_a ⇒ Array<Resource>
(also: #entries)
The resources on this page, frozen, as #items returns them.
-
#to_h {|resource| ... } ⇒ Hash
This page as a Hash in the shape of its response, or of a pair for each resource.
-
#to_json(state = nil) ⇒ String
This page as a JSON object in the shape of the response it came from.
Constructor Details
#initialize(items, meta: {}, problems: []) ⇒ Page
Initialize a new page
62 63 64 65 66 67 |
# File 'x-objects/lib/x/objects/page.rb', line 62 def initialize(items, meta: {}, problems: []) @items = resources!(items).dup.freeze @meta = Utils.deep_freeze(Hash.try_convert() || raise(ArgumentError, "meta must be a Hash, not #{.inspect}")) @problems = problems!(problems).dup.freeze freeze end |
Instance Attribute Details
#items ⇒ Array<Resource> (readonly)
The resources on this page
31 32 33 |
# File 'x-objects/lib/x/objects/page.rb', line 31 def items @items end |
#meta ⇒ Hash{String => Object} (readonly)
The pagination metadata returned with this page
49 50 51 |
# File 'x-objects/lib/x/objects/page.rb', line 49 def @meta end |
#problems ⇒ Array<Problem> (readonly)
The problems the response of this page reported
They are every problem of the response, where each resource of the page reports only those about it, or about a resource it refers to.
42 43 44 |
# File 'x-objects/lib/x/objects/page.rb', line 42 def problems @problems end |
Instance Method Details
#==(other) ⇒ Boolean Also known as: eql?
Check whether another page is the same page
Its resources are compared as resources are, by class and identifier, so a page read again, or read back from Marshal, equals the page it was read from.
140 |
# File 'x-objects/lib/x/objects/page.rb', line 140 def ==(other) = other.instance_of?(self.class) && state.eql?(other.__send__(:state)) |
#[](*args) ⇒ Resource, ...
The resource at an index, or the resources of a range, as Array#[] reads them
118 |
# File 'x-objects/lib/x/objects/page.rb', line 118 def [](*args) = items[*args] # steep:ignore DifferentMethodParameterKind, UnresolvedOverloading |
#as_json ⇒ Hash{String => Object}
This page, as a JSON encoder reads it, in the shape of the response it came from
Its resources are the data, each given as its own as_json gives it, beside the meta of the page, which holds the token of the next, and, when the response reported any, its problems as the errors, so that what this returns is plain data, which ActiveSupport reads too, and which the from_response of the resource class builds into a page again. The objects the response included are not among it, so a reference of a resource built again from it is a stub.
205 206 207 208 209 |
# File 'x-objects/lib/x/objects/page.rb', line 205 def as_json(*) json = {"data" => map(&:as_json), "meta" => } json["errors"] = problems.map(&:to_h) unless problems.empty? json.freeze end |
#each {|Resource| ... } ⇒ Enumerator, Page
Iterate over the resources on this page
76 77 78 79 80 81 |
# File 'x-objects/lib/x/objects/page.rb', line 76 def each(&block) return to_enum { size } unless block items.each(&block) self end |
#empty? ⇒ Boolean
Check whether this page holds no resources
109 |
# File 'x-objects/lib/x/objects/page.rb', line 109 def empty? = items.empty? |
#encode_with(coder) ⇒ void
This method returns an undefined value.
Write the state Marshal writes as YAML, without the clients of the resources
YAML reads no marshal_dump, and would write every instance variable of each resource, its client and the credentials it holds among them, so a page says how it is written: each part of the state Marshal writes, under its name.
316 |
# File 'x-objects/lib/x/objects/page.rb', line 316 def encode_with(coder) = YAML_KEYS.zip(marshal_dump) { |key, value| coder[key] = value } |
#hash ⇒ Integer
The hash of the page, which equal pages share
149 |
# File 'x-objects/lib/x/objects/page.rb', line 149 def hash = [self.class, state].hash |
#init_with(coder) ⇒ void
This method returns an undefined value.
Restore a page YAML read, frozen, as Marshal restores one
326 |
# File 'x-objects/lib/x/objects/page.rb', line 326 def init_with(coder) = marshal_load(coder.map.values_at(*YAML_KEYS)) |
#last(*args) ⇒ Resource, ...
The last resource on this page, or the last few
127 |
# File 'x-objects/lib/x/objects/page.rb', line 127 def last(*args) = items.last(*args) # steep:ignore DifferentMethodParameterKind, UnresolvedOverloading |
#marshal_dump ⇒ Array
The state Marshal writes
What is written is plain data, led by the number of its format, so that a page written by one release of 1.x is read by a later one: each resource, as its class, its attributes, and whether it is hydrated, without its client; the included objects the resources refer to, once for the resources that came from one response, as a resource writes those it refers to, so that the resources that resolved a reference to the same object still do; its metadata; and its problems.
280 281 282 283 |
# File 'x-objects/lib/x/objects/page.rb', line 280 def marshal_dump responses = group_by { |item| response_of(item) } [MARSHAL_FORMAT, resource_states(responses.keys), , problems, responses.map { |includes, members| includes.state_of(members) }] end |
#marshal_load(state) ⇒ void
This method returns an undefined value.
Restore a page Marshal read, frozen as the page that was written was
The resources that came from one response are built over one identity map again, so a reference they share resolves to the same object, as it did before the page was written. Each is hydrated if it was, and the query of its request asks for every field this release requests, as a resource Marshal reads is.
297 298 299 300 301 302 303 |
# File 'x-objects/lib/x/objects/page.rb', line 297 def marshal_load(state) format, resources, , problems, responses = state raise UnsupportedMarshalFormat, "#{self.class} reads format #{MARSHAL_FORMAT} of Marshal, not #{format.inspect}" unless MARSHAL_FORMAT.eql?(format) responses = responses.map { |data, about, query| Includes.new(data, problems: about, query:) } initialize(resources.map { |klass, attrs, hydrated, response| read(klass, attrs, hydrated, responses.fetch(response)) }, meta:, problems:) end |
#next_token ⇒ String?
The token used to fetch the next page
An empty token names no page, so a page whose meta holds one is the last, as a page whose meta holds none is, rather than one whose next page is fetched with an empty token the API refuses.
160 161 162 163 |
# File 'x-objects/lib/x/objects/page.rb', line 160 def next_token token = ["next_token"] token unless token.eql?("") end |
#previous_token ⇒ String?
The token used to fetch the page before this one
Most endpoints that page, such as the followers of a user, the members of a list, and the events of a direct message conversation, name the page before each page after the first. An empty token names no page, as an empty next_token does.
175 176 177 178 |
# File 'x-objects/lib/x/objects/page.rb', line 175 def previous_token token = ["previous_token"] token unless token.eql?("") end |
#result_count ⇒ Integer?
The number of results reported by the API
187 188 189 |
# File 'x-objects/lib/x/objects/page.rb', line 187 def result_count Utils.read("#{self.class}#result_count", ["result_count"]) { |value| Shape.integer(value) } end |
#size ⇒ Integer Also known as: length
The number of resources on this page
99 |
# File 'x-objects/lib/x/objects/page.rb', line 99 def size = items.size |
#to_a ⇒ Array<Resource> Also known as: entries
The resources on this page, frozen, as #items returns them
89 |
# File 'x-objects/lib/x/objects/page.rb', line 89 def to_a = items |
#to_h {|resource| ... } ⇒ Hash
This page as a Hash in the shape of its response, or of a pair for each resource
Without a block it is #as_json, as the to_h of a resource is its attributes, rather than the to_h of Enumerable, which raises TypeError for resources that are not pairs. With a block it is the to_h of Enumerable, which builds a Hash of the pair the block returns for each resource.
225 |
# File 'x-objects/lib/x/objects/page.rb', line 225 def to_h(&block) = block ? super() : as_json |
#to_json(state = nil) ⇒ String
This page as a JSON object in the shape of the response it came from
234 |
# File 'x-objects/lib/x/objects/page.rb', line 234 def to_json(state = nil) = as_json.to_json(state) |