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. Safe on empty relations.



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

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

  counted = relation.except(:order, :limit, :offset).count
  # `.count` on a grouped relation returns a Hash (group => count); for
  # offset pagination the meaningful total is the number of groups.
  total = counted.is_a?(Hash) ? counted.length : counted
  total_pages = per_page.positive? ? (total.to_f / per_page).ceil : 0

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

  set_pagination_headers(total: total, page: page, per_page: per_page, total_pages: total_pages)
  records
end

#pagination_meta(relation) ⇒ Object

Pagination metadata for a relation WITHOUT applying limit/offset — handy for body-based pagination (compose with Respondable’s ‘meta:`).



58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/concerns_on_rails/controllers/paginatable.rb', line 58

def pagination_meta(relation)
  page = pagination_page
  per_page = pagination_per_page
  counted = relation.except(:order, :limit, :offset).count
  total = counted.is_a?(Hash) ? counted.length : counted
  {
    total: total,
    page: page,
    per_page: per_page,
    total_pages: per_page.positive? ? (total.to_f / per_page).ceil : 0
  }
end