Rubocop 唯一性验证应该使用唯一索引,在从某些特定值开始的值中

Rubocop Uniqueness validation should be with a unique index, in values that start from some specific values

我有一个 rails 模型来验证 order_number 值的唯一性,应该从 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 抱怨。


来自fine Rubocop manual

When you define a uniqueness validation in Active Record model, you also should add a unique index for the column. There are two reasons First, duplicated records may occur even if Active Record’s validation is defined. Second, it will cause slow queries.

Rubocop 发现您进行了唯一性验证,但未在 db/schema.rb 中找到相应的唯一索引。模型中的唯一性验证受竞争条件的影响,因此您仍然可以获得重复值。

Rubocop 告诉您在数据库中添加一个唯一的 index/constraint 以确保唯一性。 Rails guides 说同样的话:

It does not create a uniqueness constraint in the database, so it may happen that two different database connections create two records with the same value for a column that you intend to be unique. To avoid that, you must create a unique index on that column in your database.

验证还将执行一个可能代价高昂的数据库查询,因此您确实想为该列编制索引,不妨将其设置为唯一索引以确保数据完整性(损坏的代码是暂时的,损坏的数据是永恒的)。

不要抑制警告,解决它。