Email para confirmar, que además cumple REST.
Uno de los retos en los que me embarqué dentro del proyecto, fue cambiarlo todo para que fuera RESTful. Me compliqué un poco al principio mientras veía como desaparecían las operaciones y comenzaban a aparecer los recursos, pero poco a poco uno se va acostumbrando.
Una de las funcionalidades actuales es que el sistema envía un correo electrónico al email del consumidor cuando éste crea una nueva calificación. En el email se le envía al consumidor un URL que debe utilizar para confirmar su calificación.
Si la aplicación es RESTful, no debería violar este principio: "cualquier petición que modifique el estado del sistema, debe ser enviada por POST y nunca por GET". Mmmmmm, delicado porque la URL que se envía para confirmar la calificación es GET y la tarea en sí implica modificar el estado de una calificación de no confirmada a confirmada.
Se me ocurrió la forma de solucionar esto, pero antes busqué un poco para ver que encontraba. Luego de leer la solución que plantea Elliotte Rusty Harold en "REST Mistake #1: Confirming GETs" ; fue grata mi sorpresa al ver que era la misma que se me había ocurrido; de manera que sin darle mas vueltas, procedí a implementarla.
En resumen, se parte la tarea de confirmar una calificación en dos momentos:
1. el consumidor hace una petición GET desde el enlace enviado a su correo electrónico; en respuesta, el sistema le muestra la información de la calificación que desea confirmar.
2. El consumidor lee la información de la calificación que desea confirmar y oprime un botón que hace una petición POST para cambiar el estado de la calificación de no confirmada a confirmada.
La primera petición que es GET, se enruta a la acción "edit" del recurso y la segunda petición que es POST a la acción "update" del recurso. Cumpliendo así, con REST.
Les aclaro que aunque estamos modificando el estado de confirmación de una calificación, el recurso que utilizo para esta tarea no es el recurso "calificacion" en sí, sino un recurso "virtual" que llamé "confirmación". Lo anterior, es porque el recurso "calificación" debe tener las acciones "edit" y "update" para propósitos muy diferentes a cambiar el estado de la confirmación.
Otra cosa importante, es que en esta tarea de confirmación, nunca utilizo el "id" de la calificación; porque un posible robot, podría utilizar este id, para hacerle cosas nefastas a la aplicación.
De manera que siempre utilizo un llave generada aleatoriamente.
Finalmente el código....
1. El controlador del recurso...
class ConfirmacionesController < ApplicationController #POST /confirmaciones/:id # :id = llave de confirmación def update @nueva_calificacion = NuevaCalificacion.find_by_llave_confirmacion(params[:id]) # si NO encuentra una calificación o ya está confirmada, no actualiza nada if @nueva_calificacion.nil? or @nueva_calificacion.confirmado render(:nothing => true, :status => '404') else @nueva_calificacion.update_attributes(:confirmado => true) end end #GET /confirmaciones/:id # :id = llave de confirmación def edit @nueva_calificacion = NuevaCalificacion.find_by_llave_confirmacion(params[:id]) # si NO encuentra una calificación o ya está confirmada, no retorna nada if @nueva_calificacion.nil? or @nueva_calificacion.confirmado render(:nothing => true, :status => '404') end end end
2. La vista de la acción "edit", (el método button_to, no lo saqué a un helper como acostumbro para que sea mas fácil mostrarlo acá). Está en haml ...
Email:
= @nueva_calificacion.email
%br/
Nombre:
= @nueva_calificacion.nombre
%br/
%b Empresa:
= @nueva_calificacion.producto.empresa.nombre
%br/
%b Producto:
= @nueva_calificacion.producto.nombre
%br/
Fecha:
= @nueva_calificacion.fecha_creacion
%br/
Calificacion:
= @nueva_calificacion.valor
%br/
Comentario:
= @nueva_calificacion.comentario.contenido
%hr/
Si, esta es mi calificación y puede ser publicada
%br/
= button_to('Aceptar', confirmacion_url(:id => @nueva_calificacion.llave_confirmacion), :method => :put)
%hr/
3. La vista de la acción de la acción "update". Está en haml ...
%h2 ¡Calificación Confirmada!
%div
= "El producto #{@nueva_calificacion.producto.nombre} de la empresa #{@nueva_calificacion.producto.empresa.nombre} registra desde este momento su calificación."
%br/
4. Esta es la línea de código para enviar el email. Importante ver el uso del helper "edit_confirmacion_url" ...
Notificador.deliver_solicitud_confirmacion(@nueva_calificacion,edit_confirmacion_url(:id=>@nueva_calificacion.llave_confirmacion))
Esto es todo. Saludos y espero sus comentarios.
Luis Lavena dijo
Felipe,
Es interesante saber como otros programadores encaran el concepto de recursos y sus distintas representaciones.
Además es muy grato leerlo en español :-)
Saludos!
Luis.
19 Abril 2007 | 02:34 AM