form_for con recursos nesteds

Tengo una pregunta de dos partes sobre form_for y los recursos nesteds. Digamos que estoy escribiendo un motor de blog y quiero relacionar un comentario con un artículo. Definí un recurso nested de la siguiente manera:

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

El formulario de comentarios se encuentra en la vista show.html.erb para artículos, debajo del artículo en sí, por ejemplo, como este:

  "articles/article" %>     

Esto da un error, “Identificación llamada para nulo, que erróneamente, etc.” También intenté

  

Que se representa correctamente pero relaciona f.text_area con el campo ‘texto’ del artículo en lugar de los comentarios, y presenta el html para el atributo article.text en ese área de texto. Así que parezco tener esto mal también. Lo que quiero es un formulario cuyo ‘enviar’ llamará a create action en CommentsController, con un article_id en los params, por ejemplo, una solicitud posterior a / articles / 1 / comments.

La segunda parte de mi pregunta es, ¿cuál es la mejor manera de crear la instancia de comentario para empezar? Estoy creando un @comment en la acción de mostrar de ArticlesController, por lo que un objeto de comentario estará en el scope de form_for helper. Luego, en la acción create del CommentsController, creo un nuevo comentario utilizando los parámetros pasados ​​desde form_for.

¡Gracias!

Travis R es correcto. (Ojalá pudiera votarte). Acabo de hacer esto yo mismo. Con estas rutas:

 resources :articles do resources :comments end 

Obtienes caminos como:

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

enrutado a los controladores en

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

tal como dice en http://guides.rubyonrails.org/routing.html#nested-resources , sin espacios de nombres especiales.

Pero los parciales y las formas se vuelven complicadas. Tenga en cuenta los corchetes:

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

Lo más importante, si desea un URI, puede necesitar algo como esto:

 article_comment_path(@article, @comment) 

Alternativamente:

 [@article, @comment] 

como se describe en http://edgeguides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects

Por ejemplo, dentro de una colección parcial con comment_item suministrado para la iteración,

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

Lo que dice jamuraa puede funcionar en el contexto del Artículo, pero no funcionó para mí de varias otras maneras.

Hay una gran cantidad de discusiones relacionadas con los recursos nesteds, por ejemplo, http://weblog.jamisbuck.org/2007/2/5/nesting-resources

Curiosamente, aprendí que las pruebas unitarias de la mayoría de las personas no están probando todos los caminos. Cuando las personas siguen la sugerencia de jamisbuck, terminan con dos formas de obtener recursos nesteds. Sus pruebas unitarias generalmente llegarán / publicarán al más simple:

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

Para probar la ruta que prefieran, deben hacerlo de esta manera:

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

Aprendí esto porque mis pruebas unitarias comenzaron a fallar cuando cambié de esto:

 resources :comments resources :articles do resources :comments end 

a esto:

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

Supongo que está bien tener rutas duplicadas y perder algunas pruebas unitarias. (¿Por qué probar? Porque incluso si el usuario nunca ve los duplicados, sus formularios pueden referirse a ellos, ya sea implícitamente o mediante rutas con nombre.) Sin embargo, para minimizar la duplicación innecesaria, recomiendo esto:

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

Perdón por la respuesta larga. Creo que no mucha gente conoce las sutilezas.

Asegúrese de tener ambos objetos creados en el controlador: @post y @comment para la publicación, por ejemplo:

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

Entonces a la vista:

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

Asegúrese de definir explícitamente la matriz en form_for, no solo coma separada como lo hizo anteriormente.

No necesita hacer cosas especiales en el formulario. Usted acaba de construir el comentario correctamente en la acción de mostrar:

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

y luego hacer un formulario para ello en la vista del artículo:

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

de forma predeterminada, este comentario irá a la acción de create de CommentsController , que luego probablemente quiera redirect :back para que vuelva a la página Article .