Ruby on rails 如何验证Rails 5中的组合值?

Ruby on rails 如何验证Rails 5中的组合值?,ruby-on-rails,validation,ruby-on-rails-5,Ruby On Rails,Validation,Ruby On Rails 5,我正在制作一个医院应用程序,其中有健康问题,由患者id和问题类型组成 一名患者可以有多个健康问题,但不能属于同一问题类型 创建患者时,我将其健康问题创建为嵌套属性。但是验证不会阻止我为一名患者创建重复的问题类型 这是我的健康问题模型: class HealthProblem < ApplicationRecord belongs_to :patient belongs_to :problem_type validates :problem_type_id, uniqueness

我正在制作一个医院应用程序,其中有
健康问题
,由
患者id
问题类型
组成

一名患者可以有多个
健康问题
,但不能属于同一
问题类型

创建患者时,我将其
健康问题
创建为嵌套属性。但是验证不会阻止我为一名患者创建重复的问题类型

这是我的健康问题模型:

class HealthProblem < ApplicationRecord
  belongs_to :patient
  belongs_to :problem_type
  validates :problem_type_id, uniqueness: {scope: :patient_id}
end
类健康问题
我还尝试将
问题类型\ id
患者\ id
索引设置为唯一,但没有按预期工作(即使问题类型/患者不同,我也无法添加任何重复的问题类型/患者)


更新:我添加索引时出错。 正如@mmichael所指出的,这是添加索引的正确方法:
添加索引:健康问题,[:患者id,:问题类型id],唯一性:true

现在数据库向我抛出一个错误,阻止它为一个患者添加重复的问题类型。这是一个进步,但仍然不是我需要的

我需要rails验证来显示这个错误(在某种程度上可以正确处理)


更新2:当使用
接受
+
的嵌套属性时,它看起来像一个,验证作用域的唯一性

为多列创建唯一索引将防止添加重复项,但是在Rails(5.1)版本发布之前,验证将分两次显示:首先是sql重复验证,然后是模型的其他验证

由于这只能在数据库级别进行验证,因此不需要进行模型验证(
验证:problem_type_id,惟一性:{scope::patient_id}
)。希望Rails团队尽快修复它


数据库错误可以处理。

我在
Rails 5.1.5
上也遇到了这个问题。我的解决方案是将一个独特的数据库索引(如@artur haddad建议的)与模型
arou save
回调结合使用。我将试着用一个简短的提纲来解释我的问题和解决方案

问题:

Institution (id:integer, name:string)
    | 1
    |
    | *
WaterSupply (id:integer, meter:string, institution_id:integer)
因此,一个
机构
可能有许多
供水
,每个
供水
都需要一个唯一的
水表
参考。在我使用的常用表格中编辑供水

accepts_nested_attributes_for :water_supplies, reject_if: :all_blank, allow_destroy: true
在这一点上,验证

validates :meter, uniqueness: {scope: :institution_id}
供水系统中,由于出现故障,
供水系统不再工作

解决方案:

Institution (id:integer, name:string)
    | 1
    |
    | *
WaterSupply (id:integer, meter:string, institution_id:integer)
  • 将唯一的数据库索引添加到表
    water\u supplies

    add_index :water_supplies, [:meter, :institution_id], unique: true
    
  • 在保存前后添加
    model回调

    class WaterSupply < ApplicationRecord
      # Associations
      belongs_to :institution
    
      # Validations
      validates :institution, :meter, presence: true
    
      # Callbacks
      around_save :catch_uniqueness_exception
    
      private
    
      def catch_uniqueness_exception
        yield
      rescue ActiveRecord::RecordNotUnique
        self.errors.add(:meter, :taken)
      end
    end
    
    class供水

  • 就这些。现在,如果属性
    meter
    在给定范围内不再是唯一的,则每次保存时都会得到一个
    ActiveModel::Error
    ,并且表单将显示已经发生的错误

    当您说您已经尝试添加唯一索引时,您是否尝试过添加索引:健康问题,[:患者id,:问题类型id],唯一:true
    ?@mmichael实际上我添加了单独的索引(这是一个错误)。您所说的方式如我所愿,但它只在数据库中进行验证,它返回:“Mysql2::Error:key‘index_health_problems_on_patient_id_和_problem_type_id’的重复条目‘6-3’”我需要它返回验证错误。假设您在创建健康问题记录时使用
    接受
    的嵌套属性,有一个包含各种解决方法的解决方案。我建议您从创建记录的任何位置营救
    ActiveRecord::RecordNotUnique
    。如果您在控制器中执行此操作,请查看,或者您可以简单地将您的记录创建块包装在标准的
    rescue
    中。没错,我使用的是
    接受嵌套的属性,正如您所指出的,它看起来像rails bug。非常感谢您的回答。很好。当我使用此方法时,我会收到“ActiveRecord::RecordNotSaved:未能保存记录”当我使用此方法并尝试创建具有两个嵌套记录的父级时,未保存的父级模型仍然有一个id和持久性方法,如#new#U record?而#坚持?这是不正确的。