Reputation: 51
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
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