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

params[R]

The configured params used for the current pagination.

Public Class Methods

new(client, set, params = {}, &lambda) click to toggle source

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

==(other) click to toggle source

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
Also aliased as: eql?
eql?(other)
Alias for: ==
load!() click to toggle source

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

↑ top

Public Instance Methods

filter(&lambda) click to toggle source

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
map(&lambda) click to toggle source

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
postprocessing_map(&block) click to toggle source

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
with_params(params = {}) click to toggle source

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

↑ top

Public Instance Methods

after() click to toggle source

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() click to toggle source

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() click to toggle source

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

↑ top

Public Instance Methods

all() click to toggle source

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
each() { |data| ... } click to toggle source

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
foreach!(&lambda) click to toggle source

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
page_after() click to toggle source

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
page_before() click to toggle source

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
reverse_each() { |data| ... } click to toggle source

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

get_page(params) click to toggle source
    # 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
load_page(page) click to toggle source
    # 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
new_page(direction) click to toggle source
    # 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
unload_page() click to toggle source
    # 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
with_dup() { |page| ... } click to toggle source
    # 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