Using <%= render comments %> always outputs

2019-07-31 02:44发布

问题:

I'm starting to wonder if this is a bug with Rails 4, but I'm very new to rails and find myself smacking myself in the forehead eventually with most of the bugs I run in to. But I'm running into a wall on this one.

I have a Post. Posts have comments.

My Comment partial (/views/comments/_comment.html.erb)

<div class="comment-wrap">
<div class="row">
<div class="comment-meta">
    <%= comment.commenter %>
    <small><%= comment.created_at %></small>
    <%= link_to 'Destroy', [comment.post, comment], method: :delete,  confirm: 'Are you sure?', class: "tiny button radius right" %>
</div>
<div class="small-2 columns">
  <img src="http://placehold.it/50" height="50" width="50" alt="Avatar Image"/>
</div>

<div class="small-10 columns">
  <%= comment.body %>
</div>

</div>
</div>

Here is how I render that in .../views/posts/show.html.erb

<h4>Leave a comment</h4>
<%= render "comments/form" %>

<h4>Comments</h4>
<%= render @post.comments %>

Edit:Controller .../controllers/comments/comments_controller.rb

class CommentsController < ApplicationController
    def create
        @post = post.find(params[:post_id])
        @comment = @post.comments.create(comment_params)
        redirect_to post_path(@post)
    end

    def destroy
        @post = post.find(params[:post_id])
        @comment = @post.comments.find(params[:id])
        @comment.destroy
        redirect_to post_path(@post)
    end

    private

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

Edit: Posts Controller

class postsController < ApplicationController
before_action :set_post, only: [:show, :edit, :update, :destroy]

# GET /posts
# GET /posts.json
def index
  @posts = post.all
end

# GET /posts/1
# GET /posts/1.json
def show
end

# GET /posts/new
def new
  @post = post.new
end

# GET /posts/1/edit
def edit
end

# POST /posts
# POST /posts.json
def create
  @post = post.new(post_params)

  respond_to do |format|
    if @post.save
      format.html { redirect_to @post, notice: 'post was successfully created.' }
      format.json { render action: 'show', status: :created, location: @post }
    else
      format.html { render action: 'new' }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

# PATCH/PUT /posts/1
# PATCH/PUT /posts/1.json
def update
  respond_to do |format|
    if @post.update(post_params)
      format.html { redirect_to @post, notice: 'post was successfully updated.' }
      format.json { head :no_content }
    else
      format.html { render action: 'edit' }
      format.json { render json: @post.errors, status: :unprocessable_entity }
    end
  end
end

# DELETE /posts/1
# DELETE /posts/1.json
def destroy
  @post.destroy
  respond_to do |format|
    format.html { redirect_to posts_url }
    format.json { head :no_content }
  end
end

private
  # Use callbacks to share common setup or constraints between actions.
  def set_post
    @post = post.find(params[:id])
  end

  # Never trust parameters from the scary internet, only allow the white list through.
  def post_params
    params.require(:post).permit(:name, :description, :date, :address)
  end
end

This will list out the comments, but the first item is always an empty partial, with the placeholder avatar and a delete button. I've checked in rails console to see how many comments a particular post has, just to make sure there wasn't some empty record in the db, but that's not the case. Why am I getting this empty and additional partial that does not match up with a database record?

回答1:

It is because @post.comments.build in comments/form.html.erb. build() will always create a new empty object, and that comes before render(). Try replacing it with Comment.new so the empty comment won't be associated with the post.



回答2:

The issue is that the form is above the <%= render @post.comments %> so there is an empty comment when you reach the partial for all the comments, even if there's none in database, put the <%= render "comments/form" %> below to fix this.