6

I have a model that I want to be commentable. I am having difficulty creating a form on my model's 'show' view that will allow comments to be created. I am not finding any good or useful examples. Can anyone point me to or show me an example of how to do this?

Example:

A simple blog application. I have a model called Post. It is commentable. So on the 'show' view I want to show a Post and, at the bottom, have the fields that, when completed and submitted, create a new comment associated with the post and put it in the database.

Sounds straightforward and I have it working so I can display comments that I have seeded. I just can't get a form to work to put new ones in. Any help is appreciated.

NJ.
  • 2,155
  • 6
  • 26
  • 35

3 Answers3

28

Lets assume a Post model. Make sure, you have

class Post < ActiveRecord::Base
acts_as_commentable
end

then in the view of say Post#show

  <%= form_tag "/posts/add_new_comment" do %>
    <%= hidden_field_tag "id", post.id %>
    <%= text_area_tag "comment[comment]" %>
    <%= submit_tag "Post Comment" %>
  <% end %>

then in the PostController

  def add_new_comment
    post = Post.find(params[:id])
    post.comments << Post.new(params[:comment])
    redirect_to :action => :show, :id => post
  end

and in routes.rb

  match "/posts/add_new_comment" => "posts#add_new_comment", :as => "add_new_comment_to_posts", :via => [:post]

Hope this gets u up and running.

Kunday
  • 1,041
  • 6
  • 9
3

This is very, very basic stuff and you clearly need some better structure and approach to your learning. Buying a book, such as Agile Web Development with Rails, is the only real way to learn, otherwise you'll wander from problem to problem without ever actually learning anything well.

Say you have a post that you want to comment.

#routes.rb
map.resources :posts do |post|
  post.resources :comments
end

#post_controller.rb
def show
  @post.find params[:id]
  @comment = @post.comments.new
end

#posts/show.html.erb
<%- form_for [@post, @comment] do |f|-%>
  <%= f.text_area :body -%>
  <%= f.submit -%>
<%- end -%>

#comments_controller
def create
  @post = @post.find params[:post_id]
  @comment = @post.comments.new params[:comment]
  if @comment.save
    redirect_to @post
mark
  • 10,316
  • 6
  • 37
  • 58
  • I appreciate the info and your criticism. I will look into that book. I guess what was throwing me off here was that i was using one model from with the show view of another. I guess it isn't as difficult as I assumed it to be. Thanks again. – NJ. Nov 03 '10 at 17:33
  • I think I am almost there but the route is breaking. How would the map.resources statement translate into the Rails 3 way of routing? The changes in Rails 3 is a lot of what is giving me trouble. – NJ. Nov 03 '10 at 18:56
  • Hey NJ. Sorry I didn't get back to you. I haven't used rails 3 yet so don't know of the routing changes. If you include them here I'll put them in my answer in case it helps anyone else. – mark Nov 05 '10 at 09:00
2

This is an old question, but I want to throw in my solution as well as the gem's README is still unhelpful after all these years. It builds upon @Kunday's answer. The following will be a tutorial to use the act_as_commentable gem to...

  1. Allow users to create comments under each post.
  2. Show all comments belonging to a post.

This assumes that you already have a working "blog", whether it be pictures or posts. Install gem, then run rails g comment to get started.

Allow users to create comments under each post.

First, inside the model that you want to use commentable gem, add the following line as suggested in the gem's README.

class Post < ActiveRecord::Base 
  acts_as_commentable
end

Then create a new comment controller with the create action. Please note that the :authenticate_user! is part of devise which is a gem for creating easy authentication. current_user is also part of devise as a helper. It is needed if you want to display the user's name/email under the comment body.

class CommentsController < ApplicationController
  before_action :authenticate_user!

  def create
    post = Post.find_by(id: params[:id])
    comment = post.comments.build(comment_params)
    comment.user = current_user

    if comment.save
      flash[:notice] = "Comment has been created."
      redirect_to post
    else
      flash[:alert] = "Comment has not been created."
    end
  end

  private    
    def comment_params
      params.permit(:comment)
    end
end

Next, set up the routes. It's just this. This means that when someone sends a post request to comments, we will run to create action inside the comments controller.

post 'comments' => 'comments#create', as: "create_comment"

The as: "create_comment" gives it an alias, so you can do create_comment_path. Now, on the show view of Post, we'll add the form. The divs will help you add css.

<div class="comment-section">
  <%= form_tag create_comment_path, method: "post" do %>
    <%= hidden_field_tag "id", @post.id %>
      <%= text_area_tag :comment %>
      <%= submit_tag "Submit" %>
    <% end %>
</div>

Now to show each comment under the Post show view.

The divs will help you add css, comment.user.name will work if your User class has a name column. Else, change it to email or whatever identifier you choose to use.

<div class="comment_list">
  <% @comments.each do |comment| %>
    <%= comment.comment %> <br>
      <%= comment.user.name %> <br>
        <br>
    <% end %>
</div>

And finally, in order for @comments to exist in the show page, go to your Post controller, and under show, add the following:

  def show
    @post = Post.find_by(id: params[:id])
    @comments = @post.comments.all
  end

This should be good for the requirements. Good luck.

Ka Mok
  • 1,937
  • 3
  • 22
  • 47
  • This post just saved me. The instructions on the gem page don't mention that a user has to be assigned to a comment before saving it, and I was getting an error. Thanks! – Grambo Feb 13 '21 at 23:48