首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >具有嵌套资源的form_for

具有嵌套资源的form_for
EN

Stack Overflow用户
提问于 2010-01-10 03:50:38
回答 3查看 106.6K关注 0票数 129

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

代码语言:javascript
复制
map.resources :articles do |articles|
    articles.resources :comments
end

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

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

这会产生一个错误,“为nil调用id,这将错误地依此类推。”我也试过

代码语言:javascript
复制
<% form_for @article, @comment do |f| %>

它正确地呈现,但将f.text_area与文章的“文本”字段而不是评论的字段相关联,并在该文本区域中显示article.text属性的html。所以我似乎也错了。我想要的是一个表单,它的'submit‘将调用CommentsController上的create操作,参数中有一个评论,例如一个对/ article_id /1/comments的post请求。

我的问题的第二部分是,创建comment实例的最佳方法是什么?我在ArticlesController的显示操作中创建了一个@comment,因此form_for帮助器的作用域中将有一个comment对象。然后,在CommentsController的create操作中,我使用从form_for传入的参数创建了新的@comment。

谢谢!

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-01-06 13:08:29

特拉维斯·R是对的。(我希望我能给你加分。)我自己才弄好的。使用这些路由:

代码语言:javascript
复制
resources :articles do
  resources :comments
end

您将获得如下路径:

代码语言:javascript
复制
/articles/42
/articles/42/comments/99

路由至以下位置的控制器

代码语言:javascript
复制
app/controllers/articles_controller.rb
app/controllers/comments_controller.rb

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

但是偏导数和形式变得很棘手。请注意方括号:

代码语言:javascript
复制
<%= form_for [@article, @comment] do |f| %>

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

代码语言:javascript
复制
article_comment_path(@article, @comment)

或者:

代码语言:javascript
复制
[@article, @comment]

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

例如,在带有为迭代提供的comment_item的集合partial中,

代码语言:javascript
复制
<%= link_to "delete", article_comment_path(@article, comment_item),
      :method => :delete, :confirm => "Really?" %>

jamuraa所说的可能在文章的上下文中起作用,但在其他方面对我不起作用。

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

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

代码语言:javascript
复制
# POST /comments
post :create, :comment => {:article_id=>42, ...}

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

代码语言:javascript
复制
# POST /articles/42/comments
post :create, :article_id => 42, :comment => {...}

我之所以了解到这一点,是因为当我切换到以下代码时,我的单元测试开始失败:

代码语言:javascript
复制
resources :comments
resources :articles do
  resources :comments
end

要这样做:

代码语言:javascript
复制
resources :comments, :only => [:destroy, :show, :edit, :update]
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

我想有重复的路由和错过几个单元测试是可以的。(为什么要测试?因为即使用户从未看到过副本,您的表单也可能会隐式或通过命名路由引用它们。)不过,为了减少不必要的重复,我建议这样做:

代码语言:javascript
复制
resources :comments
resources :articles do
  resources :comments, :only => [:create, :index, :new]
end

很抱歉回答得太长了。我认为,没有多少人意识到其中的微妙之处。

票数 232
EN

Stack Overflow用户

发布于 2010-12-27 15:36:00

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

代码语言:javascript
复制
@post = Post.find params[:post_id]
@comment = Comment.new(:post=>@post)

然后在视图中:

代码语言:javascript
复制
<%= form_for([@post, @comment]) do |f| %>

请确保在form_for中显式定义数组,而不是像上面那样仅使用逗号分隔。

票数 55
EN

Stack Overflow用户

发布于 2010-01-10 08:08:52

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

代码语言:javascript
复制
class ArticlesController < ActionController::Base
  ....
  def show
    @article = Article.find(params[:id])
    @new_comment = @article.comments.build
  end
  ....
end

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

代码语言:javascript
复制
<% form_for @new_comment do |f| %>
   <%= f.text_area :text %>
   <%= f.submit "Post Comment" %>
<% end %>

默认情况下,此注释将转到CommentsControllercreate操作,然后您可能希望将redirect :back放入其中,以便路由回Article页面。

票数 35
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2034700

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档