4

J'ai un modèle utilisateur avec une relation HABTM aux groupes. Je ne veux pas qu'un utilisateur puisse être dans plus de 5 groupes, donc je voudrais valider la durée de la relation HABTM.Validation de la longueur de l'association habtm sans enregistrement

Sur la page d'édition d'utilisateur, j'ai une liste de cases à cocher où l'utilisateur peut sélectionner les groupes dans lesquels il veut être (j'utilise formtastic pour le formulaire).

Dans mon contrôleur utilisateurs Je vous appelle:

@user.update_attributes(params[:user]) 

qui est à l'origine des rails pour mettre à jour les associations automatiquement.

Dans mon modèle d'utilisateur, je donne les résultats suivants:

def validate 
    if self.groups.length > 5 
     self.errors.add(:groups, "cannot have more than 5 groups") 
    end 
end 

Ceci est à l'origine de la forme à l'échec de la validation, mais les update_attributes appelle a déjà mis à jour la base de données afin de refléter les changements aux groupes associés. Ainsi, chaque fois qu'un utilisateur clique sur le bouton Enregistrer, ses associations de groupes sont enregistrées, même si l'enregistrement n'est pas valide.

Quelle est la meilleure façon de résoudre ce problème?

Je pense que la validation doit être sur le modèle de groupe au lieu du modèle d'utilisateur, cela fonctionnerait-il? Idéalement, je voudrais mettre à jour les groupes associés sans enregistrer l'enregistrement, faire la validation, et ensuite enregistrer l'enregistrement.

Répondre

11

Vous avez eu deux problèmes:

  1. Vous surchargeons
  2. validation L'ordre des opérations de l'épargne est à l'origine des problèmes.

Vous écrasez la méthode de validation qui est une mauvaise chose, car le comportement intégré empêche les enregistrements contenant des erreurs de validation d'être enregistrés dans la base de données. Pour ajouter personnalisés vous validations voulez faire ceci:

validate :maximum_group_length 

def maximum_group_length 
    if self.groups.length > 5 
     self.errors.add(:groups, "cannot have more than 5 groups") 
    end 
end 

Cependant, la nature des relations HABTM vous oblige à le faire comme un rappel after_save. Juste à cause de l'ordre que les choses sont faites. user.groups est basé sur la table de jointure implicite et n'est pas mis à jour jusqu'à ce que la table de jointure soit mise à jour.

Si vous essayez de valider dans le cadre d'un rappel (before_save, after_creation, etc.), l'ajout d'une erreur à l'objet ne déclenchera pas de retour arrière. Les rappels ne déclenchent une annulation que s'ils retournent faux. Cela gérera l'implémentation après sauvegarde que la question suggère.

after_save :validate_maximum_group_length 

def validate_maximum_group_length 
    if self.groups.length > 5 
     self.errors.add(:groups, "cannot have more than 5 groups") 
     return false 
    end 
end 

Une autre solution consiste à utiliser un modèle de jointure explicite. Et un has_many: à travers la relation. La table du modèle de jointure est mise à jour dans l'instruction update. Où les relations has_many: through et HABTM mettent à jour la relation après la sauvegarde. HABTM utilise implicitement une table de jointure, donc il n'a pas besoin d'être changé du côté du groupe.

Cependant, vous devrez modifier votre formulaire pour mettre à jour le formulaire pour fournir group_id dans le hachage params comme params[:user][:user_group_attributes][0][:group_id][3]

+0

Cela ne résout pas, il est persistant encore les changements. – jonnii

+0

On dirait que j'ai mal diagnostiqué votre problème, je pensais que vous validiez comme un rappel. Le problème était que vous étiez en train de redéfinir la validation. – EmFi

+0

J'ai déplacé la validation dans une routine de validation personnalisée comme suggéré, mais cela ne résout toujours pas le problème. – jonnii