51 votes

Contrôle de l'ordre des validations des rails

J'ai un rails de modèle qui a 7 attributs numériques rempli par l'utilisateur via un formulaire.

J'ai besoin de valider la présence de chacun de ces attributs qui n'est évidemment facile à l'aide d'

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

Cependant j'ai aussi besoin d'exécuter un validateur personnalisé qui prend un certain nombre d'attributs et fait quelques calculs avec eux. Si le résultat de ces calculs n'est pas à l'intérieur d'une certaine fourchette, puis le modèle devrait être déclaré invalide.

Sur c'est propre, c'est trop facile

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

Toutefois, le problème est que la méthode "valider" toujours est exécuté avant que la méthode "valide". Cela signifie que si l'utilisateur quitte l'un des champs obligatoires vides, des rails déclenche une erreur lorsqu'il tente de faire un calcul avec un vide d'attribut.

Alors, comment puis-je vérifier la présence de tous les attributs requis en premier?

21voto

tadman Points 70178

Je ne suis pas sûr que c'est garanti quel ordre ces validations se faire rouler dans, il peut dépendre de la façon dont l' attributes de hachage lui-même finit par commandés. Vous avez peut-être mieux de faire vos validate méthode plus résilients et fonctionne tout simplement pas si certains de données requis est manquant. Par exemple:

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

  # ...
end

Cela va renflouer si l'une des variables d' a par d sont vides, ce qui inclut le néant, vide des tableaux ou des chaînes, et ainsi de suite.

9voto

James H Points 573

Une alternative un peu plus complexe serait de créer une méthode d'aide qui gère le validations pour les attributs dépendants la première. Ensuite, vous pouvez faire votre :calculations_ok? validation exécuter conditionnellement.

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

J'ai eu à créer quelque chose comme ça pour un projet parce que les validations sur les attributs dépendants étaient assez complexes. Mon équivalent de :calculations_ok? permettrait de lever une exception si les attributs dépendants ne valide pas correctement.

Avantages:

  • relativement SEC, surtout si vos validations sont complexes
  • assure que vos erreurs tableau des rapports de la droite échec de la validation de la place de la macro-validation
  • inclut automatiquement des validations supplémentaires sur les attributs dépendants de vous ajouter plus tard

Mises en garde:

  • potentiellement s'exécute toutes les validations deux fois
  • vous ne voulez pas que toutes les validations pour s'exécuter sur les attributs dépendants

2voto

David Sulc Points 13259

Consultez http://railscasts.com/episodes/211-validations-in-rails-3

Après avoir implémenté un validateur personnalisé, vous ferez simplement

 validates :attribute1, :calculations_ok => true
 

Ceci devrait régler votre problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X