form_for嵌套资源?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (20)

我有一个关于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的发布请求。

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

提问于
用户回答回答于

resources :articles do
  resources :comments
end

你得到如下路径:

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

路由到控制器

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

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

但部分和形式变得棘手。请注意方括号:

<%= 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

有趣的是,我刚刚了解到大多数人的单元测试实际上并没有测试所有路径。当人们遵循jamisbuck的建议时,他们最终有两种方法来获取嵌套资源。他们的单元测试通常会得到/发布到最简单:

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

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

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

我学会了这一点,因为当我从这个切换开始时,我的单元测试开始失败:

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

我猜可能有重复的路线,并错过几次单元测试。(为什么要测试?因为即使用户从未看到重复项,表单可能会隐式地或通过命名路由引用它们。)尽管如此,为了尽量减少不必要的重复,我推荐:

resources :comments
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end
用户回答回答于

一定要在控制器中创建两个对象:@post@comment该职位名称,例如:

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

然后在视图中:

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

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

扫码关注云+社区