目前我正在开发一个药房系统,因此我想制定一个具有特定专业,患者和药物的处方。为此,我使用了一些像simple_form,chosen_rails和cocoon这样的宝石。但是,当我创建一个新的处方而没有填写专业领域,但选择一个专业,我得到以下错误:
> Started POST "/prescriptions" for 127.0.0.1 at 2018-01-05 21:08:42 -0300
Processing by PrescriptionsController#create as JS
Parameters: {"utf8"=>"✓", "prescription"=>{"professional_id"=>"1", "professional_attributes"=>{"first_name"=>"", "last_name"=>"", "dni"=>"", "enrollment"=>"", "sector_id"=>"", "sector_attributes"=>{"sector_name"=>"", "description"=>"", "complexity_level"=>""}}, "patient_id"=>"1", "patient_attributes"=>{"first_name"=>"", "last_name"=>"", "dni"=>"", "patient_type_id"=>""}, "quantity_medications_attributes"=>{"0"=>{"medication_id"=>"", "quantity"=>"", "_destroy"=>"false"}}, "quantity_supplies_attributes"=>{"0"=>{"supply_id"=>"", "quantity"=>"", "_destroy"=>"false"}}, "observation"=>"", "date_received"=>"01/05/2018 9:08 PM"}, "commit"=>"Cargar y dispensar"}
User Load (0.4ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 ORDER BY "users"."id" ASC LIMIT $2 [["id", 1], ["LIMIT", 1]]
Patient Load (0.5ms) SELECT "patients".* FROM "patients" WHERE "patients"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
Professional Load (0.4ms) SELECT "professionals".* FROM "professionals" WHERE "professionals"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
PrescriptionStatus Load (0.4ms) SELECT "prescription_statuses".* FROM "prescription_statuses" WHERE "prescription_statuses"."name" = $1 LIMIT $2 [["name", "Dispensada"], ["LIMIT", 1]]
(0.3ms) BEGIN
PatientType Load (0.5ms) SELECT "patient_types".* FROM "patient_types" WHERE "patient_types"."id" = $1 LIMIT $2 [["id", 1], ["LIMIT", 1]]
(0.3ms) ROLLBACK
Completed 422 Unprocessable Entity in 36ms (ActiveRecord: 2.7ms)
>
>
>ActiveRecord::RecordInvalid - Validation failed: Professional first name can't be blank, Professional last name can't be blank, Professional dni can't be blank, Professional sector must exist:
app/controllers/prescriptions_controller.rb:82:in `block in create'
app/controllers/prescriptions_controller.rb:81:in `create'
我的处方控制器是:
class PrescriptionsController < ApplicationController
before_action :set_prescription, only: [:show, :edit, :update, :destroy]
def new
@prescription = Prescription.new
@professionals = Professional.all
@medications = Medication.all
@supplies = Supply.all
@patients = Patient.all
@sectors = Sector.all
@patient_types = PatientType.all
@prescription.build_professional
@prescription.professional.build_sector
@prescription.build_patient
@prescription.quantity_medications.build
@prescription.quantity_supplies.build
end
def create
@prescription = Prescription.new(prescription_params)
if dispensing?
@prescription.prescription_status = PrescriptionStatus.find_by_name("Dispensada")
@prescription.date_dispensed = DateTime.now
end
@prescription.prescription_status = PrescriptionStatus.find_by_name("Pendiente") if loading?
date_r = prescription_params[:date_received]
@prescription.date_received = DateTime.strptime(date_r, '%d/%M/%Y %H:%M %p')
respond_to do |format|
if @prescription.save!
flash.now[:success] = "La prescripción de "+@prescription.professional.full_name+" se ha creado correctamente."
format.js
else
flash.now[:error] = "La prescripción no se ha podido crear."
format.js
end
end
end
def prescription_params
params.require(:prescription).permit(
:observation, :date_received,
:professional_id, :patient_id, :prescription_status_id,
quantity_medications_attributes: [:id, :medication_id, :quantity,
:_destroy],
quantity_supplies_attributes: [:id, :supply_id, :quantity, :_destroy],
patient_attributes: [:id, :first_name, :last_name, :dni, :patient_type_id],
professional_attributes: [:id, :first_name, :last_name, :dni, :enrollment, :sector_id,
sector_attributes: [:id, :sector_name, :description, :complexity_level] ])
end
end
我的模特是:
class Prescription < ApplicationRecord
validates_presence_of :patient
validates_presence_of :prescription_status
validates_presence_of :professional
belongs_to :professional
belongs_to :patient
belongs_to :prescription_status
has_many :quantity_medications, :as => :quantifiable, dependent: :destroy, inverse_of: :quantifiable
has_many :medications, :through => :quantity_medications
has_many :quantity_supplies, :as => :quantifiable, dependent: :destroy, inverse_of: :quantifiable
has_many :supplies, :through => :quantity_supplies
accepts_nested_attributes_for :quantity_medications,
:reject_if => :all_blank,
:allow_destroy => true
accepts_nested_attributes_for :quantity_supplies,
:reject_if => :all_blank,
:allow_destroy => true
accepts_nested_attributes_for :medications
accepts_nested_attributes_for :patient,
:reject_if => :all_blank
accepts_nested_attributes_for :professional,
:reject_if => :all_blank
def dispensed?
self.prescription_status.is_dispense?
end
end
class Professional < ApplicationRecord
validates :first_name, presence: true
validates :last_name, presence: true
validates :dni, presence: true
has_many :prescriptions
belongs_to :sector
accepts_nested_attributes_for :sector,
:reject_if => :all_blank
end
class Sector < ApplicationRecord
validates_presence_of :sector_name, presence: true
validates_presence_of :complexity_level, presence: true
has_many :professionals
end
我的表格是:
create_table "prescriptions", force: :cascade do |t|
t.text "observation"
t.datetime "date_received"
t.datetime "date_dispensed"
t.integer "prescription_status_id"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "professional_id"
t.bigint "patient_id"
t.index ["patient_id"], name: "index_prescriptions_on_patient_id"
t.index ["professional_id"], name: "index_prescriptions_on_professional_id"
end
create_table "professionals", force: :cascade do |t|
t.string "first_name"
t.string "last_name"
t.integer "dni"
t.string "enrollment"
t.string "address"
t.string "email"
t.string "phone"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.bigint "sector_id"
t.index ["sector_id"], name: "index_professionals_on_sector_id"
end
create_table "sectors", force: :cascade do |t|
t.string "sector_name"
t.text "description"
t.integer "complexity_level"
t.string "applicant"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
最后,我的表单是:
_form.html.erb
<%= simple_form_for @prescription, remote: true, html: {class: "form-inline"} do |f| %>
<%= f.error_notification %>
<%= f.input :professional_id,
label: 'Doctor',
label_method: :full_name,
value_method: :id,
collection: @professionals,
include_blank: false,
input_html: { class: 'chosen-select', id: 'professional_id' },
prompt: 'Seleccione un doctor o cree uno'
%><br><br>
<%= f.hint 'No seleccione ningún doctor para crear uno nuevo.', id: 'professional-hint', style: "display: none" %>
<%= f.simple_fields_for :professional, html: {class: "form-inline"} do |form_professional| %>
<%= render "professional_fields", :f => form_professional %>
<% end %><br>
<%= f.input :patient_id,
label: 'Paciente',
label_method: :full_info,
value_method: :id,
collection: @patients,
include_blank: false,
input_html: { class: 'chosen-select', id: 'patient_id' },
prompt: 'Seleccione un paciente o cree uno'
%><br><br>
<%= f.hint 'No seleccione ningún paciente para crear uno nuevo.', id: 'patientHint', style: "display: none" %>
<%= f.simple_fields_for :patient, html: { class: 'form-inline' } do |form_patient| %>
<%= render "patient_fields", :f => form_patient %>
<% end %><br>
<div class='row'>
<div class='col-md-6'>
<label>Medicación</label>
<div id="quantity-medications">
<%= f.simple_fields_for :quantity_medications, html: {class: "form-inline"} do |form_quantity| %>
<%= render "quantity_medication_fields", :f => form_quantity %>
<% end %>
<div class="links">
<%= link_to_add_association f, :quantity_medications, class: 'btn btn-default btn-sm' do %>
<%= content_tag(:span, '', class: 'glyphicon glyphicon-plus') %>
<% end %>
</div>
</div>
</div>
<div class='col-md-6'>
<label>Suministro</label>
<div id="quantity-supplies">
<%= f.simple_fields_for :quantity_supplies, html: {class: "form-inline"} do |form_quantity| %>
<%= render "quantity_supply_fields", :f => form_quantity %>
<% end %>
<div class="links">
<%= link_to_add_association f, :quantity_supplies, class: 'btn btn-default btn-sm' do %>
<%= content_tag(:span, '', class: 'glyphicon glyphicon-plus') %>
<% end %>
</div>
</div>
<br>
</div>
</div>
<div class='row'>
<div class='col-md-6'>
<%= f.input :observation, label: 'Observaciones', as: :text,
:input_html => { :cols => 46 , :rows => 2 } %>
</div>
<div class='col-md-6'>
<%= f.input :date_received, label: 'Fecha recibida',
as: :string,
:placeholder => "Seleccionar fecha",
input_html: {class: "form-control", required: true,
value: "#{@prescription.date_received.strftime("%d/%m/%y %H:%M") unless @prescription.new_record?}"},
html5: false
%><br><br>
</div>
</div>
<% end %>
_professional_fields.html.erb
<div id='form-professional'>
<%= f.input :first_name, placeholder: 'Nombre', required: true, label: false %>
<%= f.input :last_name, placeholder: 'Apellido', required: true, label: false %>
<%= f.input :dni, placeholder: 'DNI', required: true, label: false, input_html: { min: '10000', max:'99999999' } %>
<%= f.input :enrollment, placeholder: 'Matrícula', label: false, input_html: { min: '1000', max:'9999' } %>
<%= f.input :sector_id,
label: false,
label_method: :sector_name,
value_method: :id,
collection: @sectors,
include_blank: false,
input_html: { class: 'chosen-select', id: 'sector_id', onchange: "" },
prompt: 'Seleccione un sector o cree uno nuevo'
%>
<br><br>
<%= f.hint 'No seleccione ningun sector para crear uno nuevo', id: 'sector-hint', style: "display: none" %>
<%= f.simple_fields_for :sector, html: { class: 'form-inline' } do |fs| %>
<div id='form-sector'>
<label>Nuevo sector</label>
<%= fs.input :sector_name, placeholder: 'Nombre sector', required: true, label: false %>
<%= fs.input :description, as: :string, placeholder: 'Descripción', required: true, label: false %>
<%= fs.input :complexity_level, label: false, required: true, input_html: { min: '0', max:'10' } %>
</div>
<% end %>
</div>
我想创建一个新的处方,只选择所选择的专业人士,避免创建新的专业人士。我有另一个名为Medication的模型,其中嵌套形式如MedicationBrand和子嵌套形式名为Laboratory,我想做的工作完美无缺。
我在这个模型中做错了什么?
答案 0 :(得分:1)
您拥有:reject_if => :all_blank
设置,但由于您的专业属性中的子嵌套,这并不像您预期的那样有效。 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html的文档中解释了:all_blank
选项:
REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? } }
您的专业属性如下所示进入控制器:
"professional_attributes"=>{"first_name"=>"", "last_name"=>"", "dni"=>"", "enrollment"=>"", "sector_id"=>"", "sector_attributes"=>{"sector_name"=>"", "description"=>"", "complexity_level"=>""}}
sector_attributes
值不是空白,因为它是一个子嵌套哈希,恰好碰巧拥有所有空白值。因此,professional_attributes
不会被拒绝,并会尝试处理它们。
对于:reject_if
,您希望使用自己的自定义proc来检查professional_attributes
的值,并将任何子哈希处理为空白。
这适用于您的输入属性:
:reject_if => proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? || (value.is_a?(Hash) && value.values.all?(&:blank?)) } }
如果你想进一步使用哈希的子嵌套,你需要考虑一个递归函数,虽然我建议你可能需要重新考虑你的设计,为什么你在单一形式中有如此多的嵌套水平,是否真的有必要。
希望有所帮助!