class Fauna::Page
Helper for handling pagination over sets.
Given a client and a set, allows you to iterate as well as individually move page by page over a set.
Pages lazily load the contents of the page. Loading will occur when data
, before
, or after
are first accessed for a new page. Additionally this will occur when calling page_before
or page_after
without calling one of the data methods first (as the first page must be checked to find the next page). Pages created by builders will unload any data from the current page. Pages will always proceed in the requested direction.
Explicit paging is done via the page_after
and page_before
methods. Iteration can be done via the each
and reverse_each
enumerators. A single page can be retrieved by passing a cursor and then accessing it's data.
Examples:
Paging over a class index
page = Page.new(client, Query.match(Query.index('items')))
Paging over a class index 5 at a time, mapping the refs to the data.value
for each instance
page = Page.new(client, Query.match(Query.index('items')), size: 5) do |ref| select ['data', 'value'], get(ref) end # Same thing, but using builders instead page = Page.new(client, Query.match(Query.index('items'))).with_params(size: 5).map do |ref| select ['data', 'value'], get(ref) end
Paging over a class index, mapping refs to the data.value
for each instance, filtering out odd numbers, and multiplying the value:
page = Page.new(client, Query.match(Query.index('items'))).map do |ref| select ['data', 'value'], get(ref) end.filter do |value| equals modulo(value, 2), 0 end.map do |value| multiply value, 2 end
Attributes
The configured params used for the current pagination.
Public Class Methods
Creates a pagination helper for paging/iterating over a set.
client
-
Client
to execute queries with. set
-
A set query to paginate over.
params
-
A list of parameters to pass to paginate.
lambda
-
Optional lambda to map the generated paginate query with. The block will be run in a query context. An element from the current page will be passed into the block as an argument. See
map
for more info.
# File lib/fauna/page.rb 52 def initialize(client, set, params = {}, &lambda) 53 @client = client 54 @set = set 55 @params = params.dup 56 @fauna_funcs = [] 57 @postprocessing_map = nil 58 59 @fauna_funcs << proc { |query| map(query, &lambda) } unless lambda.nil? 60 61 unload_page 62 @params.freeze 63 end
Public Instance Methods
Returns true
if other
is a Page
and contains the same configuration and data.
# File lib/fauna/page.rb 66 def ==(other) 67 return false unless other.is_a? Page 68 @populated == other.instance_variable_get(:@populated) && 69 @data == other.instance_variable_get(:@data) && 70 @before == other.instance_variable_get(:@before) && 71 @after == other.instance_variable_get(:@after) && 72 @client == other.instance_variable_get(:@client) && 73 @set == other.instance_variable_get(:@set) && 74 @params == other.instance_variable_get(:@params) && 75 @fauna_funcs == other.instance_variable_get(:@fauna_funcs) && 76 @postprocessing_map == other.instance_variable_get(:@postprocessing_map) 77 end
Explicitly loads data for the current page if it has not already been loaded.
Returns true
if the data was just loaded and false
if it was already loaded.
# File lib/fauna/page.rb 88 def load! 89 if @populated 90 false 91 else 92 load_page(get_page(@params)) 93 true 94 end 95 end
Builders
↑ topPublic Instance Methods
Returns a copy of the page with a fauna filter
using the given lambda chained onto the paginate query.
The lambda will be passed into a filter
function that wraps the generated paginate query. Additional collection functions may be combined by chaining them together.
The lambda will be run in a Query.expr
context, and passed an element from the current page as an argument.
Example of filtering out odd numbers from a set of numbers:
page.filter { |value| equals(modulo(value, 2), 0) }
# File lib/fauna/page.rb 174 def filter(&lambda) 175 with_dup do |page| 176 page.instance_variable_get(:@fauna_funcs) << proc { |query| filter(query, &lambda) } 177 end 178 end
Returns a copy of the page with a fauna map
using the given lambda chained onto the paginate query.
The lambda will be passed into a map
function that wraps the generated paginate query. Additional collection functions may be combined by chaining them together.
The lambda will be run in a Query.expr
context, and passed an element from the current page as an argument.
Example of mapping a set of refs to their instances:
page.map { |ref| get ref }
# File lib/fauna/page.rb 157 def map(&lambda) 158 with_dup do |page| 159 page.instance_variable_get(:@fauna_funcs) << proc { |query| map(query, &lambda) } 160 end 161 end
Returns a copy of the page with the given ruby block set.
The block will be used to map the returned data elements from the executed fauna query. Only one postprocessing map can be configured at a time.
Intended for use when the elements in a page need to be converted within ruby (ie loading into a model). Wherever the operation can be performed from within FaunaDB, map
should be used instead.
The block will be passed the each element as a parameter from the data of the page currently being loaded.
Example of loading instances into your own model:
page.postprocessing_map { |instance| YourModel.load(instance) }
# File lib/fauna/page.rb 194 def postprocessing_map(&block) 195 with_dup do |page| 196 page.instance_variable_set(:@postprocessing_map, block) 197 end 198 end
Returns a copy of the page with the given params
set.
See paginate for more details.
# File lib/fauna/page.rb 132 def with_params(params = {}) 133 with_dup do |page| 134 page_params = page.instance_variable_get(:@params) 135 136 if CURSOR_KEYS.any? { |key| params.include? key } 137 # Remove previous cursor 138 CURSOR_KEYS.each { |key| page_params.delete key } 139 end 140 141 # Update params 142 page_params.merge!(params) 143 end 144 end
Data
↑ topPublic Instance Methods
After cursor for the current page.
Lazily loads the page data if it has not already been loaded.
# File lib/fauna/page.rb 121 def after 122 load! 123 @after 124 end
Before cursor for the current page.
Lazily loads the page data if it has not already been loaded.
# File lib/fauna/page.rb 112 def before 113 load! 114 @before 115 end
Data contained within the current page.
Lazily loads the page data if it has not already been loaded.
# File lib/fauna/page.rb 103 def data 104 load! 105 @data 106 end
Pagination
↑ topPublic Instance Methods
Returns the flattened contents of the set as an array.
Ideal for when you need the full contents of a set with a known small size. If you need to iterate over a set of large or unknown size, it is recommended to use each
instead.
The set is paged in the after
direction.
# File lib/fauna/page.rb 265 def all 266 each.flat_map { |x| x } 267 end
Returns an enumerator that iterates in the after
direction.
When a block is provided, the return of the block will always be nil
(to avoid loading large sets into memory).
# File lib/fauna/page.rb 224 def each 225 return enum_for(:each) unless block_given? 226 227 # Return current page 228 yield data 229 230 # Begin returning pages after 231 page = self.page_after 232 until page.nil? 233 yield page.data 234 page = page.page_after 235 end 236 end
Iterates over the entire set, applying the configured lambda in a foreach block, and discarding the result.
Ideal for performing a foreach
over an entire set (like deleting all instances in a set). The set is iterated in the after
direction. The foreach
will be chained on top of any previously configured collection functions.
Example of deleting every instance in a set:
page.foreach! { |ref| delete ref }
# File lib/fauna/page.rb 278 def foreach!(&lambda) 279 # Create new page with foreach block 280 iter_page = with_dup do |page| 281 page.instance_variable_get(:@fauna_funcs) << proc { |query| foreach(query, &lambda) } 282 end 283 284 # Apply to all pages in the set 285 until iter_page.nil? 286 iter_page.load! 287 iter_page = iter_page.page_after 288 end 289 nil 290 end
The page after the current one in the set.
Returns nil
when there are no more pages after the current page. Lazily loads the current page if it has not already been loaded in order to determine the page after.
# File lib/fauna/page.rb 207 def page_after 208 new_page(:after) 209 end
The page before the current one in the set.
Returns nil
when there are no more pages before the current page. Lazily loads the current page if it has not already been loaded in order to determine the page before.
# File lib/fauna/page.rb 216 def page_before 217 new_page(:before) 218 end
Returns an enumerator that iterates in the before
direction.
When a block is provided, the return of the block will always be nil
(to avoid loading large sets into memory).
While the paging will occur in the reverse direction, the data returned will still be in the normal direction.
# File lib/fauna/page.rb 244 def reverse_each 245 return enum_for(:reverse_each) unless block_given? 246 247 # Return current page 248 yield data 249 250 # Begin returning pages before 251 page = self.page_before 252 until page.nil? 253 yield page.data 254 page = page.page_before 255 end 256 end
Private Instance Methods
# File lib/fauna/page.rb 316 def get_page(params) 317 # Create query 318 query = Query.paginate @set, params 319 320 unless @fauna_funcs.empty? 321 # Wrap paginate query with the fauna maps 322 dsl = Query::QueryDSLContext.new 323 @fauna_funcs.each do |proc| 324 query = DSLContext.eval_dsl(dsl, query, &proc) 325 end 326 query = Query::Expr.wrap query 327 end 328 329 # Execute query 330 result = @client.query query 331 332 unless @postprocessing_map.nil? 333 # Map the resulting data with the ruby block 334 result[:data].map! { |element| @postprocessing_map.call(element) } 335 end 336 337 # Return result 338 result 339 end
# File lib/fauna/page.rb 341 def load_page(page) 342 # Not initial after the first page 343 @populated = true 344 345 # Update the page fields 346 @data = page[:data] 347 @before = page[:before] 348 @after = page[:after] 349 end
# File lib/fauna/page.rb 361 def new_page(direction) 362 fail "Invalid direction; must be one of #{CURSOR_KEYS}" unless CURSOR_KEYS.include?(direction) 363 364 cursor = self.send(direction) 365 366 # If there is no next cursor, we have reached the end of the set. 367 # Return +nil+. 368 return nil if cursor.nil? 369 370 # Use the configured cursor to fetch the first page. 371 with_params(direction => cursor) 372 end
# File lib/fauna/page.rb 351 def unload_page 352 # Reset paging 353 @populated = false 354 355 # Reset data 356 @data = nil 357 @before = nil 358 @after = nil 359 end
# File lib/fauna/page.rb 303 def with_dup 304 # Create a copy and drop loaded data 305 page = self.dup 306 page.send(:unload_page) 307 308 # Yield page for manipulation 309 yield page 310 311 # Freeze params and return page 312 page.params.freeze 313 page 314 end