如何在Rails中为医生与患者关联设置两类患者的数量限制
Rails中按患者类型限制医生关联数量的实现方案
1. 给患者模型添加类型字段
首先需要给patients表新增一个区分患者类型的字段,推荐用枚举(enum)管理,逻辑更清晰:
- 生成迁移文件:
rails generate migration AddPatientTypeToPatients patient_type:string rails db:migrate
- 在
Patient模型中定义枚举:
class Patient < ApplicationRecord belongs_to :doctor enum patient_type: { free: 'free', paid: 'paid' } end
2. 在医生模型中添加数量限制验证
在Doctor模型里自定义验证方法,分别统计免费、付费患者的数量,和预设限制值对比:
class Doctor < ApplicationRecord has_many :patients # 把限制值设为常量,方便后续修改 MAX_FREE_PATIENTS = 10 MAX_PAID_PATIENTS = 50 validate :check_free_patient_limit, :check_paid_patient_limit private def check_free_patient_limit free_patient_count = patients.free.count if free_patient_count >= MAX_FREE_PATIENTS errors.add(:base, "免费患者数量已达上限(#{MAX_FREE_PATIENTS}人)") end end def check_paid_patient_limit paid_patient_count = patients.paid.count if paid_patient_count >= MAX_PAID_PATIENTS errors.add(:base, "付费患者数量已达上限(#{MAX_PAID_PATIENTS}人)") end end end
3. 可选:添加关联回调(避免批量添加绕过验证)
如果存在批量添加患者的场景,上面的验证可能失效,这时可以用before_add回调在添加单个患者前做检查:
class Doctor < ApplicationRecord has_many :patients, before_add: :check_patient_limit_before_add MAX_FREE_PATIENTS = 10 MAX_PAID_PATIENTS = 50 # 保留原有验证方法,处理手动保存的场景 validate :check_free_patient_limit, :check_paid_patient_limit private def check_patient_limit_before_add(patient) case patient.patient_type when 'free' if patients.free.count >= MAX_FREE_PATIENTS raise ActiveRecord::Rollback, "免费患者数量已达上限" end when 'paid' if patients.paid.count >= MAX_PAID_PATIENTS raise ActiveRecord::Rollback, "付费患者数量已达上限" end end end # 以下是原有验证方法 def check_free_patient_limit free_patient_count = patients.free.count if free_patient_count >= MAX_FREE_PATIENTS errors.add(:base, "免费患者数量已达上限(#{MAX_FREE_PATIENTS}人)") end end def check_paid_patient_limit paid_patient_count = patients.paid.count if paid_patient_count >= MAX_PAID_PATIENTS errors.add(:base, "付费患者数量已达上限(#{MAX_PAID_PATIENTS}人)") end end end
补充说明
- 如果需要给不同医生设置不同的限制值(比如不同等级的医生配额不同),可以给
doctors表新增max_free_patients和max_paid_patients字段,把验证里的常量换成实例属性即可。 - 验证提示文案可以根据业务需求调整成更贴合场景的表述。
内容的提问来源于stack exchange,提问作者Andrew Kancev
相关产品推荐
相关产品推荐

