目前我正在开发一个药房系统,所以我想创建一个包含特定专业人士、患者和药物的处方。为此,我使用了一些 gem,例如 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'
我的处方 Controller 是:
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,我想做的事情完美无缺。
我在这个模型中做错了什么?
最佳答案
您设置了 :reject_if => :all_blank
,但是由于您的专业属性中的子嵌套,它并没有像您预期的那样工作。 :all_blank
选项在 http://api.rubyonrails.org/classes/ActiveRecord/NestedAttributes/ClassMethods.html 的文档中有解释。 :
REJECT_ALL_BLANK_PROC = proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? } }
您的专业属性按如下方式进入 Controller :
"professional_attributes"=>{"first_name"=>"", "last_name"=>"", "dni"=>"", "enrollment"=>"", "sector_id"=>"", "sector_attributes"=>{"sector_name"=>"", "description"=>"", "complexity_level"=>""}}
sector_attributes
值不是空的,因为它是一个子嵌套哈希,恰好本身所有空值。因此,professional_attributes
不会被拒绝,它会尝试处理它们。
对于您的 :reject_if
,您想使用自己的自定义过程来检查 professional_attributes
的值,并将任何子哈希处理为空白好吧。
这应该适用于您的输入属性:
:reject_if => proc { |attributes| attributes.all? { |key, value| key == "_destroy" || value.blank? || (value.is_a?(Hash) && value.values.all?(&:blank?)) } }
如果你想要进一步的散列子嵌套,你需要考虑一个递归函数,尽管我建议你可能需要重新考虑你的设计,为什么你有这么多层次以单一形式嵌套以及是否真的有必要。
希望对您有所帮助!
关于ruby-on-rails - 如果选择存在,不要创建嵌套表单,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48123604/