views:

546

answers:

3

I have a two-part somewhat noob question about form_for and nested resources. Let's say I'm writing a blog engine and I want to relate a comment to an article. I've defined a nested resource as follows:

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

The comment form is in the show.html.erb view for articles, underneath the article itself, for instance like this:

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

This gives an error, "Called id for nil, which would mistakenly etc." I've also tried

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

Which renders correctly but relates f.text_area to the article's 'text' field instead of the comment's, and presents the html for the article.text attribute in that text area. So I seem to have this wrong as well. What I want is a form whose 'submit' will call the create action on CommentsController, with an article_id in the params, for instance a post request to /articles/1/comments.

The second part to my question is, what's the best way to create the comment instance to begin with? I'm creating a @comment in the show action of the ArticlesController, so a comment object will be in scope for the form_for helper. Then in the create action of the CommentsController, I create new @comment using the params passed in from the form_for.

Thanks!

A: 

Include a hidden article_id form field, populated with the article's ID. On submission, the comment should set up the association all by itself.

Matchu
That sorta defeats the idea of using the nested resource path /articles/[id]/comments doesn't it?
Dave Sims
+1  A: 

Basically you are doing the same as in this guide with your second try, only thing is that you use the same field name for the post text and the comment text.

Although I do not understand why this is not working, it seems easy to change the comment field name into comment instead of text. So <%= f.text_area :comment %> is not matching with the text field of post any more.

Looking at the guide seems reasonable as well, since they tend to achieve the result you are looking for with your example.

For your second question: that is also explained in the guide. Using

@comment = Comment.new

for the new action and

@comment = Comment.new(params[:comment])
@comment.save

for the create actions, seem their way of working.

Veger
+2  A: 

You don't need to do special things in the form. You just build the comment correctly in the show action:

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

and then make a form for it in the article view:

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

by default, this comment will go to the create action of CommentsController, which you will then probably want to put redirect :back into so you're routed back to the Article page.

jamuraa