如何在Rails 5中验证组合值?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了如何在Rails 5中验证组合值?相关的知识,希望对你有一定的参考价值。
我正在制作一个医院应用程序,有health_problems
由patient_id
和problem_type_id
组成。
患者可以有多个health_problems
,但他们不能是相同的problem_type_id
。
当我创建一个患者时,我将其health_problems
创建为嵌套属性。但验证并没有阻止我为一名患者创建重复的problem_types
。
这是我的HealthProblem模型:
class HealthProblem < ApplicationRecord
belongs_to :patient
belongs_to :problem_type
validates :problem_type_id, uniqueness: {scope: :patient_id}
end
我也尝试设置problem_type_id
和patient_id
索引的独特性,但它没有按预期工作(我无法添加任何重复的problem_type /患者,即使有不同的problem_types /患者)
更新:我错误地添加了索引。正如@mmichael所指出的,这是添加索引的正确方法:add_index :health_problems, [:patient_id, :problem_type_id], unique: true
现在数据库抛出了一个错误,阻止它为一个病人添加重复的problem_types。这是一个进步,但仍然不是我需要的。
我需要通过rails验证显示此错误(以某种方式可以正确处理)。
更新2:当使用known rails bug + accepts_nested_attributes_for
时,它看起来像validates uniqueness with scope
。
为多列创建唯一索引将阻止添加重复项,但是 - 直到此版本的Rails(5.1) - 验证将显示两次:首先是sql重复验证,然后是模型具有的其他验证。
由于这只能在数据库级别进行验证,因此不需要模型验证(validates :problem_type_id, uniqueness: {scope: :patient_id}
)。 Hope Rails团队很快就会修复它。
可以使用rescue_from处理数据库错误。
我也在Rails 5.1.5
上遇到了这个问题。我的解决方案是使用一个独特的数据库索引(如@ artur-haddad建议)与模型around_save
回调。我将尝试将我的问题和解决方案解释为简短的大纲。
问题:
Institution (id:integer, name:string)
| 1
|
| *
WaterSupply (id:integer, meter:string, institution_id:integer)
因此,Institution
可能有许多water_supplies
,每个WaterSupply
需要一个独特的meter
参考。在我正在使用的常见形式中编辑water_supplies
accepts_nested_attributes_for :water_supplies, reject_if: :all_blank, allow_destroy: true
此时验证
validates :meter, uniqueness: {scope: :institution_id}
由于WaterSupply
,在known issue内部不再起作用。
解:
- 向表
water_supplies
添加唯一的数据库索引add_index :water_supplies, [:meter, :institution_id], unique: true
- 添加
around_save
模型回调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
就这样。现在,如果属性meter
在给定范围内不再是唯一的,则每个保存都会获得一个ActiveModel::Error
,并且表单将显示错误already taken
。
以上是关于如何在Rails 5中验证组合值?的主要内容,如果未能解决你的问题,请参考以下文章
以下代码片段是不是容易受到 Rails 5 中 SQL 注入的影响?
为 memcached 和 Rails 组合片段和对象缓存的最佳方式