form_for嵌套的资源

我有一个关于form_for和嵌套资源的两部分问题。 比方说,我正在写一个博客引擎,我想把一条评论和一篇文章联系起来。 我已经定义了一个嵌套的资源,如下所示:

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

评论表单位于文章的show.html.erb视图中,例如:

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

这给出了一个错误,“被调用的ID为零,这会错误地等。 我也试过了

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

正确呈现,但将f.text_area关联到文章的“文本”字段而不是注释,并在该文本区域中显示article.text属性的html。 所以我似乎也有这个错误。 我想要的是一个表单,其“submit”将在CommentsController上调用create操作,在params中带有article_id,例如对/ articles / 1 / comments的post请求。

我的问题的第二部分是,创build评论实例的最佳方式是什么? 我在ArticlesController的show动作中创build了一个@comment,所以一个注释对象将在form_for helper的作用域中。 然后在CommentsController的创build操作中,我使用从form_for传入的参数创build新的@comment。

谢谢!

特拉维斯R是正确的。 (我希望我可以upvote你。)我刚刚得到这个工作自己。 有了这些路线:

 resources :articles do resources :comments end 

你得到如下path:

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

路由到控制器

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

就像在http://guides.rubyonrails.org/routing.html#nested-resources中所说的那样,没有特殊的命名空间。;

但部分和forms变得棘手。 注意方括号:

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

最重要的是,如果你想要一个URI,你可能需要这样的东西:

 article_comment_path(@article, @comment) 

或者:

 [@article, @comment] 

http://edgeguides.rubyonrails.org/routing.html#creating-paths-and-urls-from-objects所述;

例如,在部分带有用于迭代的comment_item的集合中,

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

jamuraa说什么可以在文章的背景下工作,但它在其他方面不适用于我。

有很多关于嵌套资源的讨论,例如http://weblog.jamisbuck.org/2007/2/5/nesting-resources

有趣的是,我刚才了解到大多数人的unit testing并没有真正testing所有的path。 当人们按照jamisbuck的build议,他们最终有两种方式来获得嵌套的资源。 他们的unit testing一般会得到/发布到最简单:

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

为了testing他们可能更喜欢的路线,他们需要这样做:

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

我知道这一点,因为我的unit testing开始失败,当我从这个切换:

 resources :comments resources :articles do resources :comments end 

对此:

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

我猜没有重复的路线,并错过了几个unit testing。 (为什么要testing?因为即使用户从不看重复,表单可能会隐式地或通过命名路由引用它们。)但是,为了尽量减less不必要的重复,我推荐:

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

对不起,很长的答案。 我想,没有多less人知道这些微妙之处。

确保在控制器中创build了两个对象: @post@comment ,例如:

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

那么看:

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

一定要明确定义form_for中的数组,而不是像上面那样分隔逗号。

你不需要在表单中做特殊的事情。 您只需在show操作中正确构build注释:

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

然后在文章视图中为它创build一个表单:

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

默认情况下,这个评论将转到CommentsControllercreate操作,然后你可能想要redirect :back所以你路由回到Article页面。

    Interesting Posts