Module: ConcernsOnRails::Controllers::Paginatable

Extended by:
ActiveSupport::Concern
Defined in:
lib/concerns_on_rails/controllers/paginatable.rb

Overview

Adds simple offset-based pagination to a controller, with no runtime dependency on Kaminari/will_paginate. Use it like:

class ArticlesController < ApplicationController
include ConcernsOnRails::Controllers::Paginatable
paginate_by per_page: 25, max_per_page: 200   # optional

def index
  render json: paginated(Article.all)
end
end

Constant Summary collapse

DEFAULT_PER_PAGE =
25
DEFAULT_MAX_PER_PAGE =
200

Instance Method Summary collapse

Instance Method Details

#paginated(relation) ⇒ Object

Apply pagination to a relation and set the standard response headers. Returns the paginated relation; the metadata is memoized so a follow-up pagination_meta (no argument) reuses it. Safe on empty relations.



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# File 'lib/concerns_on_rails/controllers/paginatable.rb', line 41

def paginated(relation)
  @paginatable_meta = nil
  page = pagination_page
  per_page = pagination_per_page
  offset = (page - 1) * per_page

  total = paginatable_total(relation)
  total_pages = per_page.positive? ? (total.to_f / per_page).ceil : 0

  records = relation.limit(per_page).offset(offset)

  @paginatable_meta = { total: total, page: page, per_page: per_page, total_pages: total_pages }
  set_pagination_headers(**@paginatable_meta)
  records
end

#pagination_meta(relation = nil) ⇒ Object

Pagination metadata WITHOUT applying limit/offset — handy for body-based pagination (compose with Respondable's meta:). Call with no argument after paginated to reuse its memoized meta — the documented records+meta composition used to run the identical COUNT twice per request. Pass a relation to compute fresh.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/concerns_on_rails/controllers/paginatable.rb', line 62

def pagination_meta(relation = nil)
  return @paginatable_meta if relation.nil? && @paginatable_meta

  if relation.nil?
    raise ArgumentError,
          "ConcernsOnRails::Controllers::Paginatable: pagination_meta needs a relation " \
          "(no prior paginated call in this request to reuse)"
  end

  total = paginatable_total(relation)
  per_page = pagination_per_page
  {
    total: total,
    page: pagination_page,
    per_page: per_page,
    total_pages: per_page.positive? ? (total.to_f / per_page).ceil : 0
  }
end