2009-10-12 5 views
6

Je développe un site Web Rails 2.3.1. Tout au long du site Web, j'ai besoin d'un formulaire pour créer des messages sur différentes pages (page d'accueil, page de création de messages, page de publication, page de liste de commentaires, etc.). une variété de contrôleurs). Chacune de ces pages affiche une grande variété d'autres informations qui sont récupérées dans le contrôleur/action correspondant. Ex, la page d'accueil liste les 10 derniers messages, le contenu extrait de la base de données, etc.Rails meilleure pratique pour avoir la même forme sur plusieurs pages

J'ai donc déplacé le formulaire de création de message dans sa propre partie, et j'ai inclus ce partiel sur toutes les pages nécessaires. Notez que le formulaire dans les POST partiels à/questions (qui route vers PostsController :: create - c'est le comportement des rails par défaut). Le problème que je rencontre est lorsque le formulaire Posts n'est pas complété correctement, par défaut la méthode PostsController :: create rend les questions/new.html.erb, même si le formulaire a été soumis à partir de la page d'accueil (/ home/index.html.erb).

J'ai essayé de changer le formulaire dans le partiel pour envoyer le "submitting_controller" et "submitting_action", et dans PostsController :: create, quand @ post.save? == false, je rends l'action => "../submitting_controller/submitting_action" (Ce qui est légèrement hacky, mais permet de rendre des actions de non-PostsController).

Cela a semblé fonctionner correctement sur la surface. Le formulaire incomplet a été rendu dans la vue qui l'a envoyé avec tout le bon message @ post.errors, etc. Le problème était que TOUTES les autres données sur les pages ne s'affichaient pas, parce que les méthodes réelles submitting_controller/submitting_action n'étaient pas appelées, juste la vue associée. (Rappelez-vous, j'ai fait un rendu qui préserve les objets d'instance, plutôt qu'un redirect_to qui ne conserve pas l'objet instance @post qui a tous les messages d'erreur et les valeurs soumises.)

Pour autant que je peux voir, j'ai deux options :

1) Je peux stocker l'objet @post dans la session lorsque @ post.save? échoue dans PostsController :: create, redirect_to submitting_controller/submitting_action, à quel point je retire l'objet @post de la session et l'utilise pour re-remplir les messages formulaire/erreur. (Pour autant que je sache, stocker des objets dans la session est pratique BAD dans les rails)

2) Je peux déplacer toute la logique utilisée pour extraire des données de formulaire de création non-post à partir des divers submitting_controller/submitting_action, le mettre dans le ApplicationController, créez une instruction switch géante dans PostsController :: create pour submitting_controller/submitting_action et appelez les méthodes dans ApplicationController pour récupérer toutes les données supplémentaires nécessaires au rendu de chaque page soumise. Réflexions sur la meilleure façon de faire cela dans Rails?

Répondre

1

Est-ce que votre modèle Post est dans une relation belongs_to avec chaque modèle dont vous allez utiliser le contrôleur pour rendre votre formulaire? Effectuez-vous un traitement spécial dans le contrôleur Post au-delà de Post.create(params[:post])? Si vous avez répondu oui à la première question et non à la seconde, vous pourriez vous débrouiller avec un minimum de modifications en ajoutant accept_nested_attributes_for à chacun des contrôleurs sur lesquels un utilisateur peut créer un message. Quoi qu'il en soit, Robertpostill a raison de dire que c'est probablement le moment de commencer à regarder AJAX, simplement de remplacer la section de la page. Le seul problème est de savoir quoi faire si un utilisateur a javascript désactivé. Personnellement, j'aime faire de la conception pour le cas non-javascript et ajouter des méthodes de commodité.

Quant aux réflexions sur ce que vous considérez comme vos deux options,

1) Je l'ai utilisé cette méthode pour stocker une copie superficielle d'un objet dans le hachage flash. Le préserver à travers les redirections. Cependant, cela pourrait ne pas fonctionner pour vous compte tenu de la nature variable des messages. Comme vous ne pouvez envoyer qu'environ 4K de données, et cela inclut d'autres informations en plus de votre copie superficielle.

2) Voir la réponse

+0

Emfi, Bon point sur les attributs imbriqués. Cela ne m'est pas venu à l'esprit. Le point que vous faites sur la non-JS est important. Le sentiment que j'ai eu est que le questionneur (faute d'une meilleure poignée :) finira par nuire aux performances de l'application à travers la quantité d'action DB qu'il/elle devra effectuer pour reconstituer tous les objets. – robertpostill

+0

Sur ce, nous sommes d'accord. Cependant, la différence entre un non-javascript et un AJAX est généralement un appel link_to_remote, un RJS qui rend un template, et peut-être une petite logique de contrôleur pour éviter les appels de base de données que vous feriez normalement sinon. – EmFi

+0

EmFi, Malheureusement, le modèle Post et les modèles dont vous allez utiliser le contrôleur pour rendre le formulaire ne sont peut-être pas liés. (HomeController n'a même pas de modèle de support). Je fais quelques vérifications sur un mécanisme captcha dans PostController :: create (le champ captcha ne fait pas partie du Post Model, mais plutôt son propre module). Je pense que vous et Robertpostill avez raison dans AJAX est le moyen de résoudre ce problème.Je dois juste comprendre comment le faire avec jQuery (j'ai choisi de ne pas utiliser Prototype, pref personnel) et ne pas muck quoi que ce soit dans Rails. – empire29

1

Il s'agit du fait que vous passez des mises à jour de page entière à la mise à jour des sections d'une page en utilisant AJAX. Il y a un tas de choses que vous devriez considérer mais l'approche la plus linéaire serait de diviser la réponse entre une réponse AJAX et une réponse HTML. Découvrez this ONLamp article, this register article ou the awesome agile web development with rails book. Essentiellement, votre contrôleur rend une nouvelle div remplaçant l'ancienne div contenant le résultat de soumettre le partiel.

Dans votre question, vous mentionner deux approches et je vais donc essayer de vous donner quelques conseils sur pourquoi et pourquoi pas ici:

Option 1) Option Thessaloniciens est pas si mal avec un couple de coups secs. Le réglage principal est de stocker l'objet sous une forme sérialisée dans le DB. Ensuite, passez simplement l'ID de l'objet sérialisé.Vos avantages sont que les données de session sont conservées, donc la récupération d'une session est plus simple et votre session reste légère. L'inconvénient de ceci est que le fait d'avoir un seau de sessions croupes dans votre base de données polluera votre application et vous devrez réfléchir à la façon dont vous expirez de la base de données. Je n'ai jamais vu cette fin bien ...

Option2) Esez pas dans l'application_controller! :) Sérieusement, gardez cela comme votre arme de dernier recours. Vous pouvez cependant afficher des choses dans les assistants et accéder à ces méthodes dans vos contrôleurs et vues. Cependant, le test de ce genre de choses n'est pas si facile, alors faites attention avant de choisir cette route. Switch instructions peuvent être remplacés dans les applications OO avec un peu de réflexion, certainement dans son cas, vous pouvez utiliser des options de hachage pour obtenir une façon d'avoir quelques smarts sur l'état de l'application au moment où la demande est faite.

+0

Merci de, A pensées couple de robertpostill: Option 1) objs de suivi dans le DB semble que cela pourrait se transformer en un cauchemar, une pente glissante en effet. Option 2) Je ne pensais pas que les contrôleurs pouvaient accéder à des aides (cela doit être une influence de CakePHP). Je suis d'accord que le ApplicationController est un endroit grossier pour les mettre;) Le Hash est une bonne idée, bien que je n'aime toujours pas que toutes ces sélections de données spécifiques à une vue soient déplacées dans des helpers - il semble juste qu'il pourrait facilement devenir un cauchemar d'entretien. Je vais relire les articles que vous avez fournis, mais je pense qu'AJAX sera la voie à suivre. – empire29