• RSS
  • Delicious
  • Digg
  • Facebook
  • Twitter
  • Linkedin
  • Youtube

Single Table Inheritance validates_uniqueness_of Problem

Consider a case of STI where:

class User < ActiveRecord::Base
  validates_uniqueness_of :name
end

class Customer < User

end

class Manager < User

end

Now try following at console:

User.create(:name => "Akhil Bansal")
Manager.create(:name => "Akhil Bansal")
Customer.create(:name => "Akhil Bansal")

This will let you create three records in users table with same name, validates_uniqueness_of written in User class has no effect on it. validates_uniqueness_of automatically scoped with class names, that means it will not let you create two managers with same name or two customers with same name or two users with same name.

If you want uniqueness of an attribute in overall table, put the following code in some file in your lib dir and require that file in environment:

module ActiveRecord
  module Validations
    module ClassMethods
      # Intended for use with STI tables, helps ignore the type field
      def validates_overall_uniqueness_of(*attr_names)
        configuration = { :message => "has already been taken" }
        configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
        validates_each(attr_names, configuration) do |record, attr_name, value|
          records = self.find(:all, :conditions=> ["#{attr_name} = ?", value])
          record.errors.add(attr_name, configuration[:message]) if records.size > 0 and records[0].id != record.id
        end
      end
    end
  end
end

And then use validates_overall_uniqueness_of instead of validates_uniqueness_of.

3 Responses so far.

  1. Maciej K says:

    When you define methods this way, there is no such problem:

    class User

  2. João Vitor says:

    Thanks,
    I got this error and your solution worked here.

  3. John says:

    You are the man


Github2S3: Backup Github Repositori...

Cross Posted from http://vinsol.com/blog Who doesn't know GitHub now a days, ...

Edge Rails: Time#current...

Returns Time.zone.now when config.time_zone is set, otherwise just returns Time.now

Edge Rails: Array#random_element...

Array#rand is deprecated in favor of Array#random_element and will be ...

Edge Rails Updates...

New edge rails deprecations: Time#last_year is deprecated in favor of Time#prev_year Time#last_month ...

Download recursive directories with...

Using ftp to download multiple files using 'mget' command is ...

Edge Rails: Time#current...

Returns Time.zone.now when config.time_zone is set, otherwise just returns Time.now

Edge Rails: Array#random_element...

Array#rand is deprecated in favor of Array#random_element and will be ...

Edge Rails Updates...

New edge rails deprecations: Time#last_year is deprecated in favor of Time#prev_year Time#last_month ...

uninitialized constant ActionMailer...

Just a quick note, If you are getting "uninitialized constant ...

11 Things to Consider Before Deploy...

Cross Posted from http://vinsol.com/blog At VinSol, we have been ...