Module: APIHelper::Paginatable
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/api_helper/paginatable.rb
Overview
Helper To Make Resource APIs Paginatable
Paginating the requested items can avoid returning too much information in a single response. API callers can iterate over the results using pagination instead of rerteving all the data in one time, ruining the database connection or network.
There are two parameters clients can use: per_page and page. The former is used for setting how many data will be returned in each page, there will be a maxium limit and default value for each API:
GET /posts?per_page=10
The server will respond 10 items at a time.
Use the page parameter to specify which to retrieve:
GET /posts?page=5
Pagination info will be provided in the HTTP Link header like this:
Link: <http://api-server.dev/movies?page=1>; rel="first",
<http://api-server.dev/movies?page=4>; rel="prev"
<http://api-server.dev/movies?page=6>; rel="next",
<http://api-server.dev/movies?page=238>; rel="last"
Line breaks are added for readability.
Which follows the proposed RFC 5988 standard.
Usage
Include this Concern in your Action Controller:
SamplesController < ApplicationController
include APIHelper::Paginatable
end
or in your Grape API class:
class SampleAPI < Grape::API
include APIHelper::Paginatable
end
then set the options for pagination in the grape method:
resources :posts do
get do
pagination User.count, default_per_page: 25, maxium_per_page: 100
# ...
end
end
Then use the helper methods, like this:
User.page(page).per(per_page)
HTTP Link header will be automatically set.
Class Method Summary collapse
-
.page_param_desc ⇒ Object
Return the ‘page’ param description.
-
.per_page_param_desc ⇒ Object
Return the ‘per_page’ param description.
Instance Method Summary collapse
- #add_or_replace_uri_param(url, param_name, param_value) ⇒ Object
-
#page ⇒ Object
(also: #current_page)
Getter for the current page.
- #pagination(items_count, default_per_page: 20, maxium_per_page: 100, set_header: true) ⇒ Object
-
#per_page ⇒ Object
(also: #page_with)
Getter for per_page.
Class Method Details
.page_param_desc ⇒ Object
Return the ‘page’ param description
137 138 139 |
# File 'lib/api_helper/paginatable.rb', line 137 def self.page_param_desc "Specify which page you want to get." end |
.per_page_param_desc ⇒ Object
Return the ‘per_page’ param description
132 133 134 |
# File 'lib/api_helper/paginatable.rb', line 132 def self.per_page_param_desc "Specify how many items you want each page to return." end |
Instance Method Details
#add_or_replace_uri_param(url, param_name, param_value) ⇒ Object
122 123 124 125 126 127 128 129 |
# File 'lib/api_helper/paginatable.rb', line 122 def add_or_replace_uri_param(url, param_name, param_value) uri = URI(url) params = URI.decode_www_form(uri.query || '') params.delete_if { |param| param[0].to_s == param_name.to_s } params << [param_name, param_value] uri.query = URI.encode_www_form(params) uri.to_s end |
#page ⇒ Object Also known as: current_page
Getter for the current page
109 110 111 |
# File 'lib/api_helper/paginatable.rb', line 109 def page @page end |
#pagination(items_count, default_per_page: 20, maxium_per_page: 100, set_header: true) ⇒ Object
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/api_helper/paginatable.rb', line 65 def pagination(items_count, default_per_page: 20, maxium_per_page: 100, set_header: true) items_count = items_count.count if items_count.respond_to? :count @per_page = (params[:per_page] || default_per_page).to_i @per_page = maxium_per_page if @per_page > maxium_per_page @per_page = 1 if @per_page < 1 items_count = 0 if items_count < 0 pages_count = (items_count.to_f / @per_page).ceil pages_count = 1 if pages_count < 1 @page = (params[:page] || 1).to_i @page = pages_count if @page > pages_count @page = 1 if @page < 1 link_headers ||= [] if current_page < pages_count link_headers << "<#{add_or_replace_uri_param(request.url, :page, current_page + 1)}>; rel=\"next\"" link_headers << "<#{add_or_replace_uri_param(request.url, :page, pages_count)}>; rel=\"last\"" end if current_page > 1 link_headers << "<#{add_or_replace_uri_param(request.url, :page, (current_page > pages_count ? pages_count : current_page - 1))}>; rel=\"prev\"" link_headers << "<#{add_or_replace_uri_param(request.url, :page, 1)}>; rel=\"first\"" end link_header = link_headers.join(', ') if set_header if self.respond_to?(:header) self.header('Link', link_header) self.header('X-Items-Count', items_count.to_s) end if defined?(response) && response.respond_to?(:headers) response.headers['Link'] = link_header response.headers['X-Items-Count'] = items_count.to_s end end link_header end |
#per_page ⇒ Object Also known as: page_with
Getter for per_page
116 117 118 |
# File 'lib/api_helper/paginatable.rb', line 116 def per_page @per_page end |