Forum: Ruby on Rails form_for - Child object - how to set parent id

Posted by D L (Guest)
on 2006-09-07 10:01
Hi All,

I am just trying to learn ruby/rails so please don't flame me if this is 
a stupid question.

As a learning project I decided to create my own blog using ROR. I have 
created a controller that shows paged blog entries, and below each blog 
is a list of comments along with a form alowing the user to add a new 
comment.

To create the form for the comment entry I used form_for which worked 
fine. However I need to somehow set the blog Id on the comment that is 
entered into that form. Here is the rhtml for the list:

<% for blog in @blogs %>
    <span class="blog_header"><%=h blog.title %></span>
    <span class="blog_date"><%=h blog.date_entered.to_s(:long) %></span>
    <span class="blog_body"><%=h blog.body %></span>
    <div class="blog_comments">
        <span class="blog_comments_count"><%=h 
pluralize(blog.comments.size,"comments") %></h2>
        <% for comment in blog.comments %>
            <div class="comment">
            <div class="comment_name"><%=h comment.name %> said:</div>
            <div class="comment_body"><%=h comment.body %></div>
            <div class="comment_date"><%=h 
comment.date_entered.to_s(:long) %></div>
            </div>
        <% end %>
        <div class="comment_form" >
            <%= error_messages_for 'comment' %>
            <fieldset>
            <legend>Add your comment:</legend>
            <% form_for :comment, :url => { :action => :add_comment } do 
|form| %>
                <p>
                    <label for="name" >Name:</label>
                    <%= form.text_field :name %>
                </p>
                <p>
                    <label for="email" >E-Mail:</label>
                    <%= form.text_field :email %>
                </p>
                <p>
                    <label for="Comment" >Comments:</label>
                    <%= form.text_area :body, :rows => 3, :cols => 40 %>
                </p>
                <%= submit_tag "Add Comment" , :class => "submit" %>
            <% end %>
            </fieldset>
      </div>
    </div>
  </tr>
<% end %>


So you can see I have a form for block to handle the comments entry - 
but if I have multiple blogs on a single page how can I specify that 
this particular comment relates to blog X? If I only have one blog per 
page I can get away with storing the blog id in the session, but this 
seems a bit messy.

If I have not made this clear please let me know and I will try to 
clarify.

Thanks,

D.
Posted by D L (Guest)
on 2006-09-07 15:07
Anyone got any ideas on this - please?
Posted by Jeff Cohen (jeff)
on 2006-09-07 16:47
(Received via mailing list)
D L wrote:
> So you can see I have a form for block to handle the comments entry -
> but if I have multiple blogs on a single page how can I specify that
> this particular comment relates to blog X? If I only have one blog per
> page I can get away with storing the blog id in the session, but this
> seems a bit messy.
>

Hi D L,

(Welcome to Rails, by the way).

The key is to learn about how to specify the relationships between your
models.  In your comment model, indicate that it's parent object is a
Blog:

class Comment < ActiveRecord::Base
 ...
 belongs_to :blog

end

Now, anytime you have a Comment object, you can use comment.blog to
"get back" to the parent blog object.

Does this help?  If I misunderstood the question somehow, let me know.

Jeff
www.softiesonrails.com
Posted by D L (Guest)
on 2006-09-07 17:39
Hi Jeff,

Thanks for the response, but I think you have misunderstood my question.

I understand how to link the objects and have done so with the 
directives you mention (has_many, belongs_to etc). If I am working in 
the ruby debugger/console I can add comments to my blogs etc using 
syntax like blog1.comments.create(:body => "A Comment") and it all gets 
saved to the DB fine.

My problem is that I have a form in the view to create a new comment. 
Again this works up to a point - the new comment is generated from the 
params with now problems. However I intend to have multiple form_for 
blocks within this view - one per blog/post to allow the user to add a 
comment to any blog/post.
The problem is that I can not see any way to set the BlogId (parent) on 
the comment. So I have code in my controller that looks like this:

def add_comment
     @comment = Comment.new(params[:comment])
     @comment.blog_id = ????????? <- Where do I get this from???
     if @comment.save
        flash[:notice] = "Thank you for your comment"
     end
     list
     render :action => 'list'
end

So - how do I know which blog/post this comment relates to? The form_for 
does not seem to provide a way to add another parementer which I can 
pick up for the blog id. If I was only displaying one comment form per 
page this would not be a problem because I could just put the blogid 
into the session, and use it when the user clicks submit - but I have 
more than one blog per page so I am stuck.

Any ideas?

Thanks,

D.


Jeff Cohen wrote:
> D L wrote:
>> So you can see I have a form for block to handle the comments entry -
>> but if I have multiple blogs on a single page how can I specify that
>> this particular comment relates to blog X? If I only have one blog per
>> page I can get away with storing the blog id in the session, but this
>> seems a bit messy.
>>
> 
> Hi D L,
> 
> (Welcome to Rails, by the way).
> 
> The key is to learn about how to specify the relationships between your
> models.  In your comment model, indicate that it's parent object is a
> Blog:
> 
> class Comment < ActiveRecord::Base
>  ...
>  belongs_to :blog
> 
> end
> 
> Now, anytime you have a Comment object, you can use comment.blog to
> "get back" to the parent blog object.
> 
> Does this help?  If I misunderstood the question somehow, let me know.
> 
> Jeff
> www.softiesonrails.com
Posted by Steve Ross (cwd)
on 2006-09-07 18:45
(Received via mailing list)
Have you thought about using Ajax to create the form on the fly, thereby
making the ownership of the comment clearer?



D L-3 wrote:
> syntax like blog1.comments.create(:body => "A Comment") and it all gets 
> def add_comment
> does not seem to provide a way to add another parementer which I can 
> 
>> Hi D L,
>> 
> 
> -- 
> Posted via http://www.ruby-forum.com/.
> 
> > 
> 
> 

--
View this message in context: 
http://www.nabble.com/form_for---Child-object---how-to-set-parent-id-tf2231865.html#a6193614
Sent from the RubyOnRails Users forum at Nabble.com.
Posted by Max Muermann (Guest)
on 2006-09-08 02:46
(Received via mailing list)
> >      render :action => 'list'
> > end
> >

From your view code I assume that you create one blank comment in your
controller and are trying to reuse that?

A better way may be to add a new_comment method to the blog model:

def new_comment
  Comment.new( :blog=>self )
end

and then use

<%= form_for :comment, blog.new_comment, :url=>... %>
<%= form.hidden_field :blog_id %>

If you want to stick with the one-template-comment approach, do 
something like

<%= hidden_field :comment, :blog_id, :value=>blog.id %>

Cheers,
Max
Posted by D L (Guest)
on 2006-09-08 10:04
Max Muermann wrote:
>> >      render :action => 'list'
>> > end
>> >
> 
> From your view code I assume that you create one blank comment in your
> controller and are trying to reuse that?
> 
> A better way may be to add a new_comment method to the blog model:
> 
> def new_comment
>   Comment.new( :blog=>self )
> end
> 
> and then use
> 
> <%= form_for :comment, blog.new_comment, :url=>... %>
> <%= form.hidden_field :blog_id %>
> 
> If you want to stick with the one-template-comment approach, do 
> something like
> 
> <%= hidden_field :comment, :blog_id, :value=>blog.id %>
> 
> Cheers,
> Max

Hi Max - Thanks for your response - the hidden field idea looks like a 
good way round my issue.

I did find another way around it - I replaced the form_for tag with:

<%= form_tag :action => :add_comment, :id => blog   %>
        <p>
            <label for="name" >Name:</label>
            <%= text_field "comment", "name"  %>
        </p>
        etc etc

And my controller code now looks like:

  def add_comment
     @comment = Comment.new(params[:comment])
     @comment.blog_id = params[:id]
     if @comment.save

Are there any gotcha's with this? Should I do it the way you suggest, 
rather than have I have done it?

Cheers,

D.
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.