Rails:创建新记录时 ActiveModel 错误

Rails: ActiveModel Error when creating new record

我有一个控制器(患者)将 patient_id 传递给另一个控制器(referral_requests)以用于构建转诊请求记录。我 运行 在尝试创建推荐请求时遇到以下错误。我究竟做错了什么?我的 referral_requests table 包含 user_id.

的整数列

我有多个用枚举定义的用户类型。员工用户创建患者和转诊请求。

感谢您的帮助!

错误:

(0.1ms)  rollback transaction
#<ActiveModel::Errors:0x007fe696696fc0 @base=#<ReferralRequest id: nil, content: nil, user_id: nil, created_at: nil, updated_at: nil, patient_id: 4, call_option_1: nil, call_option_2: nil, call_option_3: nil, call_option_1_status: nil, call_option_2_status: nil, call_option_3_status: nil, status: "created">, @messages={:user_id=>["can't be blank"]}, @details={:user_id=>[{:error=>:blank}]}>

患者控制器创建操作:

def create
  @patient = current_user.patients.build(patient_params)
  if @patient.save
    flash[:success] = "Patient Created!"
    redirect_to new_referral_request_path(patient_id: @patient.id)
  else
    Rails.logger.info(@patient.errors.inspect)
    render 'patients/new'
end

referral_requests 控制器新建和创建动作,参数:

def new
  @patient = Patient.find(params[:patient_id]) 
  @referral_request = current_user.referral_requests.build(patient:  @patient) if signed_in?
end

def create
  @referral_request = current_user.referral_requests.build(referral_request_params)
  if @referral_request.save
        flash[:success] = "Referral Request Created!"
        redirect_to new_dispatch_path(referral_request_id:   @referral_request.id)
  else
    Rails.logger.info(@referral_request.errors.inspect)
    @feed_items = []
    render 'static_pages/home'
  end
end

private

def referral_request_params
  params.require(:referral_request).permit(:content, :user_id, :patient_id, concern_ids: [], insurance_ids: [], race_ids: [], language_ids: [], gender_ids: [])
end

模型关系如下:

require 'active_support/concern'

module StaffUser
  extend ActiveSupport::Concern

  included do
    has_many :referral_requests, foreign_key: "user_id"

class ReferralRequest < ApplicationRecord
  belongs_to :user, -> { where role: :staff }, class_name: 'User', foreign_key: 'user_id'

"user_id" 不应在您允许的参数列表中。

编辑:

评论中的实际问题是他正在验证 "user_id" 而不是 "user" 的存在。当通过关联创建记录时,id 直到过程的后期才会被填充,因此您只需检查关联项目的存在而不是 id:

validates :user, presence: true

如果您要为患者创建转诊,您应该将其设为嵌套资源:

resources :patients do
  resources: :referral_requests, shallow: true
end

由于创建此资源需要身份验证,因此您要确保在之前的过滤器中处理它:

class ReferralRequestsController < ApplicationController
  before_action :authenticate_user!
end

如果您正在推出自己的身份验证解决方案而不是使用 Devise,请确保您有这样的方法:

class ApplicationController
  private
  def authenticate_user!
    redirect_to new_session_path and return unless current_user
  end
end

当我们创建资源时请注意,我们没有从表单输入中获取 user_id(由会话提供)或患者 ID(我们从路径段中获取)。

class ReferralRequestsController < ApplicationController
  before_action :authenticate_user!
  before_action :set_patient, only: [:new, :create, :index]

  # GET /patients/:patient_id/referral_requests/new
  def new
    @referral_request = @patient.referral_requests.new
  end

  # POST /patients/:patient_id/referral_requests
  def create
    @referral_request = @patient.referral_requests.new(referral_request_params) do |rr|
      rr.user = current_user
    end

    if @referral_request.save
      flash[:success] = "Referral Request Created!"
      redirect_to new_dispatch_path(referral_request_id:   @referral_request.id)
    else 
      Rails.logger.info(@referral_request.errors.inspect)
      @feed_items = []
      render :new
    end
  end

  private
  def set_patient
    @patient = Patient.find(params[:patient_id])
  end

  def referral_request_params
     params.require(:referral_request)
        .permit(:content, 
           concern_ids: [], 
           insurance_ids: [], 
           race_ids: [], 
           language_ids: [], 
           gender_ids: []
        )
  end
end

在这里使用前置过滤器也将验证患者是否存在,因为 Patient.find(params[:patient_id]) 将引发 ActiveRecord::RecordNotFound.

处理应该使用用户输入和其他值(例如来自会话的用户 ID)创建记录的一个好方法是传递一个块:

@referral_request = @patient.referral_requests.new(referral_request_params) do |rr|
  rr.user = current_user
end

允许表单中的 user_id 参数将使恶意用户只需通过网络检查器更改输入即可传递任何用户 ID!

您通过传递数组在表单中创建正确的路径:

<%= form_for([@patient, @referral_request]) do |f| %>