【问题标题】:Rubocop Uniqueness validation should be with a unique index, in values that start from some specific valuesRubocop 唯一性验证应该使用唯一索引,在从某些特定值开始的值中
【发布时间】:2021-11-18 05:41:55
【问题描述】:

我有一个验证 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 cmets 来修复它:

STARTING_NUMBER = 1_000_000

# rubocop:disable Rails/UniqueValidationWithoutIndex
validates :order_number, uniqueness: true
# rubocop:enable Rails/UniqueValidationWithoutIndex

有没有更好的解决方案?

【问题讨论】:

  • 我已经打开了一个 PR,看看我们是否可以改进对那个警察的描述,使其更清晰,这对你有帮助吗? github.com/rubocop/rubocop-rails/pull/563
  • 谢谢@AndyWaite,是的,会很棒。
  • 更新已合并。

标签: ruby-on-rails ruby rails-activerecord activemodel rubocop


【解决方案1】:

正确的解决方法是通过迁移向数据库添加唯一索引:

def change
  add_index :orders, :order_number, unique: true
end

这将解决根本问题并防止 Rubocop 抱怨。


来自fine Rubocop manual

当您在 Active Record 模型中定义唯一性验证时,您还应该为列添加唯一性索引。有两个原因首先,即使定义了 Active Record 的验证,也可能出现重复记录。其次,会导致查询慢。

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

Rubocop 告诉您在数据库中添加唯一索引/约束以确保唯一性。 Rails guides 也是这么说的:

它不会在数据库中创建唯一性约束,因此可能会发生两个不同的数据库连接为您打算唯一的列创建具有相同值的两条记录。为避免这种情况,您必须在数据库中的该列上创建唯一索引。

验证还会执行潜在的昂贵的数据库查询,因此您确实想为该列建立索引,不妨将其设为唯一索引以确保您使用该列时的数据完整性(损坏的代码是临时的,损坏的数据是永远)。

不要抑制警告,解决它。

【讨论】:

  • 谢谢你的详细解释,现在一切都清楚了。
猜你喜欢
  • 2015-01-17
  • 2012-11-15
  • 1970-01-01
  • 2018-11-06
  • 2022-10-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-05
  • 1970-01-01
相关资源
最近更新 更多