tommers
tommers

Reputation: 51

How to validate unique combinations of two column values in Rails

I have an application where I track rivalries between football clubs. But I just want each rivalry to be registered once in the Database

I've added this to my model:

class Rivalship < ApplicationRecord
belongs_to :team
belongs_to :rival, :class_name => "Team"

validates_uniqueness_of :team_id, :scope => :rival_id
end

and this to my DB:

class AddUniqueConstraintsForRivalships < ActiveRecord::Migration[6.1]

  def change
    add_index :rivalships, [:rival_id, :team_id], unique: true, algorithm: :concurrently
  end
end

But this only prevents identical records from being stored in the database. Ex, in the following scenario, the second record will not be stored as validation will fail.

team_id: 10 | rival_id: 20 (saved)

team_id: 10 | rival id: 20 (not saved, identical record)

But how do can I also prevent this from happening? Were the combination of rival_id and team_id already exist in the DB

team_id: 10 | rival_id: 20 (saved)

team_id: 20 | rival id: 10 (identical combination, how do I prevent this from being saved?)

Upvotes: 0

Views: 312

Answers (1)

B Seven
B Seven

Reputation: 45941

You can use a Custom Validation Method :

validate :validate_team_rival_uniqueness

def validate_team_rival_uniqueness
  if Rivalship.find_by(team_id: rival.id, rival_id: team.id)
    errors.add(:base, "Inverse combination already exists")
  end
end 

Reference: https://guides.rubyonrails.org/active_record_validations.html#custom-methods

You'll still need

validates_uniqueness_of :team_id, :scope => :rival_id

But you can push this into the Custom Validation if you want...

Upvotes: 1

Related Questions