-
Notifications
You must be signed in to change notification settings - Fork 411
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
14 changed files
with
331 additions
and
34 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
--- | ||
title: Jsonapi | ||
categories: | ||
- Feature | ||
- Backend | ||
- Extra | ||
--- | ||
|
||
# Jsonapi Extra | ||
|
||
Implements the [JSON:API](https://jsonapi.org) specifications for pagination. | ||
|
||
When enabled, the query params used in the pagy URLs are nested under the `page` param, as specified by the [Query Parameter Family](https://jsonapi.org/format/#query-parameters-families) e.g. `https://example.com/products?page[number]=2&page[size]=30`. | ||
|
||
## Synopsis | ||
|
||
### Default usage | ||
|
||
||| pagy.rb (initializer) | ||
```ruby | ||
require 'pagy/extras/jsonapi' # works without further configuration | ||
``` | ||
||| | ||
|
||
||| Controller | ||
```ruby | ||
# enabled by default | ||
@pagy, @records = pagy(collection) | ||
# you can disable it explicitly for specific requests | ||
@pagy, @records = pagy(collection, jsonapi: false) | ||
``` | ||
||| | ||
|
||
### Custom usage | ||
|
||
||| pagy.rb (initializer) | ||
```ruby | ||
# optionally require other jsonapi-useful extras | ||
require 'pagy/extras/items' | ||
# jsonapi must be required AFTER other extras | ||
require 'pagy/extras/jsonapi' | ||
# optionally disable it by default (opt-in) | ||
Pagy::DEFAULT[:jsonapi] = false # default true | ||
``` | ||
||| | ||
|
||
||| Controller | ||
```ruby | ||
# disabled by default by the above Pagy::DEFAULT[:jsonapi] = false | ||
@pagy, @records = pagy(collection) | ||
# explicitly enable it for specific requests | ||
@pagy, @records = pagy(collection, jsonapi: true) | ||
# optional/custom setup | ||
@pagy, @records = pagy(collection, jsonapi: true, # enable the jsonapi specifications | ||
items_extra: true, # enable the items extra | ||
page_param: :number, # use page[number] param name instead of page[page] | ||
items_params: :size) # use page[size] param name instead of page[items] | ||
# get the links URL hash | ||
links_hash = pagy_jsonapi_links(@pagy) | ||
#=> {first: 'https://example.com/products?page[number]=1&page[size]=50&...', | ||
# last: 'https://example.com/products?page[number]=32&page[size]=50&...', | ||
# prev: 'https://example.com/products?page[number]=31&page[size]=50&...', | ||
# next: 'https://example.com/products?page[number]=33&page[size]=50&...'} | ||
``` | ||
||| | ||
|
||
## Files | ||
|
||
- [items.rb](https://github.com/ddnexus/pagy/blob/master/lib/pagy/extras/jsonapi.rb) | ||
|
||
## Variables | ||
|
||
| Variable | Description | Default | | ||
|:-----------|:------------------------------|:--------| | ||
| `:jsonapi` | Enable or disable the feature | `true` | | ||
|
||
You can use the `:jsonapi` variable to opt-out of the feature even when the extra is required. | ||
|
||
## Interaction with other features/extras | ||
|
||
This extra just nests the `:page` and `:items` params under the JSON:API reserved `:page` param. You may want to customize the `:page_param` and the `:items` params as shown in the [Synopsis](#synopsis). | ||
|
||
You may also want to use it with the [items extra](/docs/extras/items.md) in order to allow the client to request a specific number of items per page and capping it to a max number. | ||
|
||
It works also with the [countless](countless.md), [searchkick](searchkick.md), [elasticsearch_rails](elasticsearch_rails.md) and [meilisearch](/docs/extras/meilisearch.md) extras. | ||
|
||
It does not make sense (and doesn't work) with the [Calendar](countless.md) extra. | ||
|
||
## Methods | ||
|
||
The `jsonapi` extra adds the `pagy_jsonapi_links` helper to the `Pagy::Backend` module. | ||
|
||
=== `pagy_jsonapi_links(pagy, **opts)` | ||
|
||
This helper provides the JSON:API [links for pagination](https://jsonapi.org/format/#fetching-pagination) as a hash of `first`, `last`, `prev`, `next` paths. You can pass the option `asbsolute: true` to get an absolute URL instead. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/jsonapi | ||
# frozen_string_literal: true | ||
|
||
require 'pagy/url_helpers' | ||
|
||
class Pagy # :nodoc: | ||
DEFAULT[:jsonapi] = true | ||
|
||
# Add a specialized backend method compliant with JSON:API | ||
module JsonApiExtra | ||
# JsonApi :page param error | ||
class ReservedParamError < StandardError | ||
# Inform about the actual value | ||
def initialize(value) | ||
super("expected reserved :page param to be nil or Hash; got #{value.inspect}") | ||
end | ||
end | ||
|
||
private | ||
|
||
include UrlHelpers | ||
|
||
# Return the jsonapi links | ||
def pagy_jsonapi_links(pagy, **opts) | ||
{ first: pagy_url_for(pagy, 1, **opts), | ||
last: pagy_url_for(pagy, pagy.last, **opts), | ||
prev: pagy_url_for(pagy, pagy.prev, **opts), | ||
next: pagy_url_for(pagy, pagy.next, **opts) } | ||
end | ||
|
||
# Should skip the jsonapi | ||
def pagy_skip_jsonapi?(vars) | ||
return true if vars[:jsonapi] == false || (vars[:jsonapi].nil? && DEFAULT[:jsonapi] == false) | ||
# check the reserved :page param and raise PageParamError or return nil | ||
raise ReservedParamError, params[:page] unless params[:page].is_a?(Hash) || params[:page].nil? | ||
end | ||
|
||
# Override the Backend method | ||
def pagy_get_page(vars) | ||
return super if pagy_skip_jsonapi?(vars) | ||
|
||
((params[:page].is_a?(Hash) && params[:page][vars[:page_param] || DEFAULT[:page_param]]) || 1).to_i | ||
end | ||
|
||
# Override the ItemsExtra::Backend method | ||
def pagy_get_items_size(vars) | ||
return super if pagy_skip_jsonapi?(vars) | ||
|
||
params[:page][vars[:items_param] || DEFAULT[:items_param]] if params[:page].is_a?(Hash) | ||
end | ||
|
||
# Override UrlHelper method | ||
def pagy_set_query_params(page, vars, params) | ||
return super unless vars[:jsonapi] | ||
|
||
params['page'] ||= {} | ||
params['page'][vars[:page_param].to_s] = page | ||
params['page'][vars[:items_param].to_s] = vars[:items] if vars[:items_extra] | ||
end | ||
end | ||
Backend.prepend JsonApiExtra | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.