Active Record Validations, Validadores de campos de Ruby on Rails

¿Qué son las validaciones?

Las validaciones son utilizadas para asegurarse que solo datos válidos son guardados dentro de la base de datos.

Validaciones del Modelo

Las validaciones del nivel del Modelo, son la mejor manera de asegurar que solo los datos válidos son guardados en la base de datos.

Son independientes del motor de base de datos.

Rails los hace fácil de utilizar, provee métodos helpers construidos previamente para las necesidades más comunes, y te permite crear tus propias validaciones también.

Las validaciones al nivel del modelo son las más apropiadas en la mayoría de las circunstancias.

Otro tipo de validaciones

Hay varias otras maneras de validar los datos antes de guardarlos en tu base de datos:

  • Incluyendo una restricciones nativas en la base de datos.
  • Validaciones del lado del cliente.
  • Validaciones a nivel de controlador.

 

¿Cuando y cómo se validan los modelos?

Se disparará las validaciones con los siguientes métodos:

  • create
  • create!
  • save
  • save!
  • update
  • update!

 

Para verificar si un objeto es valido, en Rails se utiliza los métodos:

  • valid?  –>      true->valido,             false->invalido
  • invalid? –>    true->invalido,         false->valido

Por ejemplo:

class Person < ActiveRecord::Base
  validates :name, presence: true
end
 
Person.create(name: "John Doe").valid? # => true
Person.create(name: nil).valid? # => false

Errores en la validación del modelo

Para conocer los errores que surgieron en las validaciones:

  • Primero deberemos haber disparado las validaciones con algún método.
  • A continuación, llamaremos al método errors.messages, el cual nos retorna la colección de errores.

Para verificar los errores de un atributo en particular, se utiliza errors[:nombreAtributo]

Helpers de Validación de los modelos

  • acceptance:  Valida si un checkbox en la interfaz de usuarios es chequeado al enviar un formulario.
class Person < ActiveRecord::Base
  validates :terms_of_service, acceptance: true
end

 

  • validates_associated:  Cuando tu modelo tiene asociaciones con otros modelos y también necesiten ser validados. Cuando intentas guardar tu objeto valid? será llamado por cada uno de los objetos asociados.

**No utilices validates_associated en ambas puntas de tus asociaciones, porque se llamarán la una a la otra en un ciclo infinito.

class Library < ActiveRecord::Base
  has_many :books
  validates_associated :books
end

 

  • confirmation: Cuando tengas dos campos de texto que deban recibir exactamente el mismo contenido. Por ejemplo, puedes querer confirmar una dirección de email pidiéndolo al usuario dos veces.

Se crea un atributo virtual cuyo nombre es el campo que tiene que ser confirmado con la «_confirmation» añadida.

class Person < ActiveRecord::Base
  validates :email, confirmation: true
  validates :email_confirmation, presence: true
end

Y en la vista quedaria asi:

<%= text_field :person, :email %>
<%= text_field :person, :email_confirmation %>

 

  • format: Valida los valores de los atributos si coinciden o no con una expresión regular dada.
class Product < ActiveRecord::Base
  validates :legacy_code, format: { with: /\A[a-zA-Z]+\z/,
    message: "only allows letters" }
end

 

  • inclusion: Valida que los valores de los atributos estén incluidos en una configuración dada. En realidad, esta configuración puede ser un objeto enumerable.
class Coffee < ActiveRecord::Base
  validates :size, inclusion: { in: %w(small medium large),
    message: "%{value} is not a valid size" }
end

 

  • exclusion: Valida que los valores de los atributos no están incluidos en una configuración dada. En realidad, esta configuración puede ser cualquier objeto enumerable.
class Account < ActiveRecord::Base
  validates :subdomain, exclusion: { in: %w(www us ca jp),
    message: "%{value} is reserved." }
end

 

  • length: Valida la longitud de los valores de los atributos.
class Person < ActiveRecord::Base
  validates :name, length: { minimum: 2 }
  validates :bio, length: { maximum: 500 }
  validates :password, length: { in: 6..20 }
  validates :registration_number, length: { is: 6 }
end

 

  • numericality: Valida que tus atributos tienen solo valores numéricos y si es mayor, menor igual que otros numeros.
class Player < ActiveRecord::Base
  validates :points, numericality: true
  validates :games_played, numericality: { only_integer: true }
end

 

  • presence: Valida que el atributo no este vacio.
class Person < ActiveRecord::Base
  validates :name, :login, :email, presence: true
end

 

  • absence: El contrario de presence?? Ejemplo. ¿Si lo modifico en la base de datos al traerlo nuevamente y comprobar si es valido no debería ser valido no?

 

  • uniqueness: Este asistente valida que el valor del atributo sea único justo antes de que se guarde el objeto.
class Account < ActiveRecord::Base
  validates :email, uniqueness: true
end

** No crea una restricción de exclusividad en la base de datos, por lo que puede suceder que dos conexiones de bases de datos diferentes creen dos registros con el mismo valor para una columna que pretenda ser única. Para evitar eso, debe crear un índice único en ambas columnas en su base de datos.

 

  • validate_with:  Valida el registro con una clase separada
class GoodnessValidator < ActiveModel::Validator
  def validate(record)
    if record.first_name == "Evil"
      record.errors[:base] << "This person is evil"
    end
  end
end
 
class Person < ActiveRecord::Base
  validates_with GoodnessValidator
end

 

  • validate_each: Este helper valida varios atributos contra un bloque de validación creado para ello. En el siguiente ejemplo, no queremos que los nombres y apellidos comiencen con letras minúsculas.
    • record= engloba todos los objeto
    • attr= nombre del atributo que se esta validando en ese momento
    • value= valor del atributo que se esta validando en ese momento
class Person < ActiveRecord::Base
  validates_each :name, :surname do |record, attr, value|
    record.errors.add(attr, 'must start with upper case') if value =~ /\A[[:lower:]]/
  end
end

 

Enlace: Guia Rails