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_first_page_url ⇒ Object
- #pagination_items_count ⇒ Object
- #pagination_last_page_url ⇒ Object
- #pagination_next_page_url ⇒ Object
-
#pagination_page ⇒ Object
(also: #current_page)
Getter for the current page.
- #pagination_pages_count ⇒ Object
-
#pagination_per_page ⇒ Object
(also: #paginate_with)
Getter for per_page.
- #pagination_prev_page_url ⇒ Object
Class Method Details
.page_param_desc ⇒ Object
Return the ‘page’ param description
196 197 198 |
# File 'lib/api_helper/paginatable.rb', line 196 def self.page_param_desc "Specify which page you want to get." end |
.per_page_param_desc ⇒ Object
Return the ‘per_page’ param description
191 192 193 |
# File 'lib/api_helper/paginatable.rb', line 191 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:
181 182 183 184 185 186 187 188 |
# File 'lib/api_helper/paginatable.rb', line 181 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
-
Symbol
name of resource to receive the inclusion default_per_page
-
Integer
default per_page maxium_per_page
-
Integer
maximum 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 129 130 131 132 133 134 135 136 137 138 139 140 141 |
# 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_items_count = items_count @pagination_pages_count = pages_count @pagination_page = (params[:page] || 1).to_i @pagination_page = pages_count if @pagination_page > pages_count @pagination_page = 1 if @pagination_page < 1 if current_page > 1 @pagination_first_page_url = add_or_replace_uri_param(request.url, :page, 1) @pagination_prev_page_url = add_or_replace_uri_param(request.url, :page, (current_page > pages_count ? pages_count : current_page - 1)) end if current_page < pages_count @pagination_next_page_url = add_or_replace_uri_param(request.url, :page, current_page + 1) @pagination_last_page_url = add_or_replace_uri_param(request.url, :page, pages_count) end if set_header link_headers ||= [] if current_page > 1 link_headers << "<#{@pagination_first_page_url}>; rel=\"first\"" if @pagination_first_page_url link_headers << "<#{@pagination_prev_page_url}>; rel=\"prev\"" if @pagination_prev_page_url end if current_page < pages_count link_headers << "<#{@pagination_next_page_url}>; rel=\"next\"" if @pagination_next_page_url link_headers << "<#{@pagination_last_page_url}>; rel=\"last\"" if @pagination_last_page_url 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_first_page_url ⇒ Object
163 164 165 |
# File 'lib/api_helper/paginatable.rb', line 163 def pagination_first_page_url @pagination_first_page_url end |
#pagination_items_count ⇒ Object
155 156 157 |
# File 'lib/api_helper/paginatable.rb', line 155 def pagination_items_count @pagination_items_count end |
#pagination_last_page_url ⇒ Object
175 176 177 |
# File 'lib/api_helper/paginatable.rb', line 175 def pagination_last_page_url @pagination_last_page_url end |
#pagination_next_page_url ⇒ Object
171 172 173 |
# File 'lib/api_helper/paginatable.rb', line 171 def pagination_next_page_url @pagination_next_page_url end |
#pagination_page ⇒ Object Also known as: current_page
Getter for the current page
144 145 146 |
# File 'lib/api_helper/paginatable.rb', line 144 def pagination_page @pagination_page end |
#pagination_pages_count ⇒ Object
159 160 161 |
# File 'lib/api_helper/paginatable.rb', line 159 def pagination_pages_count @pagination_pages_count end |
#pagination_per_page ⇒ Object Also known as: paginate_with
Getter for per_page
151 152 153 |
# File 'lib/api_helper/paginatable.rb', line 151 def pagination_per_page @pagination_per_page end |
#pagination_prev_page_url ⇒ Object
167 168 169 |
# File 'lib/api_helper/paginatable.rb', line 167 def pagination_prev_page_url @pagination_prev_page_url end |