Module: APIHelper::Paginatable
- Extended by:
- ActiveSupport::Concern
- Defined in:
- lib/api_helper/paginatable.rb
Overview
Paginatable
Paginating the requested items can avoid returning too much data in a single response. API clients can iterate over the results with pagination instead of rerteving all the data in one time, ruining the database connection or network.
There are two available URL parameters: per_page and page. The former is used for setting how many resources 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 resources in a request.
Use the page parameter to specify which to page get:
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.
An aditional header, X-Items-Count, will also be set to the total pages count.
Usage
Include this Concern in your Action Controller:
SamplesController < ApplicationController
include APIHelper::Paginatable
end
or in your Grape API class:
class SampleAPI < Grape::API
helpers APIHelper::Paginatable
end
then set the options for pagination in the grape method, as the following as an example:
resources :posts do
get do
collection = current_user.posts
pagination collection.count, default_per_page: 25, maxium_per_page: 100
# ...
end
end
Then use the helper methods like this:
# this example uses kaminari
User.page(pagination_per_page).per(pagination_page)
HTTP Link header will be automatically set by the way.
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
:nodoc:.
-
#pagination(items_count, default_per_page: 20, maxium_per_page: 100, set_header: true) ⇒ Object
Set pagination for the request.
-
#pagination_page ⇒ Object
(also: #current_page)
Getter for the current page.
-
#pagination_per_page ⇒ Object
(also: #paginate_with)
Getter for per_page.
Class Method Details
.page_param_desc ⇒ Object
Return the ‘page’ param description
159 160 161 |
# File 'lib/api_helper/paginatable.rb', line 159 def self.page_param_desc "Specify which page you want to get." end |
.per_page_param_desc ⇒ Object
Return the ‘per_page’ param description
154 155 156 |
# File 'lib/api_helper/paginatable.rb', line 154 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
:nodoc:
144 145 146 147 148 149 150 151 |
# File 'lib/api_helper/paginatable.rb', line 144 def add_or_replace_uri_param(url, param_name, param_value) # :nodoc: 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 |
#pagination(items_count, default_per_page: 20, maxium_per_page: 100, set_header: true) ⇒ Object
Set pagination for the request
Params:
items_count-
Symbolname of resource to receive the inclusion default_per_page-
Integerdefault per_page maxium_per_page-
Integermaximum results do return on a single page
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/api_helper/paginatable.rb', line 84 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 @pagination_per_page = (params[:per_page] || default_per_page).to_i @pagination_per_page = maxium_per_page if @pagination_per_page > maxium_per_page @pagination_per_page = 1 if @pagination_per_page < 1 items_count = 0 if items_count < 0 pages_count = (items_count.to_f / @pagination_per_page).ceil pages_count = 1 if pages_count < 1 @pagination_page = (params[:page] || 1).to_i @pagination_page = pages_count if @pagination_page > pages_count @pagination_page = 1 if @pagination_page < 1 if set_header link_headers ||= [] if current_page > 1 link_headers << "<#{add_or_replace_uri_param(request.url, :page, 1)}>; rel=\"first\"" link_headers << "<#{add_or_replace_uri_param(request.url, :page, (current_page > pages_count ? pages_count : current_page - 1))}>; rel=\"prev\"" end 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 link_header = link_headers.join(', ') if self.respond_to?(:header) self.header('Link', link_header) self.header('X-Items-Count', items_count.to_s) self.header('X-Pages-Count', pages_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 response.headers['X-Pages-Count'] = pages_count.to_s end end end |
#pagination_page ⇒ Object Also known as: current_page
Getter for the current page
131 132 133 |
# File 'lib/api_helper/paginatable.rb', line 131 def pagination_page @pagination_page end |
#pagination_per_page ⇒ Object Also known as: paginate_with
Getter for per_page
138 139 140 |
# File 'lib/api_helper/paginatable.rb', line 138 def pagination_per_page @pagination_per_page end |