我有一个验证order_number值唯一性的rails模型,它们应该从1_000_000开始,所以我添加了一个变量用作第一个值:
# order model
STARTING_NUMBER = 1_000_000
validates :order_number, uniqueness: true
当我用Rubocop检查我的代码时,我有一个错误:
app/models/order.rb:3:3: C: Rails/UniqueValidationWithoutIndex: Uniqueness validation should be with a unique index.
validates :order_number, uniqueness: true
我通过添加disable/enable
Rubocop注释来修复它:
STARTING_NUMBER = 1_000_000
# rubocop:disable Rails/UniqueValidationWithoutIndex
validates :order_number, uniqueness: true
# rubocop:enable Rails/UniqueValidationWithoutIndex
有更好的解决方案吗?
正确的修复方法是通过迁移向数据库添加唯一索引:
def change
add_index :orders, :order_number, unique: true
end
这将解决潜在的问题,并使Rubocop不再抱怨。
来自精美的Rubocop手册:
当您在Active Record模型中定义唯一性验证时,您还应该为列添加一个唯一索引。有两个原因:第一,即使定义了Active Record的验证,也可能出现重复的记录。第二,它会导致查询缓慢。
Rubocop看到你有一个唯一性验证,但没有在你的db/schema.rb
中找到相应的唯一索引。模型中的唯一性验证受制于竞争条件,因此您仍然可以得到重复的值。
Rubocop告诉你在数据库中添加一个唯一的索引/约束来确保唯一性。Rails指南也是这么说的:
它不会在数据库中创建唯一性约束,因此可能会发生两个不同的数据库连接为您希望唯一的列创建具有相同值的两个记录。为了避免这种情况,您必须在数据库的该列上创建唯一的索引。
验证也会做一个潜在的昂贵的数据库查询,所以你真的想索引那列,最好让它成为一个唯一的索引,以确保数据的完整性,当你在它(破碎的代码是暂时的,破碎的数据是永远的)。
不要压制警告,解决它。