Routing acts_as_commentable form_for submission

15 views
Skip to first unread message

Neil Cauldwell

unread,
Mar 17, 2008, 3:48:31 PM3/17/08
to rubyonra...@googlegroups.com
I have a Group model and a NewsItem model, and NewsItems are nested in
Groups.

I'm trying to add acts_as_commentable powered comments to the NewsItem
model, but I haven't worked out how to handle the submission of new
comments when 'comments' aren't a resource in the URL. I don't have a
CommentsController or a comments route (I was under the impression that
they aren't necessary). I do have a 'comments/_form.html.erb' which I
was going to call from the 'news_items/show.html.erb'.

Should I put a '@new_comment = Comment.new' instance variable in the
news_item_controller.rb 'show' action (or any other action that will
receive new comments), and use a form_for helper on the @new_comment in
the view? Because that the method I was expecting to take, but I just
realised I don't know how to handle 'form_for' url for the @new_comment
when the comment is being created within the group_news_item_path, i.e;


<% form_for(@new_comment) do |f| %> # where do I point this?
<%= render :partial => 'comments/form', :locals => { :f => f }%>
<% end %>

And I also realised that this approach could create a fair bit of
duplication, if I'm going to maxmise this polymorphic plugin, and re-use
the comment/_form.html.erb across the 'show' actions for many other
models - all my controller actions will need the Comment.new adding to
them. Is there a better way or something I'm missing?
--
Posted via http://www.ruby-forum.com/.

Adam Cohen

unread,
Mar 18, 2008, 12:18:26 AM3/18/08
to rubyonra...@googlegroups.com
you could create a CommentsController and use hidden form fields in a shared view to tell the comments controller which type of object the comment should be associated with.

For example:

app/views/shared/_comments.rhtml

<% item = comments %> 

<% for comment in item.comments %>
Comment posted by <%= comment.user.full_name %>
<%= comment.body %>
<% end %>

<h2>Comment on this <%= item.class %></h2>
<% form_tag(comments_path) do -%>
  <%= hidden_field_tag 'comment[commentable_id]', item.id %>
  <%= hidden_field_tag 'comment[commentable_type]', item.class %>
  <%= text_area_tag 'comment[body]', nil, :style => 'width:100%; height:100px;' %>
  <%= image_submit_tag ('post_comment_button.png') %>
<% end %>

The above would work with the polymorphic Comment class used by acts_as_commentable

Adam

Neil Cauldwell

unread,
Mar 18, 2008, 5:23:00 AM3/18/08
to rubyonra...@googlegroups.com

Thanks Adam, that's pretty much what I was hoping I could do, i.e.
keeping a generic comments view which can handle object.comments, rather
than having to define news_item.comments, user.comments etc.

However, one thing has confused me;

<% item = comments %>

Why would I want to define item as the comments?

Adam Cohen

unread,
Mar 18, 2008, 2:54:20 PM3/18/08
to rubyonra...@googlegroups.com
oh, that's just a convention that I use in partials to give the passed in object a more descriptive name.  In this case, however, 'items' isn't all that more descriptive! :)

In any case, the code I wrote is supposed to be called using the following form:

<%= render(:partial => 'views/shared/comments', :object => @product %>

and then in the 'views/shared/_comments.rhtml' file, the @product object that's passed in will be accessible by the 'comments' local variable (remember in partials that a local variable with the same name as the partial file is automatically created for you which allows you to access the passed in object).

So you could either use

<% for comment in comments.comments %> ...

which to me looks a bit confusing, or you could use


<% items = comments %>
<% for comment in item.comments %>

and of course if you wanted to be more descriptive, you could use

<% commentable_item = comments %>

which is easier to read.

Adam

Neil Cauldwell

unread,
Mar 18, 2008, 4:16:44 PM3/18/08
to rubyonra...@googlegroups.com

Thanks Adam. It works, and I'll admit to being completely baffled by the
<% item = comments %> at first. But it made sense when you explained
that the partial creates a local variable after it's own naming
convention (which in my case meant @news_item = comments = item ==
confusion). However, I opted for this;

My partial call does this;

<%= render :partial => "comments/comments", :object => @news_item %>


And my _comments.html.erb looks like this;

<% for comment in object.comments %>
<ul class="comment">
<li><%=h comment.user.login %></li>
<li><p><%= comment.comment %></p></li>
<li><p>Posted <%= time_ago_in_words(comment.created_at) %>
ago</p></li>
</ul>
<% end %>

<h2>Comment on this <%= object.class %></h2>
<% form_tag(comments_path) do -%>
<%= hidden_field_tag 'comment[user_id]', current_user.id %>
<%= hidden_field_tag 'comment[commentable_id]', object.id %>
<%= hidden_field_tag 'comment[commentable_type]', object.class %>
<%= text_area_tag 'comment[comment]', nil, :style => 'width:100%;
height:100px;' %>
<%= submit_tag 'Submit' %>
<% end %>

It seems to be working just fine. Please let me know if I'm wrong to
rely on 'object' as the means with which to access the :object =>
@news_item. It seems to make sense, though.

Reply all
Reply to author
Forward
0 new messages