Eduardo Martin Rico Sotomayor
Esteban Ramos Fernández
Marina Iglesia
¿Por qué es importante validar los datos en los modelos?
Validar los datos en los modelos es crucial para garantizar la integridad y consistencia de la información que manejamos en nuestras aplicaciones. De esta manera, evitamos que se persistan datos incorrectos o incompletos en nuestra base de datos, lo cual podría causar errores a futuro. Específicamente, en el contexto de frameworks como Ruby on Rails, estas validaciones se hacen directamente en el nivel del modelo, asegurando también un mejor manejo de excepciones y errores para los usuarios.
¿Cómo implementar validaciones de presencia?
La validación de presencia es una de las más básicas y necesarias. En nuestro modelo Category estaremos asegurándonos de que los atributos name y description estén presentes antes de que cualquier registro sea guardado. Esto se logra con la siguiente línea de código:
validates :name, :description, presence: true
Al establecer esta validación, cualquier intento de crear un registro con esos campos vacíos resultará en un error, evitando que tal registro se almacene.
¿Cómo protegerse de la duplicación de datos?
Para evitar que dos categorías tengan el mismo nombre, es necesario integrar una validación de unicidad. Esto asegura que los datos únicos permanezcan únicos en la base de datos, una práctica esencial para mantener datos limpios y gestionar correctamente los registros. La sintaxis básica para implementar esta validación es:
validates :name, uniqueness: true
Además, al configurarlo con case_sensitive, se controla si las diferencias de mayúsculas deben considerarse o no. Se puede desactivar así:
validates :name, uniqueness: { case_sensitive: false }
¿Cómo realizar validaciones personalizadas?
Las validaciones personalizadas son necesarias cuando se deben cumplir condiciones específicas que no están incluidas en las validaciones estándar. En el modelo Task, donde el atributo due_date no puede ser una fecha en el pasado, se implementa un método de validación personalizada así:
validate :due_date_validity def due_date_validity return if due_date.blank? || due_date > Date.today errors.add(:due_date, I18n.t('task.errors.invalid_due_date')) end
Esta metodología permite que si el due_date está en blanco o en una fecha futura, no se genere ningún error. De lo contrario, se añade un error usando un mensaje traducido para una mejor experiencia de usuario.
¿Qué implicaciones tienen las asociaciones y llaves foráneas en las validaciones?
Las relaciones y llaves foráneas deben estar correctamente establecidas para garantizar la integridad referencial. Por ejemplo, cuando una tarea pertenece a una categoría, es esencial asegurarse de que la tarea no pueda crearse sin una categoría existente. Esto se hace automáticamente cuando las asociaciones están correctamente configuradas en los modelos.
Consejos prácticos
En resumen, las validaciones de los modelos no solo mejoran la confianza y calidad de tus datos, sino que también contribuyen significativamente a la experiencia del usuario, mostrando mensajes claros y evitando frustraciones innecesarias. La correcta implementación de estas técnicas te permitirá desarrollar aplicaciones robustas y altamente confiables. Esto es solo el comienzo, ¡sigue explorando y aprendiendo sobre autenticación y gestión de usuarios en las próximas clases!
Eduardo Martin Rico Sotomayor
Esteban Ramos Fernández
Marina Iglesia
Daniel J. Pérez
Fredy Arce
Deimer Yepes Miranda
Company_adminJuan Zenón
Esteban Ramos Fernández
Eduardo Rafael Romero Bernal
Eduardo Martin Rico Sotomayor
Johan Tique
ProfesorEduardo Martin Rico Sotomayor
Gustavo Alonso Peñaranda Cabrera
Alexis Luna
kenedy carlos de la torre mendoza
David Campos
Julio A
Luis Manuel Juárez Flores
Jorge Chirinos
Fabio Vaccaro
Agustina Corvo
josue rodrigo fierro morfin
Manuel Alejandro González Cabello
Esteban Ramos Fernández
Walter De Jesús Medina Puy
Roger Carlos Ariel Alba
Walter De Jesús Medina Puy
A mi me funcionó
uniqueness: { case_sensitive: false }
Si me funcionó también perfect
Me funcionó perfecto! El único detalle es que no toma en cuenta los acentos.
En la versión 7 de Rails, al crear el scaffold no funciona el botón Destroy, creo que es por la implementación de turbo-rails, así que para hacer que funcione el botón Destroy debemos de cambiar el código de los botones, de esto:
%td= link_to 'Destroy', category, method => :delete, :data => { :confirm => 'Are you sure?' }
a esto:
%td= link_to 'Destroy', category, :data => { turbo_method: :delete, :confirm => 'Are you sure?' }
y lo mismo con el botón Destroy de Tasks
No me funciona simplemente me muestra los datos y np borra nada
En Erb se que me fuciona este codigo para borrar con un link en rails 7 por la implementación de turbo y stimulus:
<%= link_to t('common.destroy'), category_path(@category), data: { turbo_method: :delete, turbo_confirm: '¿Estás seguro de que quieres eliminar esta categoría?' }, class: "mt-2 rounded-lg py-3 px-5 bg-gray-100 font-medium" %>
omite, las class porque estoy usando tailwind en vez de bootstrap(otro framework para css), ahora creo que para el caso del link del index sería sin el @ de @category... tendrías que convertir el codigo de erb a HAML
Para quien le interese saber más del tema de validaciones, les dejo este excelente artículo de las guías oficiales de Ruby on Rails. Y si necesitan documentos de referencia, les dejo el siguiente link: https://api.rubyonrails.org/classes/ActiveRecord/Validations/ClassMethods.html
Perfect, me sirvió mucho la lectura
Pregunta: ¿Podría agregar las validaciónes en el método del controlador en lugar de en el modelo?
En la parte de crear task no me aparece el select option para seleccionar la categoría y si le pongo una que sí existe me da error, a alguien más le ha pasado esto?
Hola Eduardo, podrías por favor colocar la salida del error, debemos verificar inicialmente varias cosas:
task_params y dentro del sistema de strong parameters este definido el simbolo :category_idassociation como método.Hola Johan, primero que nada, qué gran profesor eres.
El error dice asi:
1 error prohibited this task from being saved: Category debe existir
Chequé todo lo que me dijiste y en efecto, en el método task_params no esta relacionado a ninguna categoría:
def create @task = Task.new(task_params) respond_to do |format| if @task.save format.html { redirect_to @task, notice: 'Task was successfully created.' } format.json { render :show, status: :created, location: @task } else format.html { render :new } format.json { render json: @task.errors, status: :unprocessable_entity } end end end
Qué debería hacer?
Para quienes no les funcione al hacer click en destroy (redirecciona al registro), pueden intentar lo siquiente:
Dentro de la vista de category, en index:
%td= link_to 'Destroy', category, :data => { :turbo_method => :delete, :turbo_confirm => 'Are you sure?' }
Y aplicando la siguiente configuración en el archivo application.html.erb dentro de la etiqueta **head **
RUTA: /app/views/layouts/application.html.erb
<%= javascript_include_tag "turbo", type: "module" %>
En el punto de case_insensitive la validación se cumple, pero esto sucede porque no borro el registro que tenía por nombre Test, por lo tanto cuando hace la validación lo hace entre Test y Test, y no entre test y Test.
Hola tengo la duda de como se generaría la traducción para las validaciones ?
Para evitar la creación de registros en blanco, o para agregar validaciones que se requieran para cumplir las reglas del negocio se pueden agregar validaciones a los campos para que lancen un error sí estas no se cumplen.
Validaciones
Las validaciones se agregan en el model que será validado, empezando con la palabra validates seguido de los atributos que se quiere validar. Seguido de esto se pueden usar helpers que Rails provee para validar diferentes cosas. Por ejemplo, el helper presence para validar que el campo no esté vacío.
class Category < ApplicationRecord has_many :tasks validates :name, :description, presence: true validates :name, uniqueness: { case_insensitive: false } end
Existen otros helpers para validar diferentes aspectos y diferentes elementos HTML. Documentación:
Validación personalizada
Para validar un atributo de forma personalizada se usa la palabra validate, seguido del nombre de la función que validará el campo. La función debe ser declarada dentro de la clase.
validate :due_date_validity def due_date_validity return if due_date.blank? return if due_date > Date.today errors.add(:due_date, I18n.t('task.errors.invalid_due_date')) end
En este caso se valida que la fecha de vencimiento no esté vacía y además que la fecha no sea anterior al día actual, si no se cumplen las validaciones se agrega un error con el método errors.add.
En caso de que no quieran utlizar la internalización pueden declarar su error asi:
def due_date_validity return if due_date.blank? return if due_date > Date.today errors.add(:due_date, "Date can't be in the past") end
Cuál es la diferencia de colocar uniqueness de la siguiente manera.....
:uniqueness => true
@JohanTique
Excelente, estoy muy contento con este curso, muy buenas explicaciones.
No me funcionó el uniqueness class Category < ApplicationRecord has_many :tasks
validates :name, :description, presence: true #this 2 inputs may exist validates :name, uniqueness: { case_insensitive: false } end
En vez de:
validates :name, uniqueness: { case_insensitive: false }
Prueba con:
validates :name, uniqueness: { case_sensitive: false }
como podria poner un trim() ?
Hola josue. Podrìas usar un el método strip en ruby que quita los espacios en blanco en el principio y en el final. Para agregarlo puedes usar un before_validation. Los before_validation se corren antes de ir a las validaciones como su nombre lo indica. Entonces es ahi donde formatearemos lo que el usuario haya ingresado en los inputs de la vista. Tienes que agregarlo en el modelo. Este serìa para el modelo category:
class Category < ApplicationRecord has_many :tasks before_validation :strip_withe_spaces #ESTE ES EL BEFORE VALIDATION, LE AGREGAS EL NOMBRE QUE QUIERAS AL METODO validates :name, :description, presence: true validates :name, uniqueness: {case_sensitive: false} #metodo que le quita los espacios al nombre antes de validar def strip_withe_spaces self.name = self.name.strip unless self.name.nil? end end
A esto se le llama call_backs. Aquí te dejo más info
Espero esto te ayude
Excelente la explicación me queda muy claró cómo realizar validaciones, estoy tratando de implementarlas en una api y rescatarlas para presentarlas en un front ssr.
Profesor Johan Tique, podrías subir el código del proyecto que se está desarrollando a un github para que yo pueda comparar algunos contenidos? Lo que pasa que yo estoy trabajando sin HAML y sin simple_form, y me he topado con un incoveniente.
Resulta que mi vista "tasks/new" en la parte donde debe ir categoría no me renderiza un selector, sino un campo de tipo input, y aunque le escriba un nombre de categoría correcta, no me deja guardar la task, porque me sale como mensaje de error que no existe categoría.
Esta es mi vista "tasks/new":
Y aquí se puede ver la vista de categories
Hola,
Lo puedes encontrar en la sección de recursos de la segunda clase.
Aquí te lo dejo.
Muchas gracias, CarlosAlba