Rails: 验证3列的唯一组合

嗨,我不想验证我的表中3列的唯一组合。

假设我有一个名为 car 的表,其值为: brand、 : model _ name 和: fuel _ type。

然后,我想要验证的是,如果一个记录是唯一的基于这3个组合。举个例子:

    brand    model_name    fuel_type
Audi     A4            Gas
Audi     A4            Diesel
Audi     A6            Gas

应该都是有效的。但另一个记录与’奥迪,A6,天然气’不应该是有效的。

我知道这种验证,但我怀疑它是否真的能达到我想要的效果。

    validates_uniqueness_of :brand, :scope => {:model_name, :fuel_type}
35248 次浏览

我会这样做:

validates_uniqueness_of :model_name, :scope => {:brand_id, :fuel_type_id}

因为这对我来说更有意义:

  • “品牌”和“燃料类型”的组合不应有重复的“型号名称”,相对于
  • “车型名称”和“燃料类型”的组合不应该有重复的“品牌”

但这是主观的看法。

当然,如果 brand 和 fuel _ type 是与其他模型的关系(如果不是,那么删除“ _ id”部分)。通过唯一性验证,您无法检查非 db 列,因此必须验证模型中的外键。

你需要定义哪个属性被验证——你不需要一次验证所有属性,如果你想,你需要为每个属性创建单独的验证,所以当用户出错并试图创建重复记录时,你在无效字段附近用表单显示错误。

代码片段中有一个语法错误。正确的验证是:

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]

使用 铁轨4,你可以使用:

validates :car_model_name, uniqueness: { scope: [:brand_id, :fuel_type_id] }

铁轨5你可以使用

validates_uniqueness_of :car_model_name, scope: %i[brand_id fuel_type_id]

根据您的需要,您还可以添加一个约束(作为表创建迁移的一部分或作为一个单独的约束) ,而不是模型验证:

add_index :the_table_name, [:brand, :model_name, :fuel_type], :unique => true

如果多个数据库连接同时执行写操作,那么在数据库级别上添加唯一约束是有意义的。

向 Rails 4提供具有新散列模式的正确代码

validates :column_name, uniqueness: {scope: [:brand_id, :fuel_type_id]}

ActiveRecord::Validations#save一起使用这种验证方法并不能保证不存在重复的记录插入,因为应用程序级别上的唯一性检查本身就容易出现竞争条件。

如果使用具有“可序列化”隔离级别的事务,甚至可能出现这种情况。解决此问题的最佳方法是使用 ActiveRecord::ConnectionAdapters::SchemaStatements#add_index向数据库表添加唯一索引。在出现竞态条件的罕见情况下,数据库将保证字段的唯一性。

把其他答案拼凑起来,然后自己试试,这就是你要找的语法:

validates :brand, uniqueness: { scope: [:model_name, :fuel_type] } < br > < br > 我不确定为什么其他的答案会将 _id添加到作用域中的字段中。只有当这些字段表示其他模型时才需要这样做,但我在问题中没有看到这方面的迹象。此外,这些字段可以按任意顺序排列。这将完成同样的事情,只是错误出现在 :model_name属性上,而不是 :brand: < br > < br > validates :model_name, uniqueness: { scope: [:fuel_type, :brand] }