Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I have a rails model that validates the uniqueness of order_number value, thay should start from 1_000_000, so I added a variable that is used as a first value:

# order model 
STARTING_NUMBER = 1_000_000

validates :order_number, uniqueness: true

When I checked my code by Rubocop I had an error:

app/models/order.rb:3:3: C: Rails/UniqueValidationWithoutIndex: Uniqueness validation should be with a unique index.
  validates :order_number, uniqueness: true

I fixed it by adding disable/enable Rubocop comments:

STARTING_NUMBER = 1_000_000

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

Is there a better solution?

like image 900
Roman Avatar asked Mar 01 '23 10:03

Roman


1 Answers

The proper fix is to add a unique index to your database with a migration:

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

That will fix the underlying problem and keep Rubocop from complaining.


From the 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 sees that you have a uniqueness validation but didn't find a corresponding unique index in your db/schema.rb. A uniqueness validation in a model is subject to race conditions so you can still get duplicate values.

Rubocop is telling you to add a unique index/constraint in the database to ensure uniqueness. The Rails guides say the same thing:

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.

The validation will also do a potentially expensive database query so you really want to index that column anyway, might as well make it a unique index to ensure data integrity while you're at it (broken code is temporary, broken data is forever).

Don't suppress the warning, address it.

like image 84
mu is too short Avatar answered Mar 05 '23 16:03

mu is too short