Ruby 在 Rails - 添加评论到 post

Ruby on Rails - Adding comments to post

正在尝试学习 RoR。当前由用户向帖子添加评论。到目前为止,我有一个帖子模型、评论模型和 post_comments 模型(将两者关联起来)。所以在 'rails console' 中我可以 运行:(假设我设置 p = Post.first 和 c = Comment.first)

p.comments << c

这形成了一个关联,因此它可以在控制台中工作。我似乎无法从 UI 获得形成该协会的评论。到目前为止,我正在 "comments/new" 创建评论(不确定这是否是问题所在。是否需要在 "show view" 上为 "post" 创建评论)。

这是一些代码片段

Controllers comments_controller.rb

class CommentsController < ApplicationController

def index
  @comment = Comment.all
end

def new
  @comment = Comment.new
end

def create
  @comment = Comment.new(commentParams)
  if @comment.save
    flash[:success] = "Comment successfully added"
    redirect_to comments_path(@comment)
  else
    render 'new'
  end
end

def show
  @comment = Comment.find(params[:id])
end

private

  def commentParams
    params.require(:comment).permit(:comment)
  end
end

posts_controller

class PostsController < ApplicationController
before_action :setPost, only: [:edit, :update, :show, :destroy, :sold]
before_action :requireUser, except: [:index, :show]
before_action :requireSameUser, only: [:edit, :update, :destroy, :sold]

def index
  @posts = Post.paginate(page: params[:page], per_page: 20)
end

def new
  @post = Post.new
end

def create
  @post = Post.new(postParams)
  @post.user = currentUser
  if @post.save
    flash[:success] = "Post successfully added."
    redirect_to post_path(@post)
  else
    render 'new'
  end
end

def update
  if @post.update(postParams)
    flash[:success] = "Post successfully updated."
    redirect_to post_path(@post)
  else
    render 'edit'
  end
end

def show
end

def edit
end

def sold
  @post.toggle(:sold)
  @post.save
  redirect_to post_path(@post)
end

def destroy
  @post.destroy
  flash[:danger] = "Item successfully deleted."
  redirect_to posts_path
end

private
  def postParams
    params.require(:post).permit(:title, :price, :description,   category_ids:[])
  end

  def setPost
    @post = Post.find(params[:id])
  end

  def requireSameUser
    if currentUser != @post.user and !currentUser.admin
      flash[:danger] = "You can only edit or delete your own items"
      redirect_to root_path
    end
  end
end

Models comment.rb

class Comment < ActiveRecord::Base
  belongs_to :post_comments
  belongs_to :user
  belongs_to :post
end

post_comment.rb

class PostComment < ActiveRecord::Base
  belongs_to :post
  belongs_to :comment
end

post.rb

class Post < ActiveRecord::Base
  belongs_to :user
  has_many :post_categories
  has_many :categories, through: :post_categories
  has_many :post_comments
  has_many :comments, through: :post_comments  

  validates :title, presence: true,
                length: { minimum: 4, maximum: 20 }

  validates :description, presence: true,
                      length: { maximum: 1000 }
  validates :user_id, presence: true

结束

Views posts/show.html.erb

  <p>Comments: <%= render @post.comments %></p>

这呈现了下面的部分

comments/_comment.html.erb <%= link_to comment.name, comment_path(comment) %>  

终于是新的评论页面了

comments/new.html.erb

<h1>New Comment</h1>

<%= render 'shared/errors', obj: @comment %>

<div class="row">
<div class="col-xs-12">
  <%= form_for(@comment, :html => {class: "form-horizontal", role: "form"}) do |f| %>

  <div class="form-group">
    <div class="control-label col-sm-2">
      <%= f.label :comment %>
    </div>

    <div class="col-sm-8">
      <%= f.text_area :comment, rows: 3, class: "form-control", placeholder: "Please enter a comment", autofocus: true %>
    </div>
  </div>

  <div class="form-group">
    <div class="center col-sm-offset-1 col-sm-10">
      <%= f.submit class: "btn btn-primary btn-lg" %>
    </div>
  </div>
<% end %>

如有任何帮助,我们将不胜感激。

更新

Log

Started GET "/posts/2" for ::1 at 2016-01-15 12:39:55 +0000
Processing by PostsController#show as HTML
Parameters: {"id"=>"2"}
[1m[36mPost Load (0.1ms)[0m  [1mSELECT  "posts".* FROM "posts" WHERE    "posts"."id" = ? LIMIT 1[0m  [["id", 2]]
[1m[35mUser Load (0.1ms)[0m  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 1]]
[1m[36m (0.1ms)[0m  [1mSELECT COUNT(*) FROM "posts" WHERE "posts"."user_id" = ?[0m  [["user_id", 1]]
[1m[35mCategory Exists (0.1ms)[0m  SELECT  1 AS one FROM "categories"    INNER JOIN "post_categories" ON "categories"."id" =  "post_categories"."category_id" WHERE "post_categories"."post_id" = ?  LIMIT 1  [["post_id", 2]]
[1m[36mCategory Load (0.0ms)[0m  [1mSELECT "categories".* FROM "categories" INNER JOIN "post_categories" ON "categories"."id" = "post_categories"."category_id" WHERE "post_categories"."post_id" = ?[0m  [["post_id", 2]]
Rendered categories/_category.html.erb (0.2ms)
[1m[35mComment Load (0.1ms)[0m  SELECT "comments".* FROM "comments"  WHERE "comments"."post_id" = ?  [["post_id", 2]]
Rendered comments/_comment.html.erb (0.1ms)
Rendered posts/show.html.erb within layouts/application (6.5ms)
[1m[36mCategory Load (0.1ms)[0m  [1mSELECT "categories".* FROM "categories"[0m
Rendered layouts/_navigation.html.erb (0.9ms)
Rendered layouts/_messages.html.erb (0.1ms)
Rendered layouts/_footer.html.erb (0.1ms)
Completed 200 OK in 52ms (Views: 50.3ms | ActiveRecord: 0.5ms)

由于评论只能属于单个 post,因此您不需要关联 table (post_comments)。你只需要一个简单的 one-to-many 关系。

您的 post 评论将是:

class Post < ActiveRecord::Base
  has_many :comments
  ...
end

评论会是这样的:

class Comment < ActiveRecord::Base
  belongs_to :post
  ...
end

只需确保 comments table 中有必要的 post_id 列(您可以检查 db/schema.rb 文件)。如果缺少,您可以使用以下迁移来添加它:

class AddPostIdToComments < ActiveRecord::Migration
  def change
    add_column :comments, :post_id, :integer
    add_index  :comments, :post_id
  end
end

您还需要确保在某处保留对 post 的引用,每当用户尝试对 post 创建评论时。您可以将其添加到 comments/new.html.erb 模板的隐藏字段中。在通过 URL.

传递后,您可以在 PostsController 的 new 操作中设置隐藏字段

因此,在您的 posts/show.html.erb 模板中,您将拥有:

<%= link_to "Add Comment", new_comment_path(post_id: @post.id) %>

在您的 new 操作中,在 PostsController:

def new
  @comment = Comment.new(post_id: params[:post_id])
end

最后,您表单中的隐藏字段将是:

<%= f.hidden_field :post_id %>

最后,将 post_id 参数添加到 CommentsController 中允许的参数列表中。

而不是

在您的新操作中,在 PostsController 中:

def new
    @comment = Comment.new(post_id: params[:post_id])
end

您可以在表单视图中使用它

<%= form.hidden_field :post_id, value: "#{params[:post_id]}" %>