Add register/cancel to event API
One-sentence description
Add register/cancel to event API
Discussion
Het zou prachtig zijn als je je via de ThaliApp zou kunnen aanmelden voor evenementen. Nu is dit niet alleen een geavanceerde functionaliteit, maar ook een moeilijke omdat er veel business logic voor nodig is.
Op dit moment hebben we een simpele REST API waarmee gegevens over evenementen en registraties kunnen worden opgehaald. Dit werkt erg goed, maar geeft nog geen fancy mogelijkheden.
Maar we hebben twee discussies die we wat mij betreft even moeten tackelen zodat goed is nagedacht over de implementatie. De twee problemen staan hieronder en ik ben benieuwd hoe jullie hierover denken.
Probleem 1: DRY
Stel we willen de mogelijkheid tot aanmelden toevoegen aan de API dan zal de events app een refactor moeten ondergaan, aangezien we anders de business logic op twéé plekken moeten doen: views.py
en api/viewsets.py
. Nu weet ik niet wat de beste manier is om dit te doen, maar het beste lijkt me om een services.py
toe te voegen die de business logic uitvoert. Ongeveer zoals hier beschreven wordt. Die services.py
doet dan alle business logic die dan weer gebruikt kan worden in de views. Voordeel is dat zo’n services.py
apart getest kan worden en we geen code gaan herhalen. Maar het kan natuurlijk zijn dat er betere manieren zijn om dit te doen, dus ideeën zijn welkom.
Probleem 2: REST
Aangezien we Django REST Framework gebruiken zou het natuurlijk mooi zijn als we een superduper fancy RESTful API zouden neerzetten. Basic REST is makkelijk: dingen ophalen met GET, dingen aanmaken met POST, dingen aanpassen met PUT/PATCH en dingen verwijderen met DELETE.
Een simpele API zou je dus eigenlijk zo kunnen doen:
POST /events/1/registrations met een optionele body die de fields bevat -> Aanmelden voor event
PUT /registrations/<id>/ met required body die de fields bevat -> Aanpassing registratie
DELETE /registrations/<id>/ -> Registratie verwijderen = Afmelden voor event
Maar dat wil je eigenlijk niet. DELETE zou namelijk niet echt iets verwijderen, dat past enkel de cancellation date van de registratie aan. En dan kun je die niet meer gebruiken als je daadwerkelijk dingen wilt verwijderen (zoals in-app event management oid). Dus laten we deze optie vooral niet gebruiken.
Een tweede, betere optie ([info over PATCH] (http://restcookbook.com/HTTP%20Methods/patch/)):
POST /events/1/registrations met een optionele body die de fields bevat -> Aanmelden voor event
GET /registrations/<id>/fields -> Verkrijg velde en huidige waardes (initial state zou dus velden met default values zijn)
PUT /registrations/<id>/fields met required body die de fields bevat -> Aanpassing registratie
PATCH /registrations/<id>/ met {“is_cancelled”: true} body -> Afmelden voor event
PATCH /registrations/<id>/ met {“is_cancelled”: false} body -> Weer aanmelden voor event na afmelding
Nadeel hiervan is dat het eigenlijk wel veel werk is in de app: Stel je meld je aan dan moet POST worden gedaan, bij een cancel gaat het met PATCH. Maar als je je dan weer wilt aanmelden dan is dat geen POST maar een PATCH.
En dan hebben we nog een derde optie die minder REST is (want: verbs are bad):
POST /events/1/registrations/register met een optionele body die de fields bevat -> Aanmelden voor event
POST /events/1/registrations/update met een optionele body die de fields bevat -> Aanpassing registratie
POST /events/1/registrations/cancel zonder body -> Afmelden voor event
Dit is niet echt REST, maar wel het makkelijkst te maken aangezien onze huidige structuur voor de normale view eigenlijk ongeveer hetzelfde in elkaar zit.
Er zijn nog wel meer opties te bedenken, dus als er iets beters is dan zijn ook hiervoor ideeën welkom. Ik heb persoonlijk een voorkeur voor optie 2.