Actualizar el estado de una tarea directamente desde la interfaz gráfica, sin recargar la página, es una funcionalidad esencial en cualquier sistema de gestión de información. Aquí se conecta todo lo trabajado previamente —la máquina de estados, las rutas, el controlador y las pruebas— para lograr una experiencia fluida utilizando Ajax y SJR (Server-generated JavaScript Responses) en una aplicación Rails.
¿Cómo preparar la vista show para mostrar el estado de una tarea?
Antes de cualquier cambio visual, es necesario reiniciar el servidor [0:28] para que los cambios recientes sean tomados correctamente. Esto se hace con Ctrl + C para pausar y luego ejecutando rails server de nuevo.
Una vez en el navegador, la vista show de una tarea no muestra el estado actual. Para solucionarlo, se agregan nuevas columnas en la tabla de la vista show.html.erb:
- Una columna con el encabezado Estado.
- Una celda que muestre
task.status con una clase CSS llamada task-status, que servirá más adelante para localizar el elemento y actualizarlo dinámicamente.
- Un espacio adicional para colocar un dropdown con los eventos disponibles.
El dropdown se reutiliza del que ya existía en la vista index de tareas [2:25], aprovechando los componentes de Bootstrap como framework CSS.
¿Cómo obtener los eventos disponibles para una tarea con un helper?
No todos los eventos son válidos en todo momento. Por ejemplo, no se puede invocar el evento finish si la tarea está en estado pending; primero debe pasar a in_process. La máquina de estados controla estas reglas mediante lo que se conoce como permitted transitions [3:52], que define desde qué estado se puede transicionar a cuál otro.
Para exponer esta lógica en la vista, se crea un método en el TaskHelper llamado available_events_for [3:20]:
ruby
def available_events_for(task)
task.status_state_machine.permitted_transitions.map { |t| t.event }
end
Este método recibe una tarea, accede a su máquina de estados y con permitted_transitions obtiene todas las transiciones válidas. Luego, con .map, extrae únicamente la key del evento asociado. Así, la vista solo muestra los eventos que realmente se pueden ejecutar según el estado actual.
¿Cómo iterar los eventos en el dropdown?
En la vista show, se itera con each sobre la colección que devuelve el helper [4:47]:
erb
<% available_events_for(@task).each do |event| %>
<li><%= link_to event, trigger_task_path(@task, event: event, format: :js), remote: true, method: :patch %></li>
<% end %>
Cada elemento del dropdown se genera dinámicamente con el nombre del evento. El link_to apunta a la ruta trigger_task_path y recibe:
- La referencia a la tarea.
- El evento que se quiere disparar.
- El formato
:js para activar SJR.
- La opción
remote: true para que la petición use Ajax en lugar de una recarga completa.
- El método
patch, porque link_to usa get por defecto y la acción del controlador espera patch [6:08].
¿Cómo actualizar el estado en la interfaz sin recargar la página?
Se crea una vista especial trigger.js.erb [6:40] dentro de la carpeta de vistas de tareas. Este archivo contiene JavaScript puro que el servidor renderiza y el cliente ejecuta automáticamente:
javascript
document.querySelector('.task-status').innerHTML = '<%= @task.status %>';
Con document.querySelector se localiza el elemento HTML que tiene la clase .task-status [7:08]. Mediante innerHTML se reemplaza el contenido con el nuevo valor del estado, obtenido desde la variable de instancia @task disponible en el controlador.
¿Cómo corregir las pruebas tras el cambio de formato?
Al ejecutar rspec [8:18], la prueba asociada a la acción trigger falla porque espera una respuesta en HTML, pero ahora el controlador responde en JavaScript. La solución es agregar format: :js en la prueba correspondiente [8:40], exactamente como se hizo en el link_to de la vista.
Tras este ajuste, todas las pruebas pasan correctamente.
¿Por qué es importante este patrón en sistemas de información?
El uso de una máquina de estados permite controlar el ciclo de vida de los registros y auditar cada transición. Combinado con SJR y Ajax, se logra una interfaz reactiva que refleja cambios sin interrumpir la experiencia del usuario. Este patrón es fundamental al modelar proyectos donde los registros atraviesan distintas fases —como tareas, órdenes o tickets— y cada transición debe respetar reglas de negocio definidas.
¿Te animas a llevar este mismo estado a la página de index para que cada tarea de la lista también muestre su estado actual? Comparte tu solución en los comentarios.