Topic: validates_uniqueness_of can't be class agnostic?

I've got a table full of users and I'm trying to use validates_uniqueness_of on the username column.  All records are from derived STI classes but I put most of the model definition into the parent User class:

class User < ActiveRecord::Base
  validates_uniqueness_of   :username
end
class Writer < User
end
class Reader < User
end

.


I'm attempting to get this validation check to work at the topmost scope, but it's not working:

w = Writer.new
w.username = 'danger'
w.save     # => true
r = Reader.new
r.username = 'danger'
r.save     # => true

.


ActiveRecord is automatically assigning the scope to my derived class:

Writer Load (0.015708)   SELECT * FROM users WHERE (users.username = 'danger') AND ( (users.`type` = 'Writer' ) ) LIMIT 1
Reader Load (0.015708)   SELECT * FROM users WHERE (users.username = 'danger') AND ( (users.`type` = 'Reader' ) ) LIMIT 1

.


I've tried using

validates_uniqieness_of :username, :scope => nil

but that doesn't do anything.  Any ideas how to work around this issue?

Last edited by danger (2006-08-25 21:12:01)

Re: validates_uniqueness_of can't be class agnostic?

Looks like I figured out the answer.  validates_uniqueness_of is simply too limited to allow for any customization so using a more flexible validation rule is in order:

  validates_each :username do |record, attr, value|
    record.errors.add attr, 'is already in use.' if User.find(:first, :conditions => ["#{attr} = ?", value])
  end

Last edited by danger (2006-08-25 21:11:41)

Re: validates_uniqueness_of can't be class agnostic?

Whoops, I soon realized that wouldn't work.  Here's a version that excludes the current record:

  validates_each :username do |record, attr, value|
    found = record.new_record? ?
      User.find(:first, :conditions => ["#{attr} = ?", value]) :
      User.find(:first, :conditions => ["#{attr} = ? AND id <> ?", value, record.id])
    record.errors.add attr, 'is already in use.' if found
  end

Last edited by danger (2006-08-25 21:11:34)