Ouverture de session

Commentaires récents

Syndication
Flux XML

[Résolu] Problème de création d'enregistrements avec has_and_belongs_to_many et collection_select

[Résolu] Problème de création d'enregistrements avec has_and_belongs_to_many et collection_select
Posté par djib le Dimanche, 27 Mai, 2007 - 11:55pm. Débuter avec Rails

Bonjour,

Je fais un projet de gestion de tours de magie (tricks). Chaque tours a plusieurs techniques et inversement. J'ai donc une relation de :has_and_belongs_to_many entre les deux que j'ai déclarée dans les modèles respectifs.

Je suis maintenant en train de créer un formulaire pour la création de tours de magie. J'y ai inséré un select à choix multiples qui m'affiche bien toutes les techniques que j'ai (et qui me resélectionne les techniques sélectionnées après un message d'erreur).

collection_select(:trick, :technique_ids,
 Technique.find(:all), :id, :name, {:prompt => false},
 {:multiple => true, :size => 5})

Quand je regarde le code source, ça me génère un élément avec name="trick[technique_ids][]" ce qui me semble correct.

J'ai un problème à la création du tour. J'obtiens le message Techniques is invalid dans un flash, autant de fois que j'ai sélectionné d'éléments dans mon select.

Pour créer mon tour de magie j'utilise la commande :

@trick = Trick.new(params[:trick])

et je me demande si ce n'est pas elle qui génère le flash.

Je ne comprends pas trop d'où vient ce problème. Des idées ?

Merci.



[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | sujet précédent | sujet suivant | envoyer par email ]

Options d'affichage des commentaires
Sélectionnez la méthode d'affichage des commentaires que vous préférez, puis cliquez sur "Sauvegarder" pour activer vos changements.

Sujet: 
des tours de magie?
Auteur: 
orfeu
Date: 
Lun, 28/05/2007 - 01:39

deja je ne crois que les erreurs dans activerecord ne generent pas de flash...

Apres, pour le probleme, je crois que lorsque tu ajoute une technique a ton trick, il ne faut pas mettre un new mais un push d'une technique. Mais je ne connais pas trop l'orthographe de collection_select...Il te renvoie quoi comme requete?

Mais cette histoire de tours de magie, je ne comprend pas trop... faudra que tu post le résultat!


[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | envoyer par email ]

Sujet: 
Tu as raison... mais c'est pas encore ça
Auteur: 
djib
Date: 
Lun, 28/05/2007 - 03:23

Tu as parfaitement raison orfeu, visiblement ce qui pose problème c'est la création "simultanée" des tours et des techniques rattachées. Si je modifie mon code à la manière suivante :

collection_select(:technique, :id, Technique.find(:all),
  :id, :name, {:prompt => false}, {:multiple => true, :size => 5})

dans la vue et:

    @trick = Trick.new(params[:trick])
    if @trick.save
      @trick.techniques < < Technique.find(
        params[:technique][:id].collect{|char| char.to_i}
      )
    end

dans le contrôleur j'ai presque le comportement souhaité.

Je dis bien presque car à ce moment là, je ne garde pas la sélection des techniques en cas d'erreur dans un autre champ (nom du tour invalide, ...). C'est pourtant un comportement auquel je tiens beaucoup : je ne devrais pas avoir a resélectionner les techniques simplement parce que j'ai oublié d'entrer un titre à mon tour.

Comment donc puis-je faire pour que les éléments soient re-sélectionnés ?

Aussi, comment puis-je savoir la requête que revoie 'collection_select' ?

Enfin je n'hésiterai pas un instant à partager ma petite base quand elle sera un peu plus avancée.

Merci pour ton aide.


[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | envoyer par email ]

Sujet: 
params
Auteur: 
jasperiel
Date: 
Lun, 28/05/2007 - 08:51

Salut,

tes données sont sauvées entre un new et un create dans les params : rails sérialise tout ça comme il faut pour renvoyer les données du form, et s'il voit les données conservées dans les params il les rétablit.

Ton problème signifie qu'il n'y a pas de conservation de tes données de cette manière. Je te recommande de surveiller comment ton select est sérialisé dans les params (c'est peut etre simplement qu'il est en 'toplevel' et pas dans le hash correspondant au form), avec un params.inspect en haut de ta page create (vive le debug en verbose !).

Une fois que tu auras vu la cause, tu pourras si c'est vraiment nécessaire coder dans ton contrôleur qqch qui convertit tes params 'non-standard' en params standard afin que tes données s'actualisent.

Bon code !


[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | envoyer par email ]

Sujet: 
Params.inspect
Auteur: 
djib
Date: 
Lun, 28/05/2007 - 20:44

Bonjour,

En faisant params.inspect j'obtiens :

{
  "trick"=>{
    "name"=>"",
    "explanation"=>"",
    "sweet_talk"=>"",
    "author_id"=>""
  },
  "commit"=>"Create",
  "action"=>"create",
  "controller"=>"trick",
  "techniques"=>{
    "id"=>["1", "2"]
  }
}

Je trouve donc bien techniques dans mes paramètres. C'est un tableau des deux ids qui sont bien ceux que j'ai choisis. (Cela explique le fait que les données sont bien enregistrées...)

Pourquoi donc est-ce que mes entrées ne sont pas sélectionnées ?


[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | envoyer par email ]

Sujet: 
nest
Auteur: 
jasperiel
Date: 
Lun, 28/05/2007 - 21:37

Toutes les proprietes de Trick sont dans la hash "trick" => {...}
Technique est hors de cette hash.

Tu peux donc faire un truc sale dans ton controleur :
params[:trick][:techniques] = params[:techniques]

ou un truc propre dans ta vue :
regarder le code source, comprendre qu'il y a une convention de nommage dans les proprietes HTML 'ID' et 'NAME', et appliquer cette convention a "techniques".

On fait du HTML. Regarder le source genere c'est bien :P


[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | envoyer par email ]

Sujet: 
Oui, mais après viens le problème du Trick.new()
Auteur: 
djib
Date: 
Lun, 28/05/2007 - 22:42

OK, je ne savais pas que mes paramètres devaient forcément être dans dans le hash trick.
Je pense cependant que je retombe sur le même problème que celui du début si je mets les valeurs dans le hash : la commande @trick = Trick.new(params[:trick]) va générer une erreur. En effet, le contrôleur ne va pas pouvoir créer simultanément le tour et lui attribuer les techniques : il faudrait d'abord créer le tour avec les paramètres ne dépendant pas des techniques, puis associer les techniques au tour.

Je m'explique : si je veux que mes données soient sauvées dans le hash trick (avoir un attribut name du genre trick[toto][]) je dois (si j'ai bien compris) nécessairement avoir soit
collection_select(:trick,:techniques, ...)
ou
collection_select(:trick,:technique_ids, ...).

Le premier cas me génére une erreur :

Technique expected, got String

Je pense comprendre ce message : le select renvoie l'id d'une Technique, pas d'un objet Technique.

Le deuxième cas me ré-affiche la vue avec le message :

Techniques is invalid

provenant de error_messages_for 'trick'.
Je suis beaucoup plus perplexe par rapport à ce message que je ne comprends pas trop.

Je me casse peut-être la tête, mais je ne vois vraiment pas comment m'en sortir.
Désolé et surtout merci pour votre aide.


[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | envoyer par email ]

Sujet: 
[Résolu] (Je suis stupide)
Auteur: 
djib
Date: 
Mar, 29/05/2007 - 00:08

Je suis vraiment c**. L'erreur Techniques is invalid est parfaitement logique puis que j'ai changé mon modèle de données :S Vraiment je ne suis pas malin, j'ai oublié de mettre à jour les enregistrements qui existaient déjà, et forcément quand le contrôleur les envoie au modèle, ils ne sont plus bon.

J'en reviens pas d'avoir perdu autant de temps la dessus, et je suis vraiment désolé de vous avoir fait perdre du temps.
Pour que tout ceci ne soit pas inutile, voici ma solution finale :

Dans la vue :

<p><label for="trick_technique_ids">Techniques (multiple choice)</label><br/>
<%= collection_select(:trick, :technique_ids,
 Technique.find(:all), :id, :name, 
 {:prompt => false}, {:multiple => true, :size => 5}) %>
</p>

Dans le contrôleur :

  def create
    @trick = Trick.new(params[:trick])
    if @trick.save
      flash[:notice] = 'Trick was successfully created.'
      redirect_to :action => 'list'
    else
      render :action => 'new'
    end
  end

et c'est tout, ça marche nickel !

Vive Rails et je ne peux que me dire que c'est pas ses erreurs qu'on apprends :) On est toujours un peu déboussolé quand on débute : je n'ai pas été assez méthodique et j'ai mal interprété les erreurs :)

Merci à tous.


[ Vous devez vous connecter ou vous enregistrer pour écrire des commentaires | envoyer par email ]

Nouveaux liens

Sondage
Lorsque je développe avec Ruby on Rails c'est principalement sous:
Linux
36%
Mac OS X
30%
Windows
32%
(Free|Open|Net) BSD
1%
Autre...
1%
Nombre de votes: 368

Qui est en ligne
Il y a actuellement 1 utilisateur et 68 invités en ligne.

railsfrance.org - communauté francophone des utilisateurs de Ruby on Rails
[ Hébergement et ressources techniques gracieusement fournis par la SSLL Nuxos Group ]