Eu tenho uma página da web com formato de assistente. O botão de envio para a API estará na quarta etapa do assistente. No entanto, quero que os dados inseridos sejam armazenados no banco de dados antes de passar para a próxima etapa do assistente. Também quero que a API REST esteja funcionando para as páginas com uma única guia.
Por isso, projetei a API para executar um parâmetro de consulta action = draft ou submit. Se a ação for rascunhada, apenas certos campos serão obrigatórios. Se a ação for enviada, todos os campos são obrigatórios. As validações na camada de serviço da API REST serão feitas com base no parâmetro de consulta. Parece que eu tenho que especificar explicitamente as cláusulas if / else na documentação. Essa é uma forma aceitável de design RESTful? Qual seria o melhor design com esses requisitos?
Respostas:
Como você deseja manter as coisas no servidor entre as etapas do assistente, parece perfeitamente aceitável considerar cada etapa como um recurso separado. Algo nesse sentido:
Ao incluir links hipermídia na resposta, você pode informar o cliente sobre o que ele pode fazer após esta etapa - avançar ou voltar para as etapas intermediárias e nada para a etapa final. Você pode ver um exemplo disso na Figura 5 aqui .
fonte
in_progress
ordraft
.Eu precisava fazer algo semelhante há algum tempo, e o seguinte descreve o que terminamos.
Temos duas tabelas, Item e UnfinishedItem. Quando o usuário preenche os dados com o assistente, os dados são armazenados na tabela UnfinishedItem. Em cada etapa do assistente, o servidor valida os dados inseridos durante essa etapa. Quando o usuário termina o assistente, ele cria um formulário oculto / somente leitura em uma página de confirmação que mostra todos os dados a serem enviados. O usuário pode revisar esta página e voltar à etapa relevante para corrigir erros. Quando o usuário estiver satisfeito com suas entradas, o usuário clica em enviar e o assistente envia todos os dados nos campos de formulário oculto / somente leitura para o servidor da API. Quando o servidor da API processa essa solicitação, ele executa novamente todas as validações realizadas durante cada etapa do assistente e executa validações adicionais que não se encaixam nas etapas individuais (por exemplo, validações globais, validações caras).
As vantagens da abordagem de duas tabelas:
no banco de dados, você pode ter restrições mais rígidas na tabela Item do que na tabela UnfinishedItem; você não precisa ter colunas opcionais que serão realmente necessárias quando o assistente for concluído.
As consultas agregadas nos itens concluídos para geração de relatórios são mais fáceis, pois você não precisa se lembrar de excluir os UnfinishedItems. No nosso caso, nunca precisamos fazer consultas agregadas entre Item e UnfinishedItems, portanto, isso não é um problema.
A desvantagem:
Outras possibilidades que considerei e por que não as acompanhamos:
fonte
if
instruções verificando o status de rascunho durante as validações, o que não seria bom. Embora algumas estruturas muito sofisticadas, como o Ruby on Rails, possam simplificar significativamente esse problema se implementadas corretamente.Eu implementei isso de maneira semelhante a uma mistura de soluções @ guillauma31 e @Lie Ryan.
Aqui estão os principais conceitos:
/users/:id_user/profile/step_1
,.../step_2
etc.).../profile/confirm
. Este recurso não precisa receber todos os dados novamente. Apenas marca os dados como corretos e completos.O pessoal do front-end precisa cuidar dos tokens para que o fluxo de entrada e saída do assistente funcione.
A API é sem estado e atômica.
Para fazer com que um "assistente de uma etapa" funcione com essa configuração, é necessário alterar algumas coisas, como remover o fluxo de token ou criar um recurso para retornar tokens com base no tipo de assistente ou até mesmo criar um novo recurso apenas para preencher esse único assistente de etapas (como
PUT /users/:id_user/profile/
).fonte