2009-05-09 6 views
2

J'utilise un motif hideux dans mon code et je sais qu'il doit y avoir une meilleure façon de procéder. Aide-moi à repenser à ce que je fais.Passer des données entre les contrôleurs avec la session RESTfully

Mon site Web est une sorte de forum de discussion. Toutes les réponses aux discussions sont faites sur la page de discussion DiscussionsController #, inline.

Certaines réponses ne sont cependant pas valides. Par exemple, si vous tentez d'envoyer une réponse qui ne contient aucun texte, elle vous renvoie à DiscussionsController # show avec un message d'erreur.

Voici un bref aperçu de la façon dont je l'ai mis en œuvre ce flux de travail:

  1. utilisateur va montrer DiscussionsController de #. Ce modèle a un formulaire de réponse dessus. Il n'y a pas d'action # RepliesController explicite.
  2. L'utilisateur soumet un formulaire de réponse, qui est POSTé sur replies_path et géré dans RepliesController # create.
  3. RepliesController # create ne peut pas enregistrer la réponse car elle est invalide (validates_length_of in Reply invalide l'objet).
  4. RepliesController # create place l'objet réponse en session [: new_reply] et redirige vers le chemin de discussion d'où provient l'utilisateur.
  5. DiscussionsController # show gère l'objet de la session ...

comme ceci:

if session[:new_reply] 
    @new_reply = session[:new_reply] 
    session.delete(:new_reply) 
end 

Et maintenant show.html.erb a un objet @new_reply nouvellement régénéré pour inspecter les erreurs.

Il y a quelque chose qui ne va pas: vous ne devriez pas stocker des objets entiers à l'intérieur de la session. Mais puisque l'objet Reply que nous avons essayé d'enregistrer dans RepliesController # create n'est jamais sauvegardé, comment puis-je le conserver entre les appels d'action du contrôleur?

Ou s'il y a une solution de conception plus grande, n'hésitez pas à le partager. C'est tellement moche que ça me fait mal. Merci.

Répondre

2

Au lieu de rediriger, faites plutôt render :action => "discussions/show" à la place. J'allais dire que vous deviez aussi configurer la variable @discussion, mais cela devrait être fait puisque les réponses sont des ressources imbriquées dans les discussions, n'est-ce pas?

+0

Je fais ce genre de choses de cette façon. Assurez-vous d'avoir @discussion et @reply chargés. – klew

+0

J'ai pensé faire cela, mais il y a deux raisons pour lesquelles je n'aime pas l'approche de rendu: 1. Il change l'URL; Je voudrais garder l'illusion que vous êtes toujours sur la même page (parce que vous êtes). 2. Je n'aime vraiment pas le fait que je dois dupliquer la logique dans DiscussionsController # show - en m'assurant que les mêmes filtres sont appliqués, en m'assurant que @ discussion et d'autres variables d'instance sont choisies de la même manière avec des conditions, etc.) - ne semble pas très sec. – Raphomet

2

Au lieu de la session, je stocker la réponse dans le flash, ce qui est bon pour passer des messages/objets à travers une action.

Le contrôleur serait tout simplement stocker la réponse dans le flash si elle n'a pas été valide et redirect:

if @reply.save 
    ... 
else 
    flash[:reply] = @reply 
end 

Et votre logique de formulaire sur les discussions/page spectacle devrait être un peu plus intelligent et de saisir la réponse dans le flash ou la nouvelle (que je suppose que vous créez dans les discussions/action show):

form_for(flash[:reply] || @reply) do 
    ... 
end 
+0

Je n'étais pas enclin à l'utiliser - Obie Fernandez, auteur de The Rails Way, dit d'utiliser flash pour les messages et la session pour passer des valeurs entre les actions. Mais la documentation Rails (http://api.rubyonrails.org/classes/ActionController/Flash.html) semble impliquer que le flash est un endroit approprié pour stocker n'importe quel type d'objet temporairement. Je pense que je vais essayer ça pour le moment et en tirer des leçons si ça me brûle. :) – Raphomet

0

Je dirais que la façon dont vous le faire est raisonnable. Pas le plus propre mais c'est RESTful.

La suggestion de radar est géniale mais dans la version actuelle de Rails, l'utilisation de render :action => "discussions/show" ne crée pas le comportement correct, au moins dans mes tentatives, qui ont été sans routage de ressources imbriquées. L'utilisation de render :controller => "discussions", :action => "show" donne un autre comportement qui n'est pas ce que l'affiche recherche.

Questions connexes