2010-06-01 12 views
8

J'ai un formulaire d'inscription qui a des associations/attributs imbriqués que vous voulez appeler.Rails: se débarrasser des erreurs de validation génériques "X is invalid"

Ma hiérarchie est la suivante:

class User < ActiveRecord::Base 
    acts_as_authentic 
    belongs_to :user_role, :polymorphic => true 
end 

class Customer < ActiveRecord::Base 
    has_one :user, :as => :user_role, :dependent => :destroy 
    accepts_nested_attributes_for :user, :allow_destroy => true 
    validates_associated :user 
end 

class Employee < ActiveRecord::Base 
    has_one :user, :as => :user_role, :dependent => :destroy 
    accepts_nested_attributes_for :user, :allow_destroy => true 
    validates_associated :user 
end 

J'ai des trucs de validation dans ces classes ainsi. Mon problème est que si j'essaye de créer et client (ou employé etc.) avec un formulaire vide j'obtiens toutes les erreurs de validation que je devrais obtenir plus certains génériques comme "l'utilisateur n'est pas valide" et "le client est invalide" les erreurs je reçois quelque chose comme:

user.login can't be blank 
User is invalid 
customer.whatever is blah blah blah...etc 
customer.some_other_error etc etc 

comme il y a au moins un champ non valide dans le modèle imbriqué utilisateur, un message supplémentaire « X est non valide » est ajouté à la liste des erreurs. Cela devient confus pour mon client et je me demande s'il y a un moyen rapide de le faire au lieu d'avoir à filtrer les erreurs moi-même.

Répondre

6

Salil réponse était presque droit mais il n'a jamais fait de 100%. Voici la bonne façon de le faire:

def after_validation 
    # Skip errors that won't be useful to the end user 
    filtered_errors = self.errors.reject{ |err| %{ person }.include?(err.first) } 

    # recollect the field names and retitlize them 
    # this was I won't be getting 'user.person.first_name' and instead I'll get 
    # 'First name' 
    filtered_errors.collect{ |err| 
     if err[0] =~ /(.+\.)?(.+)$/ 
     err[0] = $2.titleize 
     end 
     err 
    } 

    # reset the errors collection and repopulate it with the filtered errors. 
    self.errors.clear 
    filtered_errors.each { |err| self.errors.add(*err) } 
    end 
+0

En outre, j'ai proposé une demande de fonctionnalité comme une meilleure solution, puis cette solution: https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/5632-validates_associated-should-be-allowed -to-not-create-an-error # ticket-5632-2 – DJTripleThreat

+0

Je reçois erreur "pas de conversion implicite de symbole en chaîne" – Chemist

+0

@Chemist cela fonctionnait pour une version plus ancienne de rails. Essayez de modifier le code fourni pour qu'il fonctionne correctement avec la version que vous utilisez actuellement. – DJTripleThreat

3

Utilisez after_validation méthode

def after_validation 
    # Skip errors that won't be useful to the end user 
    filtered_errors = self.errors.reject{ |err| %w{ user User }.include?(err.first) } 
    self.errors.clear 
    filtered_errors.each { |err| self.errors.add(*err) } 
    end 

ÉDITÉ

Note: -

Ajouter la dans la liste suivante dans votre cas, il est l'utilisateur ou de l'utilisateur. vous pouvez en ajouter plusieurs si vous avez plusieurs assosciations séparées par un espace. de

%w{ User user }.include?(err.first) #### This piece of code from the above method has logic which reject the errors which won't be useful to the end user 
+0

Ok, cela semble prometteur! :) Je pense que vous avez une erreur de grammaire sous "Note: -" ce qui me déroute .. "Ajouter le ... ???" Aussi, où devrais-je mettre cette fonction? dans chaque modèle qui fait cela? Est-ce une fonction de remplacement d'ARB? – DJTripleThreat

+0

désolé pour la grammaire :). mettre cette méthode dans chaque modèle où vous écrivez ** validates_associated ** – Salil

+0

Ok, je vais vous upvote maintenant parce que cela fonctionne principalement. Un problème cependant: au lieu de cela: ** Login ** est trop court (minimum de 3 caractères) ** Mot de passe ** est trop court (4 caractères minimum) ** La confirmation du mot de passe ** est trop courte (minimum est de 4 caractères) Je reçois ceci: ** User.login ** est trop court (minimum est de 3 caractères) ** user.password ** est trop court (minimum est de 4 caractères) ** utilisateur .password confirmation ** est trop court (minimum 4 caractères) Si vous pouvez trouver une solution, j'accepte votre réponse. – DJTripleThreat