具有嵌套资源的form_for

Dav*_*ims 118 ruby-on-rails form-for nested-resources

我有一个关于form_for和嵌套资源的两部分问题.假设我正在编写一个博客引擎,我想将评论与文章联系起来.我已经定义了一个嵌套资源,如下所示:

map.resources :articles do |articles|
    articles.resources :comments
end
Run Code Online (Sandbox Code Playgroud)

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

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

这给出了一个错误,"为nil调用id,这会错误等等".我也试过了

<% form_for @article, @comment do |f| %>
Run Code Online (Sandbox Code Playgroud)

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

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

谢谢!

cdu*_*001 221

特拉维斯R是对的.(我希望我可以赞成你.)我自己就这样做了.有了这些路线:

resources :articles do
  resources :comments
end
Run Code Online (Sandbox Code Playgroud)

你得到的路径如下:

/articles/42
/articles/42/comments/99
Run Code Online (Sandbox Code Playgroud)

路由到控制器

app/controllers/articles_controller.rb
app/controllers/comments_controller.rb
Run Code Online (Sandbox Code Playgroud)

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

但局部和形式变得棘手.注意方括号:

<%= form_for [@article, @comment] do |f| %>
Run Code Online (Sandbox Code Playgroud)

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

article_comment_path(@article, @comment)
Run Code Online (Sandbox Code Playgroud)

或者:

[@article, @comment]
Run Code Online (Sandbox Code Playgroud)

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?" %>
Run Code Online (Sandbox Code Playgroud)

jamuraa所说的可能在文章的背景下起作用,但它在各种其他方面对我不起作用.

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

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

# POST /comments
post :create, :comment => {:article_id=>42, ...}
Run Code Online (Sandbox Code Playgroud)

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

# POST /articles/42/comments
post :create, :article_id => 42, :comment => {...}
Run Code Online (Sandbox Code Playgroud)

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

resources :comments
resources :articles do
  resources :comments
end
Run Code Online (Sandbox Code Playgroud)

对此:

resources :comments, :only => [:destroy, :show, :edit, :update]
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end
Run Code Online (Sandbox Code Playgroud)

我想有重复的路线,并错过一些单元测试是可以的.(为什么测试?因为即使用户从未看到重复项,您的表单也可以隐式或通过命名路由引用它们.)尽管如此,为了最大限度地减少不必要的重复,我建议:

resources :comments
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end
Run Code Online (Sandbox Code Playgroud)

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


Tra*_*der 52

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

@post = Post.find params[:post_id]
@comment = Comment.new(:post=>@post)
Run Code Online (Sandbox Code Playgroud)

然后在视图中:

<%= form_for([@post, @comment]) do |f| %>
Run Code Online (Sandbox Code Playgroud)

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


jam*_*raa 34

您不需要在表单中执行特殊操作.您只需在show动作中正确构建注释:

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

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

<% form_for @new_comment do |f| %>
   <%= f.text_area :text %>
   <%= f.submit "Post Comment" %>
<% end %>
Run Code Online (Sandbox Code Playgroud)

默认情况下,此注释将转到您可能想要放入的create操作CommentsController,redirect :back因此您将被路由回Article页面.

  • 我不得不使用`form_for([@ article,@ new_comment])`格式.我想这是因为我正在展示`comments#new`的观点,而不是`article#new_comment`.我想在`article#new_comment`中Rails是否足够聪明,可以找出嵌套注释对象的内容,这样你就不必指定它了? (10认同)