2009-09-15 10 views
0

Dans l'un de mes objets modèles, j'ai un tableau d'objets.Comment puis-je forcer la validation en cas d'ajout d'un objet à un autre objet dans Rails?

Dans la vue, j'ai créé un formulaire simple pour ajouter des objets supplémentaires au tableau via une boîte de sélection.

Dans le contrôleur j'utiliser la méthode append pour ajouter un utilisateur des objets sélectionnés dans le tableau:

def add_adjacents 
    @site = Site.find(params[:id]) 

    if request.post? 
    @site.adjacents << Site.find(params[:adjacents]) 
    redirect_to :back 
    end  
end 

J'ai ajouté une validation au modèle validate_the uniqueness_of :neighbors mais en utilisant la méthode append semble être sans passer par la validation.

Existe-t-il un moyen de forcer la validation? Ou un moyen plus approprié d'ajouter un élément au tableau afin que la validation se produise? Été googling partout pour cela et aller sur les livres, mais ne trouve rien à ce sujet.

+1

Comment vos associations de modèles sont-elles configurées? – hgmnz

Répondre

0

Avez-vous essayé de vérifier la validité par la suite en appelant le ".valid?" méthode, comme indiqué ci-dessous?

def add_adjacents 
    @site = Site.find(params[:id]) 
    @site.neighbors << Site.find(params[:neighbors]) 
    unless @site.valid? 
    #it's not valid, do something to fix it! 
    end 
end 
+0

J'ai ajouté le @ à moins.valid?ligne et je reçois l'erreur suivante: NoMethodError dans SitesController # add_adjacents Vous avez un objet nul quand vous ne l'attendiez pas! L'erreur s'est produite lors de l'évaluation de nil.text? J'ai également ajouté des entrées en double et essayé d'utiliser @ site.valid? commande dans la console de ruby ​​et il évalue à vrai – Frank

0

Quelques commentaires:

  1. Alors seule façon de garantir l'unicité est d'ajouter une contrainte unique sur la base de données. validates_uniqueness_of a ses gotchas quand il y a beaucoup d'utilisateurs dans le système:
    • Le processus 1 vérifie l'unicité, renvoie vrai.
    • Le processus 2 vérifie l'unicité, renvoie true.
    • Le processus 1 enregistre.
    • Le processus 2 enregistre.
    • Vous êtes en difficulté.
  2. Pourquoi devez-vous tester request.post?? Cela devrait être géré par vos routes, donc à mon avis c'est logique d'engraisser votre contrôleur inutilement. J'imagine quelque chose comme ce qui suit dans config/routes.rb: map.resources :sites, :member => { :add_adjacents => :post }
  3. Besoin d'en savoir plus sur vos associations pour savoir comment validates_uniqueness_of devrait jouer dans cette configuration ...
+0

La raison pour laquelle j'ai testé pour request.post? était parce que je ne pouvais pas obtenir la valeur de params [: id] quand j'ai utilisé submit_tag sur le formulaire et il est allé à une deuxième action. J'ai recherché form_tag dans Rails Way (page 379) et l'auteur a suggéré que ce serait un moyen rapide de gérer les post-backs (mon but ultime est de mettre à jour la vue avec ajax, mais je voulais commencer petit avant de compliquer le tout. Pour ce qui est de l'association, c'est un peu compliqué, le modèle du site a_et_s'implique beaucoup: les voisins.C'est une relation auto-référentielle, réalisée via une table de formulaire .Pour référence http://tinyurl.com/ommquj – Frank

+0

Puisque vous me dites que il y a un modèle de jointure, vous devriez pouvoir mettre validates_uniqueness_of: site_id,: scope =>: adjacent_site_id dedans (bien sûr, je fais des noms puisque vous n'avez pas vraiment dit ce que sont vos associations). – hgmnz

0

Je pense que vous » re recherchant ceci:

@site.adjacents.build params[:adjacents] 

la méthode de construction acceptera un tableau de hachages d'attribut. Ceux-ci seront validés avec le modèle parent au moment du gain. Puisque vous êtes validating_uniqueness_of, vous pourriez avoir un peu d'étrangeté lorsque vous sauvegardez plusieurs enregistrements en conflit en même temps, en fonction de l'implémentation des rails pour les phases de sauvegarde et de validation de l'association.

Une solution de contournement hacky serait à votre params uniques quand ils viennent dans la porte, comme ceci:

@site.adjacents.build params[:adjacents].inject([]) do |okay_group, candidate| 
    if okay_group.all? { |item| item[:neighbor_id] != candidate[:neighbor_id] } 
    okay_group << candidate 
    end 
    okay_group 
end 

Pour le crédit supplémentaire, vous pouvez tenir cette opération de retour dans le modèle.

Questions connexes