【问题标题】:Why does database rollback on creating a new comment? Ruby on Rails为什么数据库在创建新评论时会回滚? Ruby on Rails
【发布时间】:2018-07-14 18:44:45
【问题描述】:

我有一个问题在过去一周内一直在尝试解决。我正在尝试使用closure_tree gem 创建一个嵌套评论系统。我终于想出了如何将 parent_id 作为参数的一部分传递,现在整个散列已正确填充到服务器日志中,但是每次我尝试保存回复时,我的日志都会在保存评论之前显示回滚。所有 cmets 都属于 wad。

这是我的评论控制器中的相关代码:

class CommentsController < ApplicationController
    before_action :find_wad
    before_action :find_comment, only: [:destroy, :edit, :update, :comment_owner, :comment_params]
    before_action :comment_owner, only: [:destroy, :edit, :update]

    def create
        if params[:comment][:parent_id].to_i > 0
            parent = Comment.find_by(params[:comment].delete(:parent_id))
            @comment = parent.children.build(comment_params)
            parent_id = parent.id

        else
            @comment = @wad.comments.build(comment_params)
            parent_id = @comment.id
        end
            @comment.user_id = current_user.id
            @comment.save

        if @comment.save
            flash[:success] = 'Your comment was successfully added!'
            redirect_to wad_path(@wad)
        else
            render 'new'
        end
    end


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

private

    def find_wad
        @wad = Wad.find(params[:wad_id])
    end

    def find_comment
        @comment = @wad.comments.find_by(params[:id])
    end

    def comment_params
        params.require(:comment).permit(:content, :wad_id, :user_id, :parent_id)
    end


    def comment_owner
        unless current_user.id == @comment.user_id
            flash[:notice] = "Action Restricted"
            redirect_to @wad

        end
    end
end

这是我在 cmets 视图的 _reply 部分中使用的回复表单:

<%= form_for([@wad, @comment]) do |f| %>
<%= f.hidden_field :parent_id %>
<%= f.text_area :content %>
<%= f.submit %>

<% end %>

当我尝试输入回复评论时,服务器日志中会发生以下情况:

Started POST "/wads/1/comments" for 127.0.0.1 at 2018-02-04 14:20:04 -0800
Processing by CommentsController#create as HTML
  Parameters: {"utf8"=>"✓", "authenticity_token"=>"LYk07p6h3+RJ6kfx+rixaGJ0a56XPt29v7mFFbCQ+H+Gr5PjzzkrWOWfShCuKwFEIShwEz8Om7IsLjGI3hN0vw==", "comment"=>{"parent_id"=>"136", "content"=>"elmle"}, "commit"=>"Create Comment", "wad_id"=>"1"}
  Wad Load (0.2ms)  SELECT  "wads".* FROM "wads" WHERE "wads"."id" = ? ORDER BY "wads"."created_at" DESC LIMIT ?  [["id", 1], ["LIMIT", 1]]
  Comment Load (0.2ms)  SELECT  "comments".* FROM "comments" WHERE (136) LIMIT ?  [["LIMIT", 1]]
  User Load (0.3ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  begin transaction
  CACHE User Load (0.0ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = ? LIMIT ?  [["id", 1], ["LIMIT", 1]]
   (0.1ms)  rollback transaction
   (0.1ms)  begin transaction
   (0.0ms)  rollback transaction

在我的任何模型中都没有 attr_accessor - 只有正确定义的 has_many 和 belongs_to 关系。有人知道为什么会这样吗?

Wad 模型:

class Wad < ApplicationRecord
     acts_as_votable
      belongs_to :user
      has_many :comments, dependent: :destroy
      default_scope -> { order(created_at: :desc) }
      validates :user_id, presence: true
      validates :category, presence: true
      validates :long_form, presence: true, length: { maximum: 1000 }
      validates :short_form, presence: true, length: { maximum: 140 }
      validates :problem_state, presence: true, length: { maximum: 50 }
    end

评论模型:

class Comment < ApplicationRecord
  acts_as_tree order: 'created_at DESC'
  belongs_to :wad
  belongs_to :user
end

用户模型的相关部分:

class User < ApplicationRecord
  acts_as_voter
  has_many :wads, dependent: :destroy
  has_many :comments

【问题讨论】:

  • 好像找不到用户。
  • else 块中,当您检查if @comment.save 时,您应该阅读.errors.full_messages 以了解它失败的原因。您可以将它们分配给实例变量并在new 模板中显示它们。
  • 感谢@maxpleaner。错误是 ["Wad must exist"],但是 wad #1 确实存在并且 wad_id 存在于 params 中?
  • 顺便说一句,@comment.save 的重复是没有意义的,因为在这种情况下你要进行两次交易
  • @O.Don 你打电话给Comment.new,只是传递了一个parent_id。尝试将 wod 传递给该构造函数。除此之外,由于我不熟悉此宝石,因此我没有想法。

标签: ruby-on-rails ruby rubygems


【解决方案1】:

据我所知,参数是:

{"comment"=>{"parent_id"=>"136", "content"=>"elmle"}, "commit"=>"Create Comment", "wad_id"=>"1"}

在这种情况下,我们将达到这个条件:

if params[:comment][:parent_id].to_i > 0
  parent = Comment.find_by(params[:comment].delete(:parent_id))
  @comment = parent.children.build(comment_params)
  parent_id = parent.id

params["comment"] 创建的新评论对象仅包含 parent_idcontent。 因此,正在创建新对象而没有 belongs_to 所需的 wad_id 键,您可能在模型中拥有该键

【讨论】:

  • 谢谢,我明白你在说什么。如果这是一个不好的问题,请原谅我,但为什么 params["comment"] 没有得到 wad_id,即使 wad_id 在 comment_params 中?
  • @O.Don 它在params.require(:comment).permit(:content, :wad_id, :user_id, :parent_id) 中,而您的"wad_id"comment 散列之外params 变量
  • 但我不明白为什么它在外面或者comment_params和“params变量的评论哈希”有什么区别?
  • @O.Don comment_params 等于 params[:comment]。现在让我们从日志中查看您的参数。 wad_idparams[:comment] 之外,它在params[:wad_id] 中,但不在params[:comment][:wad_id]
  • 要解决您的问题,您需要将您的:wad_id 放在参数的:comment 部分中,或者从设计的角度做@comment.wad_id = params[:wad_id] 这不是很好。
【解决方案2】:

当你使用时

Comment.find_by(params[:comment].delete(:parent_id))

您从 params[:comment] 的哈希中删除您的 :parent_id,您需要从您的 comment_params 中的许可中删除。尝试像这样更改您的方法,它应该可以工作:

def comment_params
    params.require(:comment).permit(:content, :wad_id, :user_id)
end

编辑 另外我认为您需要更改中的第一个命令

parent = Comment.find_by_id(params[:comment].delete(:parent_id))

 parent = Comment.find(params[:comment].delete(:parent_id))

【讨论】:

  • 这些更改导致相同的 ["Wad must exist"] 错误
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 2018-04-27
相关资源
最近更新 更多