Reputation: 289
I have one controller (patients) that passes a patient_id to another controller (referral_requests) to use in building the referral request record. I am running into the following error when trying to create the referral request. What am I doing wrong? My referral_requests table includes an integer column for user_id.
I have multiple user types defined with enums. Staff users create both patients and referral requests.
Thanks for any help!
error:
(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}]}>
patients controller create action:
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 controller new and create actions, and params:
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
Here are the model relationships:
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'
Upvotes: 0
Views: 291
Reputation: 3031
"user_id" shouldn't be in your permitted parameters list.
edit:
The actual issue from the comments is that he's validating the presence of "user_id" instead of "user". When creating a record through an association the id won't be filled in until later in the process, so you just check for the presence of the associated item rather than the id:
validates :user, presence: true
Upvotes: 1
Reputation: 101851
If you are creating referrals for a patient you should make it a nested resource:
resources :patients do
resources: :referral_requests, shallow: true
end
Since creating this resource should require authentication you want to make sure to handle that in a before filter:
class ReferralRequestsController < ApplicationController
before_action :authenticate_user!
end
If you are rolling your own authentication solution rather than using Devise, make sure you have such a method:
class ApplicationController
private
def authenticate_user!
redirect_to new_session_path and return unless current_user
end
end
When we create the resource note that we are not taking the user_id
(provided by the session) nor the patient id (we get it from the path segment) from the form input.
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
Using a before filter will here will also validate that the patient exists since Patient.find(params[:patient_id])
will raise ActiveRecord::RecordNotFound
.
A good way to handle where a record should be created with user input and other values such a user id from the session is to pass a block:
@referral_request = @patient.referral_requests.new(referral_request_params) do |rr|
rr.user = current_user
end
Allowing the user_id
param from the form would make it possible for a malicious user to pass any user id by just altering the input with the web inspector!
You create the proper path in the form by passing an array:
<%= form_for([@patient, @referral_request]) do |f| %>
Upvotes: 1