ruby-on-rails - 通过关联向has_many中的连接表添加一个额外的字段
问题描述
在我的应用程序中,我有一些工作可以在完成后进行审查。审查表预先填充了预定义的值。经理应选中她想要添加到工作的所有评论的复选框。
我有一个 has_many :through 与额外列的关联,这是连接表中的一个额外关联:
class Job < ApplicationRecord
has_many :job_reviews, dependent: :destroy
has_many :reviews, through: :job_reviews
accepts_nested_attributes_for :job_reviews, allow_destroy: true, reject_if: :all_blank
end
class Review < ApplicationRecord
has_many :job_reviews, dependent: :destroy
has_many :jobs, through: :job_reviews
end
class JobReview < ApplicationRecord
belongs_to :job
belongs_to :review
belongs_to :user
end
在我看来,我有这样一个表格:
= simple_form_for @job do |f|
= f.association :reviews, collection: Review.all, as: :check_boxes, include_hidden: false, label: false
= f.input :user_id, input_html: {value: current_user.id}
= f.button :submit, class: 'btn btn-success'
控制器看起来像这样:
def job_params
params.require(:job).permit(:user_id, review_ids: [])
end
当我运行代码时,这些是正在处理的参数:
<ActionController::Parameters {"user_id"=>"dfd24578-5asa-4143-b209-d13cb419af30", "review_ids"=>["453852c5-45f0-4f67-a41c-e7e50dab711a", "a1303a62-fbef-5asa-95a0-a3ffa0b7616c"]} permitted: true>
控制器中的创建方法:
def create
respond_to do |format|
if @job.update(job_params)
format.js
else
format.js { render :js=>"alert('#{@job.errors.full_messages }');" }
end
end
end
这是我得到的错误:
INSERT INTO "job_reviews" ("uuid", "review_id", "job_id", "created_at", "updated_at") VALUES ($1, $2, $3, $4, $5) RETURNING "uuid" [["id", "dfd24578-5asa-42b8-807c-38be1036bcf5"], ["review_id", "a1303a62-fbef-5asa-95a0-a3ffa0b7616c"], ["job_id", "cb7eba6e-95a0-45f0-81f2-490d1c80ee07"], ["created_at", "2019-06-13 12:04:08.581557"], ["updated_at", "2019-06-13 12:04:08.581557"]]
(0.2ms) ROLLBACK
ActiveRecord::NotNullViolation: PG::NotNullViolation: ERROR: null value in column "user_id" violates not-null constraint
解决方案
首先:
- 模型中有错误
JobReview
。替换belongs_to :job_review
为belongs_to :review
- 该
job_review_params
方法应重命名为,job_params
因为它实际上是Job
您分配参数的对象。
当您分配reviews
给一个job
传递review_ids
参数时,Rails 会尝试自动创建job_reviews
关联。它失败是因为 Rails 不能自动计算该user_id
值并且它没有正确传递。
尽管您在表单中有参数,但它是作为的属性user_id
传递的。job
Rails 不知道如何处理它。
解决问题的方法之一是reviews
手动job
分配:
job_params[:review_ids].each do |review_id|
@job.job_reviews.build(review_id: review_id, user_id: current_user.id)
end
@job.save
在这种情况下,您不必user_id
通过表单发送,因为它在控制器中可用:
= simple_form_for @job do |f|
= f.association :reviews, collection: Review.all, as: :check_boxes, include_hidden: false, label: false
= f.button :submit, class: 'btn btn-success'
推荐阅读
- nlp - 是否可以将特定领域的 word2vec 嵌入和现成的 ELMo 嵌入结合起来用于下游无监督任务?
- gradle - 将平台约束应用于所有配置
- javascript - 如何将包添加到我的 Lerna 存储库?
- php - Prestashop Api Url 始终重定向到登录 URL
- sql - 如何在 OUT SYS_REFCURSOR 中返回 null
- android-studio - com.android.tools.r8.a:MethodHandle.invoke 和 MethodHandle.invokeExact 仅从 Android O 开始支持 (--min-api 26)
- ios - 删除后如何在模拟器中重新安装 react-native 应用程序?
- javascript - 如何在Angular中停止计时器?
- python - ValueError:以 10 为底的 int() 的无效文字:python 3.9.1
- python - python matplotlib contourf的插值方法是什么