Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document REST API filtering with Ransack #4128

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 3 additions & 3 deletions api/openapi/main.hub.yml
Expand Up @@ -38,11 +38,11 @@ pages:
path: /authentication
data:
$ref: ./authentication.md
- title: Pagination
- title: Pagination and Filtering
route:
path: /pagination
path: /pagination-and-filtering
data:
$ref: ./pagination.md
$ref: ./pagination-and-filtering.md
- title: Errors
route:
path: /errors
Expand Down
23 changes: 23 additions & 0 deletions api/openapi/pagination-and-filtering.md
@@ -0,0 +1,23 @@
# Pagination and Filtering

## Pagination

Most endpoints that return a collection are paginated. A paginated response contains metadata about the current page at the root level and the resources in the current page in a child key named after the resource (e.g. `orders`).

You can pass the `page` and `per_page` parameters to set the current page and the desired number of items per page. Note that the default and the maximum number of items per page is decided at the application level.

All pagination metadata is documented in the individual API endpoints, so take a look there if you're unsure what data you can expect.

## Filtering

Most endpoints that return a collection also have the ability to filter data using query params. This works taking advantage of the search filters provided by [Ransack](https://github.com/activerecord-hackery/ransack/).

For example, if we want to retrieve only products that contain the word "Watch" in their title we can make the following request:

```
GET /products?q[name_cont]=Watch
```

The `name_cont` matcher will generate a query using `LIKE` to retrieve all the products that contain the value specified. For an extensive list of search matchers supported, please refer to the Ransack documentation.

The result will be paginated as described in the paragraph above.
7 changes: 0 additions & 7 deletions api/openapi/pagination.md

This file was deleted.

32 changes: 32 additions & 0 deletions api/openapi/solidus-api.oas.yml
Expand Up @@ -38,6 +38,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -117,6 +118,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
'/orders/{number}':
Expand Down Expand Up @@ -257,6 +259,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
'/countries/{id}':
get:
responses:
Expand Down Expand Up @@ -516,6 +519,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -837,6 +841,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -1203,6 +1208,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
'/users/{id}':
Expand Down Expand Up @@ -1398,6 +1404,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -1520,6 +1527,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -1682,6 +1690,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -1898,6 +1907,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -2053,6 +2063,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
- order-token: []
Expand Down Expand Up @@ -2213,6 +2224,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -2803,6 +2815,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -2964,6 +2977,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -3153,6 +3167,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -3303,6 +3318,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -3454,6 +3470,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -3671,6 +3688,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -3822,6 +3840,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -3985,6 +4004,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
/users:
Expand Down Expand Up @@ -4012,6 +4032,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -4071,6 +4092,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
post:
Expand Down Expand Up @@ -5666,12 +5688,15 @@ paths:
name: id
schema:
type: integer
description: The id of the Taxon
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
- in: query
name: simple
schema:
type: boolean
description: Returns a simplified version of the JSON
security:
- api-key: []
'/orders/{order_number}/customer_returns':
Expand Down Expand Up @@ -5702,6 +5727,7 @@ paths:
parameters:
- $ref: '#/components/parameters/page'
- $ref: '#/components/parameters/per_page'
- $ref: '#/components/parameters/q'
security:
- api-key: []
parameters:
Expand Down Expand Up @@ -5794,6 +5820,12 @@ components:
schema:
type: integer
default: 25
q:
name: q
in: query
schema:
example: '?q[attribute_eq]=value'
description: 'Allows to query results based on search filters provided by Ransack (https://github.com/activerecord-hackery/ransack/).'
responses:
not-found:
description: ''
Expand Down
35 changes: 29 additions & 6 deletions api/spec/requests/spree/api/credit_cards_controller_spec.rb
Expand Up @@ -13,7 +13,7 @@ module Spree
create(:user, :with_api_key)
end

let!(:card) { create(:credit_card, user_id: admin_user.id, gateway_customer_profile_id: "random") }
let!(:admin_user_card) { create(:credit_card, user_id: admin_user.id, gateway_customer_profile_id: "admin-user-random") }

before do
stub_authentication!
Expand All @@ -37,13 +37,15 @@ module Spree
end

it "can view all credit cards for user" do
get spree.api_user_credit_cards_path(current_api_user.id)
normal_user_card = create(:credit_card, user_id: normal_user.id, gateway_customer_profile_id: "normal-user-random")

get spree.api_user_credit_cards_path(normal_user.id)

expect(response.status).to eq(200)
expect(json_response["pages"]).to eq(1)
expect(json_response["current_page"]).to eq(1)
expect(json_response["credit_cards"].length).to eq(1)
expect(json_response["credit_cards"].first["id"]).to eq(card.id)
expect(json_response["credit_cards"].first["id"]).to eq(normal_user_card.id)
end
end

Expand All @@ -52,9 +54,9 @@ module Spree
normal_user
end

let!(:card) { create(:credit_card, user_id: normal_user.id, gateway_customer_profile_id: "random") }
let!(:normal_user_card) { create(:credit_card, user_id: normal_user.id, gateway_customer_profile_id: "normal-user-random") }

it "can not view user" do
it "can not view admin user cards" do
get spree.api_user_credit_cards_path(admin_user.id)

expect(response.status).to eq(404)
Expand All @@ -67,7 +69,28 @@ module Spree
expect(json_response["pages"]).to eq(1)
expect(json_response["current_page"]).to eq(1)
expect(json_response["credit_cards"].length).to eq(1)
expect(json_response["credit_cards"].first["id"]).to eq(card.id)
expect(json_response["credit_cards"].first["id"]).to eq(normal_user_card.id)
end

context "when user has multiple credit cards" do
let!(:another_normal_user_card) do
create(:credit_card, user_id: normal_user.id, gateway_customer_profile_id: "another-normal-user-random")
end

it 'can control the page size through a parameter' do
get spree.api_user_credit_cards_path(current_api_user.id), params: { per_page: 1 }
expect(json_response['count']).to eq(1)
expect(json_response['current_page']).to eq(1)
expect(json_response['pages']).to eq(2)
end

it "can query the results through a parameter" do
get spree.api_user_credit_cards_path(current_api_user.id), params: { q: { id_eq: normal_user_card.id } }
expect(json_response["credit_cards"].count).to eq(1)
expect(json_response["count"]).to eq(1)
expect(json_response["current_page"]).to eq(1)
expect(json_response["pages"]).to eq(1)
end
end
end
end
Expand Down
8 changes: 8 additions & 0 deletions api/spec/requests/spree/api/payments_controller_spec.rb
Expand Up @@ -132,6 +132,14 @@ module Spree
expect(json_response['current_page']).to eq(1)
expect(json_response['pages']).to eq(2)
end

it "can query the results through a parameter" do
get spree.api_order_payments_path(order), params: { q: { id_eq: @payment.id } }
expect(json_response["payments"].count).to eq(1)
expect(json_response["count"]).to eq(1)
expect(json_response["current_page"]).to eq(1)
expect(json_response["pages"]).to eq(1)
end
end

context "for a given payment" do
Expand Down