2. Self directed lesson for setting up comments

You can easily setup comments for post like the same way as post.

The basic steps include

1. Generate the comment model and controller

2. add fields to comment table and run the migration

3. set up the database relations between the Comment model, the User model, and the Post model.

# in user.rb
has_many :comments

# in post.rb
has_many :comments

# in comment.rb
belongs_to :user
belongs_to :post

4. add routes for comments

resources :posts do
  resources :comments
end

5. set up the backend logic so that users can post comments to photos.

The comments controller should look like this

class CommentsController < ApplicationController
  def create
    @post = Post.find(params[:post_id])
    @comment = @post.comments.create(comment_params.merge(user_id: current_user.id))
    if @comment.valid?
      redirect_to root_path
    else
      flash[:alert] = "Invalid params"
      redirect_to root_path
    end
  end

  private

  def comment_params
    params.require(:comment).permit(:text, :post_id)
  end
end

The thing that is new is .merge(user_id: current_user.id). Before, we did things like current_user.posts.create(post_params) which hooked up the post and the current_user. Here, since the comment belongs to a Post and a User as well, we can't chain the method like this: current_user.@post.comments.create.

However, we can use this merge method to merge in the user_id and set it to current_user.id. That's what .merge(user_id: current_user.id) is doing right here.

6. Don't forget to add validations as well.

Make sure that we get valid data to be saved into our database. Specifically, we need to make sure that the text, post_id, and user_id is present.

7. Create the comments form so that users can post comments to photos.

In index.html.erb file of posts. Inside our loop, let's create a form for each instance of a post. The form will look like this:

<%= simple_form_for Comment.new, url: post_comments_path(post), method: :post do |f| %>
  <%= f.input :text, label: 'Comment', placeholder: 'Add a comment...', label_html: {class: 'mt-4'}, input_html: {class: 'mt-2 md:max-w-[50%]'} %>
  <%= f.submit 'Post', class: 'text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800' %>
<% end %>

8. Display all of the comments for each post above the form. You can do this with a simple loop. Try to do this yourself and see how far you get!

What you need to do:

  • Display the name of the user that posted the comment
  • Display the comment text

9 Set up the backend logic for deleting comments. It's very similar to what we did for posts.

In our comments_controller.rb, let's add a destroy method that will delete a comment and then redirect the user to the root_path.

The code now should look like this

<% post.comments.each do |comment| %>
  <div class="px-2">
    <p class="mb-3"><%= comment.user.email.split('@').first %> <%= comment.text %></p>
    <%= link_to 'Delete', post_comment_path(post_id: post.id, id: comment.id), method: :delete, class: 'text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 focus:outline-none dark:focus:ring-red-800' %>
  </div>
<% end %>
Lesson list