Ransack (Rails)
Import the driver directly so every other driver tree-shakes away.
import { RANSACK_DRIVER, QubeeStore, QueryBuilder, Paginator } from '@qubeejs/core';
const store = new QubeeStore();const qb = new QueryBuilder(store, RANSACK_DRIVER.createRequestStrategy('query'));const paginator = new Paginator( store, RANSACK_DRIVER.createResponseStrategy(), RANSACK_DRIVER.createResponseOptions({}),);Example query
Section titled “Example query”qb.setResource('articles') .addFilter('status', 'published') .addSort('created_at', SortEnum.DESC) .setLimit(25) .generateUri();Produces:
/articles?q[status_eq]=published&q[s][]=created_at+desc&page=1&limit=25Capabilities
Section titled “Capabilities”| Capability | Supported |
|---|---|
| Filters | ✅ |
| Operators | ✅ |
| Sort | ✅ |
| Select | — |
| Fields | — |
| Includes | — |
| Search | — |
| Embedded | — |
Pagination gems
Section titled “Pagination gems”Ransack filters and sorts; a separate gem paginates, and its headers carry the totals. Both common ones are read without configuration:
| Pagy | Kaminari + api-pagination | |
|---|---|---|
| Page-size param | limit (the default) |
per_page |
| Headers read | total-count, total-pages, current-page, page-limit, link |
total, per-page, link |
| Last page | total-pages |
the rel="last" link, else total ÷ page size |
Kaminari reads the page size from per_page, so rename the parameter once:
const { builder, paginator } = createQubee({ driver: RANSACK_DRIVER, request: { limit: 'per_page' },});Pagy ignores a client-supplied limit unless the server sets its client_limit option. Kaminari on
its own sends no headers at all; pair it with the api-pagination gem. A header renamed on the
server is renamed here through response: { total: 'x-total' } reads x-total first.
Attribute names
Section titled “Attribute names”Conditions and sorts name the model’s own attributes, in snake_case: created_at, not
createdAt. Ransack 4 and later search only what the model allowlists in
ransackable_attributes (and ransackable_associations, for a condition such as
author_name_cont); a condition or sort on any other attribute is ignored.
Searching across columns
Section titled “Searching across columns”Ransack has no global search parameter; a combinator attribute name searches several columns in one condition:
builder.addFilterOperator('title_or_body', FilterOperatorEnum.ILIKE, 'rails');// q[title_or_body_i_cont]=railsILIKE maps to _i_cont. CONTAINS maps to _cont, which Ransack 6.0 made case-sensitive on
PostgreSQL.
Reading a response
Section titled “Reading a response”The totals travel in the response headers, so pass them as the second argument:
const response = await fetch(`https://example.com/api${uri}`);const page = paginator.paginate(await response.json(), response.headers);
page.data; // rowspage.total; // total rows the backend reportedpage.lastPage; // final page number