134 votes

form_for avec des ressources imbriquées

J'ai une question en deux parties sur form_for et imbriqués de ressources. Disons que je suis en train d'écrire un moteur de blog et je voudrais rapporter un commentaire à un article. J'ai défini un ensemble de ressources comme suit:

map.resources :articles do |articles|
    articles.resources :comments
end

Le formulaire de commentaires est dans le spectacle.html.erb vue pour les articles, en dessous de l'article lui-même, par exemple comme ceci:

<%= render :partial => "articles/article" %>
<% form_for([ :article, @comment]) do |f| %>
    <%= f.text_area :text %>
    <%= submit_tag "Submit" %>
<%  end %>

Cela donne une erreur", a Appelé l'id de néant, qui aurait, à tort, etc." J'ai aussi essayé

<% form_for @article, @comment do |f| %>

Qui s'affiche correctement, mais se rapporte f.text_area à l'article " champ de texte au lieu de le commenter, et présente le code html de l'article.attribut de texte dans cette zone de texte. Donc, il me semble avoir ce mal que de bien. Ce que je veux, c'est une formule dont le "soumettre" va appeler l'action de création sur CommentsController, avec une valeur contenue dans les paramètres, par exemple une requête post /articles/1/commentaires.

La deuxième partie de ma question est, quelle est la meilleure façon de créer le commentaire de l'instance pour commencer? Je suis de la création d'un @commentaire à la fin de l'action du contrôleur d'articles articlescontroller, donc un objet commentaire sera dans le champ de la form_for helper. Ensuite, dans l'action de création de la CommentsController, je vais créer de nouveaux @commenter en utilisant les paramètres transmis à partir de la form_for.

Merci!

239voto

cdunn2001 Points 3597

Travis R est correct. (Je souhaite que je pourrais upvote ya.) Je viens de recevoir ce travail moi-même. Avec ces lignes:

resources :articles do
  resources :comments
end

Vous obtenez les chemins comme:

/articles/42
/articles/42/comments/99

acheminés vers les contrôleurs de

app/controllers/articles_controller.rb
app/controllers/comments_controller.rb

comme il est dit à http://guides.rubyonrails.org/routing.html#nested-resources, aucun espace de noms.

Mais partiels et les formes deviennent difficiles. Remarque les crochets:

<%= form_for [@article, @comment] do |f| %>

Le plus important, si vous voulez un URI, vous pouvez avoir besoin de quelque chose comme ceci:

article_comment_path(@article, @comment)

Sinon:

[@article, @comment]

comme décrit au http://edgeguides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects

Par exemple, à l'intérieur d'une des collections partielles avec comment_item fourni par itération,

<%= link_to "delete", article_comment_path(@article, comment_item),
      :method => :delete, :confirm => "Really?" %>

Ce jamuraa dit peut fonctionner dans le contexte de l'Article, mais il ne fonctionne pas pour moi de diverses autres façons.

Il y a beaucoup de discussion au sujet de imbriquée des ressources, par exemple http://weblog.jamisbuck.org/2007/2/5/nesting-resources

Fait intéressant, je viens d'apprendre que la plupart des gens de l'unité-tests ne sont pas réellement de tester tous les chemins. Quand les gens suivent jamisbuck de la suggestion, ils se retrouvent avec deux façons d'obtenir à imbriquée ressources. Leur unité-tests seront généralement get/post au plus simple:

# POST /comments
post :create, :comment => {:article_id=>42, ...}

Afin de tester l'itinéraire qu'ils préfèrent, ils doivent le faire de cette façon:

# POST /articles/42/comments
post :create, :article_id => 42, :comment => {...}

J'ai appris cela parce que mon appareil-début des épreuves à défaut lorsque je suis passé de ça:

resources :comments
resources :articles do
  resources :comments
end

pour cela:

resources :comments, :only => [:destroy, :show, :edit, :update]
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

Je suppose que c'est ok d'avoir des doublons de routes, et de manquer un peu d'unité-tests. (Pourquoi tester? Parce que même si l'utilisateur ne voit jamais les doublons, vos formes peut se référer à eux, que ce soit implicitement ou par l'intermédiaire de routes nommées.) Encore, afin de minimiser les duplications inutiles, je vous recommande ceci:

resources :comments
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

Désolé pour la réponse longue. Pas beaucoup de gens sont au courant des subtilités, je pense.

57voto

Travis R Points 8935

Assurez-vous que les deux objets ont été créés dans le contrôleur: @post et @comment pour la publication, par exemple:

 @post = Post.find params[:post_id]
@comment = Comment.new(:post=>@post)
 

Alors en vue:

 <%= form_for([@post, @comment]) do |f| %>
 

Assurez-vous de définir explicitement le tableau dans le formulaire_pour, pas seulement séparé par des virgules comme ci-dessus.

35voto

jamuraa Points 2581

Vous n'avez pas besoin de faire des choses spéciales dans le formulaire. Vous venez de construire le commentaire correctement dans l'action show:

 class ArticlesController < ActionController::Base
  ....
  def show
    @article = Article.find(params[:id])
    @new_comment = @article.comments.build
  end
  ....
end
 

puis créez un formulaire dans la vue de l'article:

 <% form_for @new_comment do |f| %>
   <%= f.text_area :text %>
   <%= f.submit "Post Comment" %>
<% end %>
 

Par défaut, ce commentaire ira à l'action create de CommentsController , que vous voudrez alors probablement mettre redirect :back afin que vous soyez redirigé vers le Article page.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X