Class: Fauna::Page

Inherits:
Object
  • Object
show all
Defined in:
lib/fauna/page.rb

Overview

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(Ref('indexes/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(Ref('indexes/items')), size: 5) do |ref|
  select ['data', 'value'], get(ref)
end

# Same thing, but using builders instead

page = Page.new(client, Query.match(Ref('indexes/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(Ref('indexes/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

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(client, set, params = {}, &lambda) ⇒ Page

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.



52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/fauna/page.rb', line 52

def initialize(client, set, params = {}, &lambda)
  @client = client
  @set = set
  @params = params.dup
  @fauna_funcs = []
  @postprocessing_map = nil

  @fauna_funcs << proc { |query| map(query, &lambda) } unless lambda.nil?

  unload_page
  @params.freeze
end

Instance Attribute Details

#paramsObject (readonly)

The configured params used for the current pagination.



82
83
84
# File 'lib/fauna/page.rb', line 82

def params
  @params
end

Instance Method Details

#==(other) ⇒ Object Also known as: eql?

Returns true if other is a Page and contains the same configuration and data.



66
67
68
69
70
71
72
73
74
75
76
77
# File 'lib/fauna/page.rb', line 66

def ==(other)
  return false unless other.is_a? Page
  @populated == other.instance_variable_get(:@populated) &&
    @data == other.instance_variable_get(:@data) &&
    @before == other.instance_variable_get(:@before) &&
    @after == other.instance_variable_get(:@after) &&
    @client == other.instance_variable_get(:@client) &&
    @set == other.instance_variable_get(:@set) &&
    @params == other.instance_variable_get(:@params) &&
    @fauna_funcs == other.instance_variable_get(:@fauna_funcs) &&
    @postprocessing_map == other.instance_variable_get(:@postprocessing_map)
end

#afterObject

After cursor for the current page.

Lazily loads the page data if it has not already been loaded.



121
122
123
124
# File 'lib/fauna/page.rb', line 121

def after
  load!
  @after
end

#allObject

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.



265
266
267
# File 'lib/fauna/page.rb', line 265

def all
  each.flat_map { |x| x }
end

#beforeObject

Before cursor for the current page.

Lazily loads the page data if it has not already been loaded.



112
113
114
115
# File 'lib/fauna/page.rb', line 112

def before
  load!
  @before
end

#dataObject

Data contained within the current page.

Lazily loads the page data if it has not already been loaded.



103
104
105
106
# File 'lib/fauna/page.rb', line 103

def data
  load!
  @data
end

#dupObject

:nodoc:



292
293
294
295
296
297
# File 'lib/fauna/page.rb', line 292

def dup # :nodoc:
  page = super
  page.instance_variable_set(:@params, @params.dup)
  page.instance_variable_set(:@fauna_funcs, @fauna_funcs.dup)
  page
end

#each {|data| ... } ⇒ Object

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).

Yields:



224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/fauna/page.rb', line 224

def each
  return enum_for(:each) unless block_given?

  # Return current page
  yield data

  # Begin returning pages after
  page = self.page_after
  until page.nil?
    yield page.data
    page = page.page_after
  end
end

#filter(&lambda) ⇒ Object

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) }


174
175
176
177
178
# File 'lib/fauna/page.rb', line 174

def filter(&lambda)
  with_dup do |page|
    page.instance_variable_get(:@fauna_funcs) << proc { |query| filter(query, &lambda) }
  end
end

#foreach!(&lambda) ⇒ Object

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 }


278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/fauna/page.rb', line 278

def foreach!(&lambda)
  # Create new page with foreach block
  iter_page = with_dup do |page|
    page.instance_variable_get(:@fauna_funcs) << proc { |query| foreach(query, &lambda) }
  end

  # Apply to all pages in the set
  until iter_page.nil?
    iter_page.load!
    iter_page = iter_page.page_after
  end
  nil
end

#load!Object

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.



88
89
90
91
92
93
94
95
# File 'lib/fauna/page.rb', line 88

def load!
  if @populated
    false
  else
    load_page(get_page(@params))
    true
  end
end

#map(&lambda) ⇒ Object

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 }


157
158
159
160
161
# File 'lib/fauna/page.rb', line 157

def map(&lambda)
  with_dup do |page|
    page.instance_variable_get(:@fauna_funcs) << proc { |query| map(query, &lambda) }
  end
end

#page_afterObject

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.



207
208
209
# File 'lib/fauna/page.rb', line 207

def page_after
  new_page(:after)
end

#page_beforeObject

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.



216
217
218
# File 'lib/fauna/page.rb', line 216

def page_before
  new_page(:before)
end

#postprocessing_map(&block) ⇒ Object

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) }


194
195
196
197
198
# File 'lib/fauna/page.rb', line 194

def postprocessing_map(&block)
  with_dup do |page|
    page.instance_variable_set(:@postprocessing_map, block)
  end
end

#reverse_each {|data| ... } ⇒ Object

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.

Yields:



244
245
246
247
248
249
250
251
252
253
254
255
256
# File 'lib/fauna/page.rb', line 244

def reverse_each
  return enum_for(:reverse_each) unless block_given?

  # Return current page
  yield data

  # Begin returning pages before
  page = self.page_before
  until page.nil?
    yield page.data
    page = page.page_before
  end
end

#with_params(params = {}) ⇒ Object

Returns a copy of the page with the given params set.

See paginate for more details.



132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'lib/fauna/page.rb', line 132

def with_params(params = {})
  with_dup do |page|
    page_params = page.instance_variable_get(:@params)

    if CURSOR_KEYS.any? { |key| params.include? key }
      # Remove previous cursor
      CURSOR_KEYS.each { |key| page_params.delete key }
    end

    # Update params
    page_params.merge!(params)
  end
end