【问题标题】:ActiveRecord::NotNullViolation in ReviewsController#createReviewController#create 中的 ActiveRecord::NotNullViolation
【发布时间】:2021-05-04 10:14:25
【问题描述】:

在 Rails 中收到此错误: PG::NotNullViolation:错误:“reviewer_id”列中的空值违反非空约束详细信息:失败行包含(26、2222、2222、8、null、2021-01-30 19:26:03.354983、2021-01- 30 19:26:03.354983)。

此应用试图允许用户给其他用户评论。 我是新手,所以错误可能很明显,但对于未经训练的眼睛来说不是。经过数小时的研究,这是我最后的手段。 我会很感激帮助解决这个问题。上帝保佑。

routes.rb

resources :users do
    resources :reviews, only: [ :new, :create ]
  end

reviews_controller.rb

 def create
    @review = Review.new(review_params)
    @review.user_id = current_user.id

    if @review.save
      redirect_to user_path(current_user), notice: 'Review added!'
    else
      render :new
    end
  end

  private

  def review_params
    params.require(:review).permit(:rating, :content)
  end

schema.rb

create_table "reviews", force: :cascade do |t|
    t.text "content"
    t.integer "rating"
    t.bigint "user_id", null: false
    t.bigint "reviewer_id", null: false
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.index ["reviewer_id"], name: "index_reviews_on_reviewer_id"
    t.index ["user_id"], name: "index_reviews_on_user_id"
  end

  create_table "users", force: :cascade do |t|
    t.string "email", default: "", null: false
    t.string "encrypted_password", default: "", null: false
    t.string "reset_password_token"
    t.datetime "reset_password_sent_at"
    t.datetime "remember_created_at"
    t.integer "sign_in_count", default: 0, null: false
    t.datetime "current_sign_in_at"
    t.datetime "last_sign_in_at"
    t.inet "current_sign_in_ip"
    t.inet "last_sign_in_ip"
    t.datetime "created_at", precision: 6, null: false
    t.datetime "updated_at", precision: 6, null: false
    t.string "username"
    t.index ["email"], name: "index_users_on_email", unique: true
    t.index ["reset_password_token"], name: "index_users_on_reset_password_token", unique: true
    t.index ["username"], name: "index_users_on_username", unique: true
  end

  add_foreign_key "offers", "games"
  add_foreign_key "offers", "users"
  add_foreign_key "rentals", "offers"
  add_foreign_key "rentals", "users"
  add_foreign_key "reviews", "users"
  add_foreign_key "reviews", "users", column: "reviewer_id"

user.rb

  has_many :reviews, dependent: :destroy
  has_many :given_reviews, source: :reviews, foreign_key: :reviewer_id
  has_many :received_reviews, source: :reviews, foreign_key: :user_id

review.rb

  belongs_to :user
  validates :content, presence: true
  validates :rating, presence: true

【问题讨论】:

  • 你在哪里设置reviewer_id?您允许评论的唯一两个参数是评分和内容。
  • 听起来你想做@review.reviewer = current_user。你有没有故意的userreviewer?他们不一样吗?

标签: ruby-on-rails model-view-controller error-handling schema


【解决方案1】:

对于 Reviewer_id 字段,您对 Review 有一个数据库约束,在您的架构中定义:

t.bigint "reviewer_id", null: false

在您的controller#create 操作中,您定义了一个user_id,但我看不到您在哪里传递reviewer_id 或设置它。如果表单中有一个字段,则需要将该参数添加到 review_params 以便它可以从表单传递到控制器操作。或者您需要在 create 操作中定义它,类似于您定义 user_id 的方式。

由于您的评论者是留下评论的人,并且正在对用户进行评论,所以我会这样做:

在您留下评论的地方,(我假设这将是User#show)您正在查看特定用户。您知道这是哪个用户,并且很可能在该视图中将其定义为@user,因此您很可能在表单中使用<%= hidden_field_tag :user_id, @user.id %> 进行审核。这会将user_id 传递给参数中的Reviews#create 操作。您还需要将user_id 添加到review_params,以便可以在#create 操作中访问它。

然后在您的Reviews#create 操作中分配@review.reviewer_id = current_user.id@review.user_id 将在您调用 Review.create(review_params) 时分配,假设您已按照上面的建议将其添加到表单和 review_params

尝试在 create 操作中添加断点并查看从审核表单发送的 params 对象,这可能有助于您了解正在发生的事情。

典型的 Rails 实践也是使用模型验证。这样一来,您就会在请求到达数据库之前收到应用错误。

【讨论】:

  • 谢谢。我想要一个 reviewer_id,因为评论会显示评分、内容以及留下评论的人。所以,我会在 review.rb 中添加“验证:reviewer_id,presence:true”,然后在评论控制器中,将:reviewer_id 添加到 review_params。然后在 def create... review instance = Review.new(review_params), review.user_id instance = current_user.id, review.reviewer_id instance = current_user.id, and user instance = user.find(params[:user_id]) ?
  • 那么user_id 是给被审查的人,reviewer_id 是给离开审查的人?如果评论者是离开评论的人,他们很可能是current_user,并且您已经知道如何将id 分配给评论上的属性。由于您要为用户留下评论,因此您可以在要留下评论的视图中访问该用户的 ID。因此,您希望将该 id 与参数一起传递给 create 操作。您需要将:user_id 添加到:review_params,并在视图中添加hidden_field_tag@user.id
  • 我编辑了我的答案,使其更加具体和清晰。
  • 我的回答有帮助吗?
猜你喜欢
  • 2018-03-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多