Ruby on Rails, parte 15: Validaciones

En nuestro posteo anterior Ruby on Rails, parte 14: CRUD y REST habíamos visto como insertar, modificar, eliminar y mostrar registros en RoR gracias a los modelos. Continuando con ese proyecto, organizador, hoy vamos a ver cómo validar los datos antes de insertar o modificar registros.

En primer lugar, en otras publicaciones sobre Ruby On Rails a la hora de crear formularios habíamos utilizado las validaciones de Html5, sin embargo acá surge un primer problema, y es que no todos los navegadores (aunque sí las últimas versiones) soportan estas validaciones. Otra solución sería validar formularios con Jquery, pero con esto surge un segundo problema.

Validar formularios con Javascript, independientemente si es con Html5, Jquery o cualquier otra forma está bien, evitamos de esa manera el envío de información inútil al servidor. Sin embargo todo lo que está en Javascript está en el navegador, en la máquina del usuario, por tanto las validaciones pueden fallar, o porque el usuario tiene el navegador con Javascript deshabilitado o porque es un usuario malintencionado que con conocimientos medios puede burlar las validaciones del navegador. Por esto nosotros también necesitamos la necesidad de tener una segunda validación, en el servidor, y de esta manera evitar por ejemplo que se guarden campos obligatorios vacíos.

Siguiendo con el nuestra pequeña aplicación que comenzamos en el último posteo vamos a ir a nuestra carpeta app -> models -> tarea.rb y editamos este archivo. Por empezar tanto los campos :titulo, :descripcion y :prioridad deben ser obligatorios. Así que vamos a agregar las siguientes líneas dentro de la clase:

validates :titulo, :presence => true
validates :descripcion, :presence => true
validates :prioridad, :presence => true

Con esto basta. Ahora para que aparezcan los mensajes de error debemos ir a nuestro formulario. El que creamos la última vez, el que estaba dentro de app -> views -> tareas llamado _formulario_guardar_tareas.html.erb y agregar lo siguiente en la parte dónde quieras que se visualicen los mensajes de error (si es que hay):

<% if @tarea.errors.any? %>
   <ul>
      <% @tarea.errors.each do |atributo, mensaje| %>
      <li> <%= mensaje %> </li>
      <% end %>
   </ul>
<% end %>

La primer línea:

<% if @tarea.errors.any? %>

Preguntará si hay errores, de haberlos generará un código html con una lista desordenada (etiqueta ul) Y dentro recorreremos los errores con un each.

<% @tarea.errors.each do |atributo, mensaje| %>
      <li> <%= mensaje %> </li>
<% end %>

Mostrando por pantalla cada error con un item (etiqueta li)

Ahora, bien, si intentaste hacerlo seguramente habrás notado que los errores vienen en inglés. Para personalizar los mensajes de error vamos de nuevo a nuestro modelo tarea.rb y modificamos:

validates :titulo, :presence => true
validates :descripcion, :presence => true
validates :prioridad, :presence => true

Por esto:

validates :titulo, :presence => {:message => "Usted debe ingresar un título"}
validates :descripcion, :presence => {:message => "Usted debe ingresar una descripción"}
validates :prioridad, :presence => {:message => "Usted debe ingresar una prioridad"}

Bien, ahora sólo faltan un par de cosas. Hasta ahora hemos puesto sólo la regla de campos completos, sin embargo nosotros podemos agregar más reglas. Por ejemplo, que el título y la descripción tengan un mínimo y máximo de caracteres.

Para ello debemos agregar algo cómo esto:

length: {minimum: 2, maximum: 50, :message => "Mensaje"}

En este caso ponemos una regla del mínimo y máximo que deben tener la validación y el mensaje de error.

Así que vamos a modificar nuevamente nuestras validaciones:

#Validaciones de título
validates :titulo, :presence => {:message => "Usted debe ingresar un título"}, length: {minimum: 2, maximum: 50, :message => "El título debe tener entre 2 y 50 caracteres"}
#Validaciones de descripción
validates :descripcion, :presence => {:message => "Usted debe ingresar una descripción"}, length: {minimum: 2, maximum: 4000, :message => "La descripción debe tener entre 2 y 4000 caracteres"}
#Validaciones de prioridad
validates :prioridad, :presence => {:message => "Usted debe ingresar una prioridad"}

En este caso el mínimo y máximo del título y la descripción debe ser mínimo de 2 y máximo de 50 para el título y mínimo de 2 y máximo de 4000 para la descripción.

Ahora vamos a agregar una nueva validación: la prioridad, ésta debe ser numérica, así que deberíamos agregar algo cómo esto:

:numericality => {:only_integer => true, :message => "Mensaje"}

En este último caso agregamos una validación numérica que sólo admitirá enteros (números sin coma :)) y un mensaje de error si no se cumple la condición.

Así que nuestra validación quedará así:

#Validaciones de título
validates :titulo, :presence => {:message => "Usted debe ingresar un título"}, length: {minimum: 2, maximum: 50, :message => "El título debe tener entre 2 y 50 caracteres"}
#Validaciones de descripción
validates :descripcion, :presence => {:message => "Usted debe ingresar una descripción"}, length: {minimum: 2, maximum: 4000, :message => "La descripción debe tener entre 2 y 4000 caracteres"}
#Validaciones de prioridad
validates :prioridad, :presence => {:message => "Usted debe ingresar una prioridad"}, :numericality => {:only_integer => true, :message => "La prioridad debe ser numérica"}

Bien, con esto ya tenemos nuestras validaciones. Algo que lleva mucho tiempo pero que siempre es necesario como las validaciones en RoR es una tarea rápida y sencilla.

Saludos!

Anterior: Ruby on Rails, parte 14: CRUD y REST

Siguiente: Ruby on Rails, parte 16: Relaciones en los modelos

Redes sociables