mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-03-04 02:31:33 +00:00
Add pagination with Pagy using structure from JSON:API specification
https://jsonapi.org/examples/#pagination Update schema for collections rendered with pagination data
This commit is contained in:
committed by
Maikel Linke
parent
c102ce8e7e
commit
3dbf00f302
@@ -582,6 +582,7 @@ Metrics/MethodLength:
|
||||
- 'app/controllers/spree/orders_controller.rb'
|
||||
- 'app/helpers/checkout_helper.rb'
|
||||
- 'app/helpers/spree/admin/navigation_helper.rb'
|
||||
- "app/json_schemas/json_api_schema.rb"
|
||||
- 'app/models/spree/ability.rb'
|
||||
- 'app/models/spree/gateway/pay_pal_express.rb'
|
||||
- 'app/models/spree/order/checkout.rb'
|
||||
|
||||
@@ -5,6 +5,8 @@ module Api
|
||||
class BaseController < ActionController::API
|
||||
include CanCan::ControllerAdditions
|
||||
include RequestTimeouts
|
||||
include Pagy::Backend
|
||||
include JsonApiPagination
|
||||
|
||||
check_authorization
|
||||
|
||||
|
||||
@@ -11,9 +11,9 @@ module Api
|
||||
before_action :authorize_action, only: [:show, :update, :destroy]
|
||||
|
||||
def index
|
||||
customers = search_customers
|
||||
@pagy, customers = pagy(search_customers, pagy_options)
|
||||
|
||||
render json: Api::V1::CustomerSerializer.new(customers, is_collection: true)
|
||||
render json: Api::V1::CustomerSerializer.new(customers, pagination_options)
|
||||
end
|
||||
|
||||
def show
|
||||
|
||||
74
app/controllers/concerns/json_api_pagination.rb
Normal file
74
app/controllers/concerns/json_api_pagination.rb
Normal file
@@ -0,0 +1,74 @@
|
||||
# frozen_string_literal: true
|
||||
|
||||
module JsonApiPagination
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
DEFAULT_PER_PAGE = 50
|
||||
MAX_PER_PAGE = 200
|
||||
|
||||
def pagination_options
|
||||
{
|
||||
is_collection: true,
|
||||
meta: meta_options,
|
||||
links: links_options,
|
||||
}
|
||||
end
|
||||
|
||||
def pagy_options
|
||||
{ items: final_per_page_value }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def meta_options
|
||||
{
|
||||
pagination: {
|
||||
results: @pagy.count,
|
||||
pages: total_pages,
|
||||
page: current_page,
|
||||
per_page: final_per_page_value
|
||||
}
|
||||
}
|
||||
end
|
||||
|
||||
def links_options
|
||||
{
|
||||
self: pagination_url(current_page),
|
||||
first: pagination_url(1),
|
||||
prev: pagination_url(previous_page),
|
||||
next: pagination_url(next_page),
|
||||
last: pagination_url(total_pages)
|
||||
}
|
||||
end
|
||||
|
||||
def pagination_url(page_number)
|
||||
return if page_number.nil?
|
||||
|
||||
url_for(only_path: false, params: request.query_parameters.merge(page: page_number))
|
||||
end
|
||||
|
||||
# User-specified value, or DEFAULT_PER_PAGE, capped at MAX_PER_PAGE
|
||||
def final_per_page_value
|
||||
(params[:per_page] || DEFAULT_PER_PAGE).to_i.clamp(1, MAX_PER_PAGE)
|
||||
end
|
||||
|
||||
def current_page
|
||||
params[:page] || 1
|
||||
end
|
||||
|
||||
def total_pages
|
||||
@pagy.pages
|
||||
end
|
||||
|
||||
def previous_page
|
||||
return nil if current_page < 2
|
||||
|
||||
current_page - 1
|
||||
end
|
||||
|
||||
def next_page
|
||||
return nil if current_page >= total_pages
|
||||
|
||||
current_page + 1
|
||||
end
|
||||
end
|
||||
@@ -22,7 +22,8 @@ class JsonApiSchema
|
||||
type: :object,
|
||||
properties: data_properties(**options)
|
||||
},
|
||||
meta: { type: :object }
|
||||
meta: { type: :object },
|
||||
links: { type: :object }
|
||||
},
|
||||
required: [:data]
|
||||
}
|
||||
@@ -39,9 +40,33 @@ class JsonApiSchema
|
||||
properties: data_properties(**options)
|
||||
}
|
||||
},
|
||||
meta: { type: :object }
|
||||
meta: {
|
||||
type: :object,
|
||||
properties: {
|
||||
pagination: {
|
||||
type: :object,
|
||||
properties: {
|
||||
results: { type: :integer, example: 250 },
|
||||
pages: { type: :integer, example: 5 },
|
||||
page: { type: :integer, example: 2 },
|
||||
per_page: { type: :integer, example: 50 },
|
||||
}
|
||||
}
|
||||
},
|
||||
required: [:pagination]
|
||||
},
|
||||
links: {
|
||||
type: :object,
|
||||
properties: {
|
||||
self: { type: :string },
|
||||
first: { type: :string },
|
||||
prev: { type: :string, nullable: true },
|
||||
next: { type: :string, nullable: true },
|
||||
last: { type: :string }
|
||||
}
|
||||
}
|
||||
},
|
||||
required: [:data]
|
||||
required: [:data, :meta, :links]
|
||||
}
|
||||
end
|
||||
|
||||
|
||||
@@ -66,6 +66,8 @@ components:
|
||||
type: object
|
||||
meta:
|
||||
type: object
|
||||
links:
|
||||
type: object
|
||||
required:
|
||||
- data
|
||||
securitySchemas:
|
||||
@@ -149,8 +151,43 @@ paths:
|
||||
type: object
|
||||
meta:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
type: object
|
||||
properties:
|
||||
results:
|
||||
type: integer
|
||||
example: 250
|
||||
pages:
|
||||
type: integer
|
||||
example: 5
|
||||
page:
|
||||
type: integer
|
||||
example: 2
|
||||
per_page:
|
||||
type: integer
|
||||
example: 50
|
||||
required:
|
||||
- pagination
|
||||
links:
|
||||
type: object
|
||||
properties:
|
||||
self:
|
||||
type: string
|
||||
first:
|
||||
type: string
|
||||
prev:
|
||||
type: string
|
||||
nullable: true
|
||||
next:
|
||||
type: string
|
||||
nullable: true
|
||||
last:
|
||||
type: string
|
||||
required:
|
||||
- data
|
||||
- meta
|
||||
- links
|
||||
post:
|
||||
summary: Create customer
|
||||
tags:
|
||||
@@ -208,6 +245,8 @@ paths:
|
||||
type: object
|
||||
meta:
|
||||
type: object
|
||||
links:
|
||||
type: object
|
||||
required:
|
||||
- data
|
||||
'422':
|
||||
@@ -322,6 +361,8 @@ paths:
|
||||
type: object
|
||||
meta:
|
||||
type: object
|
||||
links:
|
||||
type: object
|
||||
required:
|
||||
- data
|
||||
'404':
|
||||
@@ -430,6 +471,8 @@ paths:
|
||||
type: object
|
||||
meta:
|
||||
type: object
|
||||
links:
|
||||
type: object
|
||||
required:
|
||||
- data
|
||||
'422':
|
||||
@@ -546,6 +589,8 @@ paths:
|
||||
type: object
|
||||
meta:
|
||||
type: object
|
||||
links:
|
||||
type: object
|
||||
required:
|
||||
- data
|
||||
"/api/v1/enterprises/{enterprise_id}/customers":
|
||||
@@ -614,7 +659,42 @@ paths:
|
||||
type: object
|
||||
meta:
|
||||
type: object
|
||||
properties:
|
||||
pagination:
|
||||
type: object
|
||||
properties:
|
||||
results:
|
||||
type: integer
|
||||
example: 250
|
||||
pages:
|
||||
type: integer
|
||||
example: 5
|
||||
page:
|
||||
type: integer
|
||||
example: 2
|
||||
per_page:
|
||||
type: integer
|
||||
example: 50
|
||||
required:
|
||||
- pagination
|
||||
links:
|
||||
type: object
|
||||
properties:
|
||||
self:
|
||||
type: string
|
||||
first:
|
||||
type: string
|
||||
prev:
|
||||
type: string
|
||||
nullable: true
|
||||
next:
|
||||
type: string
|
||||
nullable: true
|
||||
last:
|
||||
type: string
|
||||
required:
|
||||
- data
|
||||
- meta
|
||||
- links
|
||||
servers:
|
||||
- url: "/"
|
||||
|
||||
Reference in New Issue
Block a user