Class: JsonApiServer::Pagination
- Inherits:
-
Object
- Object
- JsonApiServer::Pagination
- Defined in:
- lib/json_api_server/pagination.rb
Overview
Description
JSON API Spec: jsonapi.org/format/#fetching-pagination - “Pagination links MUST appear in the links object that corresponds to a collection. To paginate the primary data, supply pagination links in the top-level links object.”
This class handles pagination. It (1) ensures page[number]
is a positive integer, (2) page[limit]
doesn’t exceed a maximum value and (3) generates a pagination sub-query (to be merged into a master query). It uses the WillPaginate gem rubygems.org/gems/will_paginate/versions/3.1.6.
Usage:
A paginating request will look like:
/comments?page[number]=1&page[limit]=10
Where:
-
page[number]
is the current page -
page[limit]
is number of records per page
The class takes an ActiveDispatch::Request object, an ActiveRecord::Base model (to generate a pagination sub-query) and two options:
:max_per_page
- maximum number of records per page which defaults to JsonApiServer::Configuration#default_max_per_page.
:default_per_page
- number of records to show if not specified in page[limit]
defaults to JsonApiServer::Configuration#default_per_page).
Example:
Create an instance in your controller:
pagination = JsonApiServer::Pagination.new(request, Comment, max_per_page: 50, default_per_page: 10)
Merge pagination sub-query into your ActiveRecord query:
recent_comments = Comment.recent.merge(pagination.query)
Get JsonApiServer::Paginator instance to create links in your JSON serializer:
paginator = pagination.paginator_for(recent_comments)
paginator.as_json # creates JSON API links
Pass paginator as param to a class inheriting from JsonApiServer::ResourcesSerializer and it creates the links section for you.
class CommentsSerializer < JsonApiServer::ResourcesSerializer
serializer CommentSerializer
end
serializer = CommentsSerializer.new(recent_comments, paginator: paginator)
Note:
JsonApiServer::Builder class provides an easier way to use this class.
Instance Attribute Summary collapse
-
#default_per_page ⇒ Object
readonly
Default number of records to show per page.
-
#max_per_page ⇒ Object
readonly
Maximum records per page.
-
#model ⇒ Object
readonly
ActiveRecord::Base model passed in constructor.
-
#params ⇒ Object
readonly
Query parameters from #request.
-
#request ⇒ Object
readonly
ActionDispatch::Request passed in constructor.
Class Method Summary collapse
-
.default_max_per_page ⇒ Object
Default max per page.
-
.default_per_page ⇒ Object
Default per page.
Instance Method Summary collapse
-
#base_url ⇒ Object
Joins JsonApiServer::Configuration#base_url with request.path.
-
#initialize(request, model, **options) ⇒ Pagination
constructor
Arguments: -
request
- ActionDispatch::Request -model
- ActiveRecord::Base model. -
#page ⇒ Object
(also: #number)
The current page number.
-
#paginator_for(collection, options = {}) ⇒ Object
Create an instance of JsonApiServer::Paginator for a WillPaginate collection.
-
#per_page ⇒ Object
(also: #limit)
Number of records per page.
-
#relation ⇒ Object
(also: #query)
Calls WillPaginate ‘paginate’ method with #page and #per_page.
Constructor Details
#initialize(request, model, **options) ⇒ Pagination
Arguments:
-
request
- ActionDispatch::Request -
model
- ActiveRecord::Base model. Used to generate sub-query. -
options
- (Hash)-
:max_per_page (Integer) - Optional. Defaults to JsonApiServer.configuration.default_max_per_page.
-
:default_per_page (Integer) - Optional. Defaults to JsonApiServer.configuration.default_per_page.
-
85 86 87 88 89 90 91 |
# File 'lib/json_api_server/pagination.rb', line 85 def initialize(request, model, **) @request = request @model = model @max_per_page = ([:max_per_page] || self.class.default_max_per_page).to_i @default_per_page = ([:default_per_page] || self.class.default_per_page).to_i @params = request.query_parameters end |
Instance Attribute Details
#default_per_page ⇒ Object (readonly)
Default number of records to show per page. If page[limit]
is not present, it will use this value. If this is not set, it will use JsonApiServer.configuration.default_per_page.
76 77 78 |
# File 'lib/json_api_server/pagination.rb', line 76 def default_per_page @default_per_page end |
#max_per_page ⇒ Object (readonly)
Maximum records per page. Prevents users from requesting too many records. Passed into constructor.
71 72 73 |
# File 'lib/json_api_server/pagination.rb', line 71 def max_per_page @max_per_page end |
#model ⇒ Object (readonly)
ActiveRecord::Base model passed in constructor.
64 65 66 |
# File 'lib/json_api_server/pagination.rb', line 64 def model @model end |
#params ⇒ Object (readonly)
Query parameters from #request.
67 68 69 |
# File 'lib/json_api_server/pagination.rb', line 67 def params @params end |
#request ⇒ Object (readonly)
ActionDispatch::Request passed in constructor.
61 62 63 |
# File 'lib/json_api_server/pagination.rb', line 61 def request @request end |
Class Method Details
.default_max_per_page ⇒ Object
Default max per page. Defaults to JsonApiServer.configuration.default_max_per_page
110 111 112 |
# File 'lib/json_api_server/pagination.rb', line 110 def default_max_per_page JsonApiServer.configuration.default_max_per_page end |
.default_per_page ⇒ Object
Default per page. Defaults to JsonApiServer.configuration.default_per_page.
115 116 117 |
# File 'lib/json_api_server/pagination.rb', line 115 def default_per_page JsonApiServer.configuration.default_per_page end |
Instance Method Details
#base_url ⇒ Object
Joins JsonApiServer::Configuration#base_url with request.path.
167 168 169 |
# File 'lib/json_api_server/pagination.rb', line 167 def base_url @base_url ||= File.join(JsonApiServer.configuration.base_url, request.path) end |
#page ⇒ Object Also known as: number
The current page number. From query parameter page</tt>.
153 154 155 156 157 158 159 160 161 162 |
# File 'lib/json_api_server/pagination.rb', line 153 def page @page ||= begin n = begin params[:page][:number].to_i rescue 1 end n <= 0 ? 1 : n end end |
#paginator_for(collection, options = {}) ⇒ Object
Create an instance of JsonApiServer::Paginator for a WillPaginate collection. Returns nil if not a WillPaginate collection.
params:
-
collection
(WillPaginate collection) - i.e., Comment.recent.paginate(page: x, per_page: y) -
options
(Hash): -
per_page
(Integer) - defaults to self.per_page. -
base_url
(String) - defaults to self.base_url (joins JsonApiServer.configuration.base_url with request.path).
128 129 130 131 132 133 134 135 |
# File 'lib/json_api_server/pagination.rb', line 128 def paginator_for(collection, = {}) if collection.respond_to?(:current_page) && collection.respond_to?(:total_pages) # call to_i on WillPaginate::PageNumber which DelegateClass(Integer) # paginator(collection.current_page.to_i, collection.total_pages.to_i, options) # HACK: collection.current_page.to_i disappears when merged? works w/o merge. paginator(page, collection.total_pages.to_i, ) end end |
#per_page ⇒ Object Also known as: limit
Number of records per page. From query parameter page[limit]
.
138 139 140 141 142 143 144 145 146 147 148 |
# File 'lib/json_api_server/pagination.rb', line 138 def per_page @per_page ||= begin l = begin params[:page][:limit].to_i rescue default_per_page end l = [max_per_page, l].min l <= 0 ? default_per_page : l end end |
#relation ⇒ Object Also known as: query
Calls WillPaginate ‘paginate’ method with #page and #per_page. Returns an ActiveRecord::Relation object (a query fragment) which can be merged into another query with merge.
Example:
pagination = JsonApiServer::Pagination.new(request, Comment, )
recent_comments = Comment.recent.merge(pagination.relation)
102 103 104 |
# File 'lib/json_api_server/pagination.rb', line 102 def relation @relation ||= model.paginate(page: page, per_page: per_page) end |