54 votos

Controlar el orden de las validaciones de rieles

Tengo un rieles modelo que dispone de 7 atributos numéricos rellenados por el usuario a través de un formulario.

Necesito validar la presencia de cada uno de estos atributos, que es, obviamente, fácil de usar

validates :attribute1, :presence => true
validates :attribute2, :presence => true
# and so on through the attributes

Sin embargo, yo también necesita ejecutar un validador personalizado que toma un número de los atributos y hace algunos cálculos con ellos. Si el resultado de estos cálculos no se encuentra dentro de un cierto rango, a continuación, el modelo debe ser declarada nula.

En es propio, esto es demasiado fácil

validate :calculations_ok?

def calculations_ok?
  errors[:base] << "Not within required range" unless within_required_range?
end

def within_required_range?
  # check the calculations and return true or false here
end

Sin embargo, el problema es que el método de "validar" siempre se ejecuta antes de que el método de "valida". Esto significa que si el usuario sale de uno de los campos en blanco, rieles tira un error cuando se intenta hacer un cálculo con un espacio en blanco atributo.

Entonces, ¿cómo puedo verificar la presencia de todos los atributos necesarios en primer lugar?

22voto

tadman Puntos 70178

No estoy seguro de que es lo que garantiza el fin de estas validaciones consigue correr, ya que podría depender de cómo la attributes hash sí termina ordenado. Usted puede ser mejor de hacer su validate método más resistentes y simplemente no funciona si algunos de los datos requeridos es el que falta. Por ejemplo:

def within_required_range?
  return if ([ a, b, c, d ].find(&:blank?))

  # ...
end

Este va a rescatar a si alguna de las variables a través d están en blanco, que incluye nula, vacía de conjuntos o cadenas, y así sucesivamente.

9voto

James H Puntos 573

Una alternativa un poco más complejo de situaciones sería crear un método auxiliar que se ejecuta la validación de los atributos dependientes de la primera. Entonces usted puede hacer su :calculations_ok? validación de ejecución condicional.

validates :attribute1, :presence => true
validates :attribute2, :presence => true
...
validates :attribute7, :presence => true

validate :calculations_ok?, :unless => Proc.new { |a| a.dependent_attributes_valid? }

def dependent_attributes_valid?
  [:attribute1, ..., :attribute7].each do |field|
    self.class.validators_on(field).each { |v| v.validate(self) }
    return false if self.errors.messages[field].present?
  end
  return true
end

Tenía que crear algo como esto para un proyecto, porque las validaciones en los atributos dependientes son bastante complejas. Mi equivalente de :calculations_ok? podría lanzar una excepción si los atributos dependientes no validar correctamente.

Ventajas:

  • relativamente SECO, especialmente si su validaciones son complejos
  • se asegura de que sus errores de la matriz de los informes de la derecha fallado la validación del lugar de la macro-validación
  • incluye automáticamente a cualquier adicional validaciones sobre los atributos dependientes de agregar más tarde

Advertencias:

  • potencialmente se ejecuta todas las validaciones dos veces
  • puede que no quiera que todas las validaciones para que se ejecute en los atributos dependientes

2voto

David Sulc Puntos 13259

Echale un vistazo http://railscasts.com/episodes/211-validations-in-rails-3

Después de implementar un validador personalizado, simplemente harás

validates :attribute1, :calculations_ok => true

Debe resolver su problema.

Iteramos.com

Iteramos es una comunidad de desarrolladores que busca expandir el conocimiento de la programación mas allá del inglés.
Tenemos una gran cantidad de contenido, y también puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X