Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails: Validate unique combination of 3 columns

Hi I wan't to validate the 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 then want is to validate if a record is unique based on the combination of those 3. An example:

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

Should all be valid. But another record with 'Audi, A6, Gas' should NOT be valid.

I know of this validation, but I doubt that it actually does what I want.

    validates_uniqueness_of :brand, :scope => {:model_name, :fuel_type}
like image 228
Niels Kristian Avatar asked Sep 15 '11 09:09

Niels Kristian


3 Answers

There is a syntax error in your code snippet. The correct validation is :

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]
like image 71
alup Avatar answered Nov 03 '22 05:11

alup


Depends on your needs you could also to add a constraint (as a part of table creation migration or as a separate one) instead of model validation:

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

Adding the unique constraint on the database level makes sense, in case multiple database connections are performing write operations at the same time.

like image 18
Alexander Avatar answered Nov 03 '22 05:11

Alexander


To Rails 4 the correct code with new hash pattern

validates :column_name, uniqueness: {scope: [:brand_id, :fuel_type_id]}
like image 5
Ruby Junior Dev Avatar answered Nov 03 '22 07:11

Ruby Junior Dev