Routing acts_as_commentable form_for submission

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?

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 %>

Comment on this <%= item.class %>

<% 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

On Mon, Mar 17, 2008 at 3:48 PM, Neil C. <

Adam C. wrote:

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 %>

Comment on this <%= item.class %>

<% 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

On Mon, Mar 17, 2008 at 3:48 PM, Neil C. <

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?

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! :slight_smile:
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

On Tue, Mar 18, 2008 at 5:23 AM, Neil C. <

Adam C. wrote:

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! :slight_smile:
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

On Tue, Mar 18, 2008 at 5:23 AM, Neil C. <

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 %>

  • <%=h comment.user.login %>
  • <%= comment.comment %>

  • Posted <%= time_ago_in_words(comment.created_at) %> ago

<% end %>

Comment on this <%= object.class %>

<% 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.