Reputation: 41
How would one go about allowing a user to reorder resources manually using a RESTful api?
I'm using mysql with an 'sequence' column that can be updated manually. The resources returned from a GET request will be sorted by that column ASC. Is it a good idea to have the front end responsible for determining what each 'sequence' value is and then sending multiple PUT requests to update each resource, or is there a way to provide a single endpoint specifically to reorder resources in one request?
This is the current setup for the part of my express app that needs to allow reordering.
apiRouter.route('/products/:product')
.get(getProduct)
.put(updateProduct)
.delete(removeProduct)
apiRouter.route('/products')
.get(getProducts)
.post(addProduct)
And this is my mysql query for getting products:
SELECT
id, name, width, depth, productId, category
FROM products
WHERE user = :user
ORDER BY sequence ASC
I'm thinking about adding another route like
apiRouter.put('/products/reorder', reorderProducts)
But I'm not sure what the payload should be or what the response should be.
Upvotes: 1
Views: 742
Reputation: 1338
A valid restful approeach would be to update the whole collection:
PUT /products
[
{...}, {...}
]
But here you need to send all products data in the payload. If you have a big collection its probably nothing you'd like to do.
Personally I'd patch the whole collection instead:
PATCH /products
[
{"id": 1, "sequence": 1},
{"id": 4, "sequence": 2},
{"id": 3, "sequence": 3},
{"id": 2, "sequence": 4}
]
But you'd need to handle errors for each resource you are about to update and respond with 207 Multi-Status, but well this is not very restful afaik.
Patching each resource would do the trick in a restful way, but you'd need to perform all the requests to your API, what you most likely dont want to do, when you have a huge set of products.
Upvotes: 0
Reputation: 41
I've decided to use just return a 200 status code for now. The request only includes a number array called 'ids' which is looped through and the index set as the 'sequence' column value:
export const reorderProducts: RequestHandler = async (req, res) => {
await products.reorderProducts(req.user.id, req.body.ids)
res.sendStatus(200)
}
// in model function 'reorderProducts'
for (let index = 0; index < ids.length; index++) {
await query(`
UPDATE products
SET sequence = :index
WHERE
user = :user
AND id = :id
`, {
user,
index,
id: ids[index],
})
}
Upvotes: 0