Madhan
Madhan

Reputation: 506

Performing a function to check for duplicates before saving the record in the model in Rails

This is what I have in my model. I want to check for duplicate records and I cant just use a unique index for a field since the contacts are unique per job) I am unable to do this using the following code. Am I doing it wrong? Any help is appreciated. Thanks!

before_save :check_for_duplicates?

def check_for_duplicates?
  JobsPeople.find(:all, :conditions => ["job_id = ? and contact_id = ?", self.job_id, self.contact_id])
end

Upvotes: 2

Views: 7226

Answers (2)

Cluster
Cluster

Reputation: 5617

Callbacks don't do anything more than run the code you tell them to run. If you want to prevent something from executing you have two options, use a validation or raise an error.

In your current code you could check if that query you ran returns anything, and then raise an error if it does. The error will bubble up to the transaction that is wrapping the save and trigger a rollback, then propagate the error into your code where you can handle it if you want.

before_save :check_for_duplicates?

def check_for_duplicates?
  if JobsPeople.find(:all, :conditions => ["job_id = ? and contact_id = ?", self.job_id, self.contact_id]).any?
    raise 'some error'
  end
end

Although there is already a built-in uniqueness validator that handles this situation

validates :job_id, :uniquness => {:scope => :contact_id, :message => 'must be unique per contact}

Of course this should still be backed up with a composite unique index in the database as there is a potential race condition, the likelihood of which depends largely on the behavior of your application.

# in a migration

add_index :table_name, [:job_id, :contact_id], :unique => true, :name => 'index_job_id_and_contact_id_on_table_name'

Upvotes: 7

aNoble
aNoble

Reputation: 7072

I believe this should do what you want

class JobsPeople
  validates_uniqueness_of :contact_id, scope: :job_id
end

Upvotes: 7

Related Questions