Class: SolidObjects::Web::Paginator

Inherits:
Object
  • Object
show all
Defined in:
lib/solid_objects/web/paginator.rb,
sig/generated/lib/solid_objects/web/paginator.rbs

Overview

Counts and slices one relation. The page size is clamped because the page number and the page size both arrive from the query string, and an operator page that accepts an unbounded limit is a denial of service against the database the actors run on.

Constant Summary collapse

DEFAULT_PER_PAGE =

Returns:

  • (::Integer)
25
MAXIMUM_PER_PAGE =

Returns:

  • (::Integer)
200

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(relation:, page: nil, per_page: nil) ⇒ Paginator

Returns a new instance of Paginator.

RBS:

  • (relation: untyped, ?page: String?, ?per_page: String?) -> void

Parameters:

  • relation: (Object)
  • page: (String, nil) (defaults to: nil)
  • per_page: (String, nil) (defaults to: nil)


21
22
23
24
25
26
# File 'lib/solid_objects/web/paginator.rb', line 21

def initialize(relation:, page: nil, per_page: nil)
  @per_page = bounded(per_page, default: DEFAULT_PER_PAGE, maximum: MAXIMUM_PER_PAGE)
  @total = relation.count
  @page = bounded(page, default: 1, maximum: last_page)
  @records = relation.offset((@page - 1) * @per_page).limit(@per_page).to_a
end

Instance Attribute Details

#pageObject (readonly)

RBS:

  • @page: Integer

  • @per_page: Integer

  • @total: Integer

  • @records: Array[untyped]

Returns:

  • (Object)


18
19
20
# File 'lib/solid_objects/web/paginator.rb', line 18

def page
  @page
end

#per_pageObject (readonly)

RBS:

  • @page: Integer

  • @per_page: Integer

  • @total: Integer

  • @records: Array[untyped]

Returns:

  • (Object)


18
19
20
# File 'lib/solid_objects/web/paginator.rb', line 18

def per_page
  @per_page
end

#recordsObject (readonly)

RBS:

  • @page: Integer

  • @per_page: Integer

  • @total: Integer

  • @records: Array[untyped]

Returns:

  • (Object)


18
19
20
# File 'lib/solid_objects/web/paginator.rb', line 18

def records
  @records
end

#totalObject (readonly)

RBS:

  • @page: Integer

  • @per_page: Integer

  • @total: Integer

  • @records: Array[untyped]

Returns:

  • (Object)


18
19
20
# File 'lib/solid_objects/web/paginator.rb', line 18

def total
  @total
end

Instance Method Details

#bounded(value, default:, maximum:) ⇒ Integer

RBS:

  • (String?, default: Integer, maximum: Integer) -> Integer

Parameters:

  • (String, nil)
  • default: (Integer)
  • maximum: (Integer)

Returns:

  • (Integer)


56
57
58
59
60
61
# File 'lib/solid_objects/web/paginator.rb', line 56

def bounded(value, default:, maximum:)
  requested = Integer(value.to_s, 10, exception: false)
  return default unless requested&.positive?

  [ requested, maximum ].min
end

#first_recordInteger

RBS:

  • () -> Integer

Returns:

  • (Integer)


44
45
46
# File 'lib/solid_objects/web/paginator.rb', line 44

def first_record
  total.zero? ? 0 : ((page - 1) * per_page) + 1
end

#last_pageInteger

RBS:

  • () -> Integer

Returns:

  • (Integer)


29
30
31
# File 'lib/solid_objects/web/paginator.rb', line 29

def last_page
  [ (total.to_f / per_page).ceil, 1 ].max
end

#last_recordInteger

RBS:

  • () -> Integer

Returns:

  • (Integer)


49
50
51
# File 'lib/solid_objects/web/paginator.rb', line 49

def last_record
  [ page * per_page, total ].min
end

#next_pageInteger?

RBS:

  • () -> Integer?

Returns:

  • (Integer, nil)


39
40
41
# File 'lib/solid_objects/web/paginator.rb', line 39

def next_page
  (page < last_page) ? page + 1 : nil
end

#previous_pageInteger?

RBS:

  • () -> Integer?

Returns:

  • (Integer, nil)


34
35
36
# File 'lib/solid_objects/web/paginator.rb', line 34

def previous_page
  (page > 1) ? page - 1 : nil
end