marmeladze
marmeladze

Reputation: 6564

Validating uniqueness of an attribute in two tables/models

I have two different kind of user (devise) models in my Rails application. Doctor and Patient. It was my fault I haven't defined an upper class User and inherit attributes from it. They have a mutual attribute - a personal identification number and I want two check uniqueness of this attribute in both of tables. I've searched a bit and saw this answer.

I've applied things as it written there but it had no effect.

#patient.rb 
class Patient < ActiveRecord::Base

...
  validates_uniqueness_of :pin 
  validate :pin_not_on_doctors

  private

    def pin_not_on_doctors
        Doctor.where(:pin => self.pin).first.nil?
    end
end
#doctor.rb
class Doctor < ActiveRecord::Base

...
  validates_uniqueness_of :pin 
  validate :pin_not_on_patients

  private

    def pin_not_on_patients
        Patient.where(:pin => self.pin).first.nil?
    end
end

First I created a patient instance, then a doctor instance with the same pin I used in my first (patient) case. Rails unexpectedly didn't spit out an error message and created doctor instance, and more interestingly devise also turned a blind eye for duplicate email.

How can I overcome this problem?

Upvotes: 0

Views: 109

Answers (2)

Mangesh Tamhankar
Mangesh Tamhankar

Reputation: 178

In addition to adding the error, try adding a line to return true/false,

Something like,

def pin_not_on_doctors
    errors.add :pin, "already exits" if Doctor.exists?(:pin => self.pin)
    Doctor.exists?(:pin => self.pin)
end

I don't know the details of your app, but in depending on how you're actually creating the object in this case, it might need that.

EDIT: Misread something in the original, looks like your current version is to just return true/false, so this probably doesn't help. Sorry.

Upvotes: 2

Shalev Shalit
Shalev Shalit

Reputation: 1963

You should add the error on the validation function: http://api.rubyonrails.org/classes/ActiveModel/Errors.html

def pin_not_on_doctors
    errors.add :pin, "already exists" if Doctor.exists?(:pin => self.pin)
end

Upvotes: 1

Related Questions