Ruby on rails ActiveRecord::ReviewController#create中的NotNullViolation

Ruby on rails ActiveRecord::ReviewController#create中的NotNullViolation,ruby-on-rails,model-view-controller,error-handling,schema,Ruby On Rails,Model View Controller,Error Handling,Schema,在Rails中接收此错误: PG::NotNullViolation:错误:“reviewer_id”列中的null值违反了非null约束详细信息:失败的行包含(26,2222,2222,8,null,2021-01-30 19:26:03.3549832021-01-30 19:26:03.354983) 此应用程序正在尝试允许用户向其他用户提供评论。 我是新来的,所以错误可能很明显,但对未经训练的人来说并非如此。经过几个小时的研究,这是我最后的选择。 如果你能帮我解决这个问题,我将不胜感激。

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

此应用程序正在尝试允许用户向其他用户提供评论。 我是新来的,所以错误可能很明显,但对未经训练的人来说并非如此。经过几个小时的研究,这是我最后的选择。 如果你能帮我解决这个问题,我将不胜感激。上帝保佑

routes.rb

resources :users do
    resources :reviews, only: [ :new, :create ]
  end
 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
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"
  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
  belongs_to :user
  validates :content, presence: true
  validates :rating, presence: true
reviews\u controller.rb

resources :users do
    resources :reviews, only: [ :new, :create ]
  end
 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
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"
  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
  belongs_to :user
  validates :content, presence: true
  validates :rating, presence: true
schema.rb

resources :users do
    resources :reviews, only: [ :new, :create ]
  end
 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
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"
  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
  belongs_to :user
  validates :content, presence: true
  validates :rating, presence: true
user.rb

resources :users do
    resources :reviews, only: [ :new, :create ]
  end
 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
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"
  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
  belongs_to :user
  validates :content, presence: true
  validates :rating, presence: true
review.rb

resources :users do
    resources :reviews, only: [ :new, :create ]
  end
 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
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"
  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
  belongs_to :user
  validates :content, presence: true
  validates :rating, presence: true

对于在您的模式中定义的reviewer_id字段,您在Review上有一个数据库约束:

t.bigint“审阅者id”,null:false

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

因为您的审阅者是离开审阅的人,并且用户正在被审阅,所以我会这样做:

在您离开评论的地方(我假设这将是
User#show
),您正在查看特定的用户。您知道这是哪个用户,并且在该视图中它最有可能被定义为
@user
,因此您最有可能在表单中使用
。这将把
user_id
传递到参数中的Reviews#create操作。您还需要将
user_id
添加到
review_params
中,以便在
#create
操作中访问它

然后在您的
Reviews#create
操作中,分配
@review.reviewer\u id=current\u user.id
@review。当您调用
review.create(review\u params)
时,将分配用户id
,前提是您已按照上述建议将其添加到表单和
review\u params

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


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

您在哪里设置
reviewer\u id
?您只允许评论的两个参数是评级和内容。听起来您想做
@review.reviewer=current\u user
。您是否有专门的
用户
审阅者
?他们不一样吗?谢谢。我需要一个审阅者id,因为该审阅将显示评分、内容以及谁离开了审阅。因此,我会在review.rb中添加“validates:reviewer\u id,presence:true”,然后在review controller中,在review参数中添加:reviewer\u id。然后在def中创建。。。review instance=review.new(review\u params)、review.user\u id instance=current\u user.id、review.reviewer\u id instance=current\u user.id、user instance=user.find(params[:user\u id])?那么
user\u id
是给被审核人的,而
审核人id
是给离开审核的人的?如果审阅者是离开审阅的人,那么他们很可能是
当前用户
,并且您已经知道如何在审阅时将该
id
分配给属性。由于您要对某个用户离开审阅,因此您将可以在离开审阅的视图中访问该用户的id。因此,您希望将该id与参数一起传递给create操作。您需要将
:user\u id
添加到
:review\u params
,并在视图中添加一个带有
@user.id
隐藏字段标签。我编辑了我的答案,使其更加具体和清晰。我的答案有帮助吗?