Class: PackAPI::Pagination::SnapshotPaginator
- Inherits:
-
Object
- Object
- PackAPI::Pagination::SnapshotPaginator
- Defined in:
- lib/pack_api/pagination/snapshot_paginator.rb
Overview
Current Page Snapshot Query is a query that targets the records in a given page of a record set (regardless of how those records may change state). Whereas the contents of the nth page in a record set may change, the cached results query for that same page will not.
This class represents the paginator for such a query.
Constant Summary collapse
- METADATA_KEY =
:snapshot
Instance Attribute Summary collapse
-
#cursor ⇒ Object
Returns the value of attribute cursor.
-
#paginator ⇒ Object
Returns the value of attribute paginator.
-
#results ⇒ Object
Returns the value of attribute results.
Class Method Summary collapse
-
.cursor_for_results(results, table_name:, collection_key:) ⇒ Object
Create a snapshot from the current page results of a record set.
-
.generated?(paginator) ⇒ Boolean
Is the paginator one produced by this class?.
Instance Method Summary collapse
-
#apply_to(query, record_id: nil) ⇒ Object
Update the query to focus the result onto the given record within the snapshot.
-
#initialize(paginator) ⇒ SnapshotPaginator
constructor
A new instance of SnapshotPaginator.
Constructor Details
#initialize(paginator) ⇒ SnapshotPaginator
Returns a new instance of SnapshotPaginator.
38 39 40 41 42 |
# File 'lib/pack_api/pagination/snapshot_paginator.rb', line 38 def initialize(paginator) raise PackAPI::InternalError, 'Paginator does not represent CachedResultsQuery' if paginator..nil? @paginator = paginator end |
Instance Attribute Details
#cursor ⇒ Object
Returns the value of attribute cursor.
14 15 16 |
# File 'lib/pack_api/pagination/snapshot_paginator.rb', line 14 def cursor @cursor end |
#paginator ⇒ Object
Returns the value of attribute paginator.
14 15 16 |
# File 'lib/pack_api/pagination/snapshot_paginator.rb', line 14 def paginator @paginator end |
#results ⇒ Object
Returns the value of attribute results.
14 15 16 |
# File 'lib/pack_api/pagination/snapshot_paginator.rb', line 14 def results @results end |
Class Method Details
.cursor_for_results(results, table_name:, collection_key:) ⇒ Object
Create a snapshot from the current page results of a record set.
18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
# File 'lib/pack_api/pagination/snapshot_paginator.rb', line 18 def self.cursor_for_results(results, table_name:, collection_key:) offsets = {} case_statement = results.map.with_index do |record, index| record_id = record.send(collection_key) offsets[record_id.to_s] = index.to_s # Use SQL standard CAST to convert both sides to strings for comparison "WHEN CAST(\"#{table_name}\".\"#{collection_key}\" AS VARCHAR) = '#{record_id}' THEN #{index}" end sort_sql = "CASE #{case_statement.join("\n")} END" filters = { collection_key => results.pluck(collection_key) } paginator = PaginatorBuilder.build do |builder| builder.set_params(query: { filters: }, metadata: { METADATA_KEY => true, offsets:, collection_key: }, sort: Arel.sql(sort_sql), total_items: results.size, per_page: results.size) end paginator.current_page_cursor end |
.generated?(paginator) ⇒ Boolean
Is the paginator one produced by this class?
84 85 86 |
# File 'lib/pack_api/pagination/snapshot_paginator.rb', line 84 def self.generated?(paginator) paginator.&.fetch(METADATA_KEY, nil).presence end |
Instance Method Details
#apply_to(query, record_id: nil) ⇒ Object
Update the query to focus the result onto the given record within the snapshot. If no record_id is provided, it will attempt to guess the record_id based on the current paginator state. NOTE This method assumes that the paginator.total_items has already been updated to reflect the query’s count.
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 |
# File 'lib/pack_api/pagination/snapshot_paginator.rb', line 48 def apply_to(query, record_id: nil) if has_valid_offsets? # if no record_id is provided, no customization is needed return query unless record_id.present? self.target_record_id = record_id updated_query = query.offset(paginator.offset).limit(paginator.limit) @results = updated_query.to_a @cursor = paginator.current_page_cursor updated_query else # unless we have either a record_id or an offset, there is no customization needed return query unless paginator.offset.present? || record_id.present? # Step 1: If we don't have a record_id, try to guess what record_id the user was trying to access record_id ||= target_record_id # Step 2: Fetch all the records in the snapshot -- remove the offset and limits on the current query snapshot_results = query.unscope(:offset, :limit).to_a # Step 3: Update the offsets based on the current query results update_offsets(snapshot_results) # Step 4: get the correct offset for the given record_id self.target_record_id = record_id # Step 5: Filter the results to just the record_id collection_key = paginator.[:collection_key] @results = snapshot_results.select { it.send(collection_key).to_s == record_id.to_s } @cursor = paginator.current_page_cursor query.offset(paginator.offset).limit(paginator.limit) end end |