Pagination
A list endpoint answers one page at a time — limit records from offset — and both the page size
a request gets by default and the largest one it may ask for are configurable, per application and
per resource.
Declaration
class OrdersController < ApplicationController
include Habarico::Controller
model Order
fields %i[number customer status total created_at]
default_page_limit 50
max_page_limit 200
end
GET /orders now answers with 50 orders, ?limit=200 with 200, and ?limit=201 with a 422.
Options
| Option | Type | Default | Description |
|---|---|---|---|
default_page_limit | Integer | nil | Page size for a request that sends no limit. nil falls back to the application configuration. 0 is a valid value — see Meta-only requests. |
max_page_limit | Integer | nil | Largest limit this resource accepts; above it the request is refused with 422. nil falls back to the application configuration. |
Application configuration
The same two knobs configure every resource at once, in the initializer:
# config/initializers/habarico.rb
Habarico.setup do |config|
config.default_page_limit = 50
config.max_page_limit = 200
end
A value is looked up in three places, the first one that has an opinion winning:
- the resource DSL,
Habarico::Config,eluvia-base— itsset_paginationdefault of20, andEluvia::Base::Config.max_page_limit(1000), which bounds every paginated endpoint of the application.
To lift the ceiling altogether, set Eluvia::Base::Config.max_page_limit = nil — nil means "no
bound" there, while nil in Habarico::Config or in a resource means "not configured here". A
resource declares a number or nothing at all; only the base configuration can remove the bound.
Per-request limits
Both values are also plain controller methods, so a rule that depends on the request — a larger ceiling for an internal client, a smaller page for a heavy report — is an override in the controller:
class OrdersController < ApplicationController
include Habarico::Controller
model Order
def list_pagination_max_limit
current_user.internal? ? 1000 : 100
end
end
list_pagination_max_limit and list_pagination_default_limit are what habarico resolves from
the DSL and from Habarico::Config; overriding either replaces that resolution for this
controller. Overriding pagination_max_limit — the hook eluvia-base offers every controller —
works too, and a max_page_limit declared in the DSL still wins over it.
Rejected requests
A limit that is not a page size is refused with 422 Unprocessable Entity, with the error
attached to the limit field:
{
"errors": [
{
"error": "Unprocessable Entity",
"status": 422,
"message": "Limit 500 exceeds the maximum allowed limit of 200.",
"source": "limit",
"timestamp": "2026-09-18T09:15:44.031Z"
}
]
}
Refused: a limit above max_page_limit, a non-numeric one, and a negative one. Accepted: a
missing or blank limit, which falls back to the default page size.
Until now no ceiling existed at all in the Ruby stack: ?limit=99999999 reached Kaminari, and
?limit=0 crashed the endpoint with ZeroDivisionError. Both are now answered properly — the
first with a 422, the second with a meta-only response — so a client that relied on an unbounded
limit has to page instead.
Meta-only requests
limit=0 is a deliberate value, not an invalid one: the response carries the meta block and no
records, which is how a client asks for the total count alone.
{
"meta": {"total_count": 1934, "limit": 0, "offset": 0},
"objects": []
}
Example
A resource whose records are expensive to serialize keeps its pages small and its ceiling low, while a lookup resource the frontend loads in one go raises both:
class OrdersController < ApplicationController
include Habarico::Controller
model Order
default_page_limit 25
max_page_limit 100
end
class CategoriesController < ApplicationController
include Habarico::Controller
model Category
default_page_limit 200
max_page_limit 500
end
See also
- Configuration — where
Habarico::Configis set - Data Loading —
default_sortingandforce_sorting, the ordering that accompanieslimitandoffset - Pagination — the Python counterpart, option for option