嗨,我不想验证表格中3列的独特组合。
假设我有一个名为cars的表,其值为:brand,:model_name和:fuel_type。
我当时想要的是根据这些记录的组合验证记录是否唯一。例如:
brand model_name fuel_type
Audi A4 Gas
Audi A4 Diesel
Audi A6 Gas
一切都有效。但是“奥迪,A6,气体”的另一项记录不应该有效。
我知道这个验证,但我怀疑它实际上做了我想要的。
validates_uniqueness_of :brand, :scope => {:model_name, :fuel_type}
答案 0 :(得分:97)
您的代码段中存在语法错误。正确的验证是:
validates_uniqueness_of :car_model_name, :scope => [:brand_id, :fuel_type_id]
或更短的红宝石1.9.x:
validates_uniqueness_of :car_model_name, scope: [:brand_id, :fuel_type_id]
使用 rails 4 ,您可以使用:
validates :car_model_name, uniqueness: { scope: [:brand_id, :fuel_type_id] }
rails 5 可以使用
validates_uniqueness_of :car_model_name, scope: %i[brand_id fuel_type_id]
答案 1 :(得分:14)
取决于您的需求,您还可以添加约束(作为表创建迁移的一部分或作为单独的一部分)而不是模型验证:
add_index :the_table_name, [:brand, :model_name, :fuel_type], :unique => true
如果多个数据库连接同时执行写操作,则在数据库级别添加唯一约束是有意义的。
答案 2 :(得分:4)
我会这样做:
validates_uniqueness_of :model_name, :scope => {:brand_id, :fuel_type_id}
因为它对我来说更有意义:
但这是主观意见。
当然,如果brand和fuel_type是与其他模型的关系(如果没有,那么只需删除“_id”部分)。使用唯一性验证,您无法检查非db列,因此您必须在模型中验证外键。
您需要定义哪个属性已经过验证 - 您不会立即验证所有属性,如果需要,您需要为每个属性创建单独的验证,因此当用户犯错误并尝试创建重复记录时,您需要显示他在无效领域附近的形式错误。
答案 3 :(得分:4)
使用新的哈希模式向Rails 4添加正确的代码
validates :column_name, uniqueness: {scope: [:brand_id, :fuel_type_id]}
答案 4 :(得分:2)
将此验证方法与ActiveRecord::Validations#save
结合使用并不能保证不会出现重复的记录插入,因为应用程序级别的唯一性检查本质上容易出现竞争条件。
如果您使用具有“可序列化”隔离级别的事务,甚至可能会发生这种情况。解决此问题的最佳方法是使用ActiveRecord::ConnectionAdapters::SchemaStatements#add_index
向数据库表添加唯一索引。在极少数情况下发生竞争条件时,数据库将保证该字段的唯一性。
答案 5 :(得分:1)
将其他答案拼凑在一起,然后自己尝试,这是您要查找的语法:
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
我不确定为什么其他答案将validates :brand, uniqueness: { scope: [:model_name, :fuel_type] }
添加到范围中的字段。仅当这些字段代表其他模型时才需要这样做,但是我没有在问题中看到任何指示。此外,这些字段可以按任何顺序排列。这将完成相同的操作,只有错误将在_id
属性而不是:model_name
上:
:brand