Matt White
Matt White

Reputation: 117

Submitting and displaying comments to a post

I'm attempting to add basic comment functionality to posts. I am able to display the form for comments, but once saved they do not appear under the post. What I have so far:

Comment Controller

class CommentsController < ApplicationController

  def create 
    @topic = Topic.find(params[:topic_id])
    @post = Post.find(params[:post_id])
    @comment = current_user.comments.build(comment_params)
    redirect_to [@topic, @post]

  end


  private

  def comment_params
    params.require(:comment).permit(:body)
 end

end

Post Controller

class PostsController < ApplicationController

  def show
    @topic = Topic.find(params[:topic_id])
    @post = Post.find(params[:id]) 
    @comments = @post.comments 
  end

Post Show View

<h1><%= markdown_to_html @post.title %></h1>

<div class="row">
  <div class="col-md-8">
    <small>
      <%= image_tag(@post.user.avatar.tiny.url) if @post.user.avatar? %>
      submitted <%= time_ago_in_words(@post.created_at) %> ago by
      <%= @post.user.name %>
    </small>
    <p><%= markdown_to_html( @post.body) %></p>
    <h2>Comments</h2>

    <% @comments.each do |comment| %>
    <%= render partial: 'comments/comment', locals: {comment: comment} %>
    <% end %>

    <%= render partial: 'comments/form', locals: {topic: @topic, post: @post} %>

  </div>
    <div class="col-md-4">
      <% if policy(@post).edit? %>
        <%= link_to "Edit", edit_topic_post_path(@topic, @post), class: 'btn     btn-success' %>
      <% end %>
  </div>
</div>

Comment Partial

<p><%= p comment.body %></p>

Form Partial

<%= form_for [topic, post, post.comments.new] do |f| %>
<% if post.comments.new.errors.any? %>
<div class="alert alert-danger">
  <h4>There are <%= pluralize(post.errors.count, "error") %>.</h4>
  <ul>
    <%= post.comments.new.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
    <% end %>
  </ul>
</div>
<% end %>
<%= form_group_tag(post.comments.new.errors[:body]) do %>
<%= f.label :body %>
<%= f.text_area :body, rows: 1, class: 'form-control', placeholder: "Enter     comment body" %>
<% end %>
<div class="form-group">
  <%= f.submit "Save", class: 'btn btn-success' %>
</div>
<% end %>

I believe that should be all of the relevant code. The functionality seems to be there, but I must be doing something wrong with the submission process. Can someone point me in the right direction?

Thank you,

Matt

Update

I added validates :body, length: {minimum: 5}, presence: true to the post model and @comment = current_user.comments.create!(comment_params) to the comment controller.

If I submit a comment form with <5 characters I do get the 'Validation failed: Body is too short (minimum is 5 characters)' message, but if the message meets the requirements it will submit and nothing will happen.

Upvotes: 0

Views: 1307

Answers (2)

Carlos Ramirez III
Carlos Ramirez III

Reputation: 7434

Notice that you have associated the comment to a User with the following line

current_user.comments.create(...)

however nowhere do you associate the newly created comment to the Post. When you subsequently call @post.comments, you won't get the Comment back because it was never attached to that Post

Since you have access to the @post from within the CommentsController, I recommend doing something like this in your create action

def create
   # ...
   current_user.comments.create(comment_params_with_post)
   # ...
end

def comment_params_with_post
   comment_params.merge(post: @post)
end

Upvotes: 1

Maxim
Maxim

Reputation: 9961

You forget to save comment. Instead of:

@comment = current_user.comments.build(comment_params)

you should use

@comment = current_user.comments.create(comment_params)

collection.build(attributes = {}, …)

Returns one or more new objects of the collection type that have been instantiated with attributes and linked to this object through a foreign key, but have not yet been saved.

Here is more details.

Upvotes: 1

Related Questions