Search code examples
ruby-on-railsvalidationunique

Ruby on Rails Validation Issues for Multiple Fields


I'm having some problem with validations for multiple fields, specifically with case-sensitive unique validations as well as the error message.

Let's say I want to ensure that the following field combinations are unique and are case-sensitive (Mary == mary) in my [Postgres] db:

user_id
first_name
last_name

As an example
{4,Mary,Smith}
{4,mary,Smith}
should not save.

I know I need to do 2 things:
1. Create unique index in db
2. validate_uniqueness_of in my model

  1. For the index, I created it though I did not find a way to ensure case-sensitivity (from my reading, it seems that MySQL is while Postgres is not). I'll consider this done unless someone has an idea of how to do this.
  2. I have the following code in my model:
     
   validates_uniqueness_of :user_id,
                :case_sensitive => false,
                :scope => [:first_name, :last_name],
                :if => :name_subcat_is_name?,
                :message => "You have already saved this contact information combination."

The problem is that the case-sensitivity seems to only apply to user_id, and not also first and last names. So how can I apply case-sensitivity to the validation for all the fields?

Also, my error msg includes the name of the model:

User You have already saved this contact information combination.

I tried using yaml but it didn't remove the "User" class. I found this but don't know how to make it check all my fields rather than just one. How can I add all the fields into a scope and see if that scope is ":taken"?


UPDATE 1 June 24, 2012:
Using my own validation method sounds like exactly what I need but I'm having some trouble implementing the code. The MyModel.find(:first) method has been depreciated, so I tried substituting it with this:

existing_record = ContactInfo.where(:conditions => ["first_name ILIKE ? AND last_name ILIKE ?", first_name, last_name]) 

But when it gets to the next line

unless existing_record.blank? 

I get an error:

PG::Error: ERROR:  column contact_infos.conditions does not exist
LINE 1: SELECT COUNT(*) FROM "contact_infos"  WHERE "contact_infos"....
SELECT COUNT(*) FROM "contact_infos"  WHERE "contact_infos"."conditions" IN ('first_name ILIKE ? AND last_name ILIKE ?', 'mary', 'Smith')

Solution

  • You could define your own validation method to do this. It could look something like:

    validate :user_id_uniqueness
    
    def user_id_uniqueness
      return unless name_subcat_is_name?
    
      existing_record = MyModel.find(:first, :conditions => ["first_name ILIKE ? AND last_name ILIKE ?", first_name, last_name])
      unless existing_record.blank?
        errors.add(:user_id, "has already been saved in this contact information combination")
      end
    end
    

    ('ILIKE' is specific to Postgresql)

    Hope this helps!