Tengo una página web con formato de asistente. El botón de envío a la API estará en el cuarto paso del asistente. Sin embargo, quiero que los datos ingresados se almacenen en la base de datos antes de pasar al siguiente paso en el asistente. También quiero que la API REST funcione para las páginas que tienen una sola pestaña.
Así que diseñé la API para tomar una acción de parámetro de consulta = borrador o enviar. Si la acción es borrador, solo ciertos campos son obligatorios. Si se envía una acción, todos los campos son obligatorios. Las validaciones en la capa de servicio de REST API se realizarán en función del parámetro de consulta. Parece que tengo que especificar explícitamente las cláusulas if / else en la documentación. ¿Es esta una forma aceptable de diseño RESTful? ¿Cuál sería el mejor diseño con estos requisitos?
Respuestas:
Dado que desea conservar las cosas en el servidor entre los pasos del asistente, parece perfectamente aceptable considerar cada paso como un recurso separado. Algo en este sentido:
Al incluir enlaces hipermedia en la respuesta, puede informar al cliente sobre lo que puede hacer después de este paso: avanzar o retroceder para los pasos intermedios, y nada para el paso final. Puede ver un ejemplo de esto en la Figura 5 aquí .
fuente
in_progress
odraft
.Había necesitado hacer algo similar hace algún tiempo, y lo siguiente describe con qué terminamos.
Tenemos dos tablas, Item y UnfinishedItem. Cuando el usuario completa los datos con el asistente, los datos se almacenan en la tabla UnfinishedItem. En cada paso del asistente, el servidor valida los datos ingresados durante ese paso. Cuando el usuario termina con el asistente, el asistente presenta un formulario oculto / de solo lectura en una página de confirmación que muestra todos los datos que se deben enviar. El usuario puede revisar esta página y volver al paso correspondiente para corregir errores. Una vez que el usuario está satisfecho con sus entradas, el usuario hace clic en enviar y el asistente luego envía todos los datos en los campos de formulario ocultos / de solo lectura al servidor API. Cuando el servidor API procesa esta solicitud, vuelve a ejecutar todas las validaciones que realizó durante cada paso del asistente y realiza validaciones adicionales que no se ajustan a los pasos individuales (por ejemplo, validaciones globales, validaciones costosas).
Las ventajas del enfoque de dos tablas:
en la base de datos, puede tener restricciones más estrictas en la tabla Elemento que en la tabla UnfinishedItem; no tiene que tener columnas opcionales que realmente serán necesarias cuando el asistente haya finalizado.
Las consultas agregadas en los elementos terminados para generar informes son más fáciles, ya que no tiene que acordarse de excluir los UnfinishedItems. En nuestro caso, nunca tuvimos que hacer consultas agregadas entre Item y UnfinishedItems, por lo que esto no es un problema.
La desventaja:
Otras posibilidades que he considerado y por qué no fuimos con ellas:
fuente
if
declaraciones que verifiquen el estado del borrador a lo largo de sus validaciones, lo que simplemente no sería bueno. Aunque algunos marcos muy sofisticados como Ruby on Rails podrían simplificar significativamente ese problema si se implementan correctamente.He implementado esto de manera similar a una combinación de las soluciones @ guillauma31 y @Lie Ryan.
Aquí están los conceptos clave:
/users/:id_user/profile/step_1
,.../step_2
, etc.).../profile/confirm
. Este recurso no necesita recibir todos los datos nuevamente. Solo marca los datos como correctos y completos.Los chicos de front-end deben cuidar las fichas para que funcione el flujo de ida y vuelta del asistente.
La API no tiene estado y es atómica.
Para hacer que un "asistente de un paso" funcione con esta configuración, tendría que cambiar algunas cosas, como eliminar el flujo de tokens o crear un recurso para devolver tokens en función del tipo de asistente o incluso crear un nuevo recurso solo para llenar este single específico asistente de pasos (como
PUT /users/:id_user/profile/
).fuente