The simplest, most flexible, most standards-compliant pagination gem there is. Pairs nicely with begriffs/angular-paginate-anything.
class ApplicationController < ActionController::Base
include CleanPagination
# Using activemodel
def index
max_per_page = 100
paginate Bla.count, max_per_page do |limit, offset|
render json: Bla.limit(limit).offset(offset)
end
end
# Using some custom data
def numbers
paginate Float::INFINITY, 100 do |limit, offset|
render json: (offset...offset+limit).to_a
end
end
# Using optional settings
def options
begin
paginate Foo.scope.count, max_per_page, allow_render: false, raise_errors: true do |limit, offset|
respond_with Foo.scope.limit(limit).offset(offset)
end
rescue RangeError
render json: { error: { message: "invalid pagination range" } }
end
end
end
- HTTP Content-Type agnoticism. Information about total items, selected ranges, and next- previous-links are sent through headers. It works without modifying your API payload in any way.
- Graceful degredation. Both client and server specify the maximum page size they accept and communication gracefully degrades to accomodate the lesser.
- Expressive retrieval. This approach, unlike the use of
per_page
andpage
parameters, allows the client to request any (possibly unbounded) interval of items. - Semantic HTTP. Built in strict conformance to RFCs 2616 and 5988.
To prevent this gem from rendering while still allowing it to set
headers and response codes, pass allow_render: false
to paginate
.
This may be used to avoid DoubleRenderError
situations.
To handle the invalid request range condition in your app, pass the
raise_errors: true
option. This will raise a RangeError
which you can
rescue (and thus control what is rendered). Headers will still be set.
[TODO: explain what the headers mean.] Until this is written you can consult the tests for an idea how it works, or use a client that is compatible, such as begriffs/angular-paginate-anything.