Rails: checking a unique combination of 3 columns

Hi, I do not want to check a unique combination of 3 columns in my table.

Let's say I have a table called cars with the values: brand ,: model_name and: fuel_type.

What I want then is to check if the record is unique based on their combination. Example:

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

All must be valid. But another record with "Audi, A6, Gas" should NOT be valid.

I know this check, but I doubt that she really does what I want.

  validates_uniqueness_of :brand, :scope => {:model_name, :fuel_type} 
+48
ruby-on-rails ruby-on-rails-3
Sep 15 2018-11-11T00:
source share
5 answers

There is a syntax error in the code snippet. Correct check:

 validates_uniqueness_of :car_model_name, :scope => [:brand_id, :fuel_type_id] 

or even shorter in ruby โ€‹โ€‹1.9.x:

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

with rails 4 you can use:

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

with rails 5 you can use

 validates_uniqueness_of :car_model_name, scope: %i[brand_id fuel_type_id] 
+86
Jun 06 2018-12-06T00:
source share

Depending on your needs, you can also add a constraint (as part of a table creation migration or as a separate one) instead of checking the model:

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

Adding a unique restriction on the database level makes sense if several database connections are writing at the same time.

+7
Jan 11 '15 at 18:22
source share

I would do this:

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

because it makes more sense to me:

  • do not duplicate "model names" for the combination of "brand" and "type of fuel", vs
  • โ€œbrandsโ€ should not be duplicated for the combination โ€œmodel nameโ€ and โ€œfuel typeโ€

but this is a subjective opinion.

Of course, if the brand and fuel_type are relationships with other models (if not, then just uncheck the "_id" part). With uniqueness checking, you cannot check non-db columns, so you need to check the foreign keys in the model.

You need to determine which attribute is checked - you do not check everything at once, if you want, you need to create a separate check for each attribute, therefore, when a user makes an error and tries to create a duplicate record, you show his errors in the form near an invalid field.

+4
Sep 15 '11 at 10:07
source share

To Rails 4 correct code with new hash template

 validates :column_name, uniqueness: {scope: [:brand_id, :fuel_type_id]} 
+3
Apr 22 '15 at 17:34
source share

Using this validation method in combination with ActiveRecord::Validations#save does not guarantee that entries are not reentered, because application-level uniqueness checks are inherently subject to race conditions.

This can happen if you use transactions with a "serialization" level. The best way around this problem is to add a unique index to the database table using ActiveRecord::ConnectionAdapters::SchemaStatements#add_index . In the rare case when a race condition occurs, the database guarantees the uniqueness of the field.

+2
Nov 28 '15 at 11:46
source share



All Articles