I am trying to validate the uniqueness of my indexes (2 indexes) in a
table before an insert. Can I use validate_uniqueness_of to do this? It
seems it can only validate uniqueness for a column, but not for a
combination of 2 or more.
Example: a table has a PK of column#1 and column#2.
Make a unique index in the database, and write this:
begin
ModelName.create
rescue Exception => e
interrogate e to determine what sort of failure it was
and take the appropriate action.
end
This is the right way to do this. Testing before insert doesn’t
work because it’s possible that after you test, but before you
insert, another process may have inserted a duplicate!
–
– Tom M., CTO
– Engine Y., Ruby on Rails Hosting
– Reliability, Ease of Use, Scalability
– (866) 518-YARD (9273)
:message => ‘There is already another user with this email address.’
It sounds like if your PK is made of two columns you might want to
just override before_validation(). Rails has never had great
composite key functionality although I think there are some plugins
out there that might ease the pain…
Make a unique index in the database, and write this:
begin
ModelName.create
rescue Exception => e
interrogate e to determine what sort of failure it was
and take the appropriate action.
end
This is the right way to do this. Testing before insert doesn’t
work because it’s possible that after you test, but before you
insert, another process may have inserted a duplicate!
–
– Tom M., CTO
– Engine Y., Ruby on Rails Hosting
– Reliability, Ease of Use, Scalability
– (866) 518-YARD (9273)
I agree with Tom that defining a unique key in your DB and letting the
DB enforce it is the best way to go.
I question the usefulness of validates_uniqueness_of in general because:
validates_uniqueness_of can’t guarantee that the field you are about
to save to the DB is indeed unique (as Tom explained)
validates_uniqueness_of needs to query the DB in order to validate
your model, which defeats the whole purpose of an application-side
validation (IMO)
I started a discussion about this on my blog, and no one has
successfully made a case for using validates_uniqueness_of yet. If
anybody out there does have a scenario where it makes sense to use this
validation, please let me know so I can stop criticizing it http://allyourdatabase.blogspot.com/2006/11/generating-activerecord-data.html
I agree with Tom that defining a unique key in your DB and letting the
Bryan,
I think validates_uniqueness_of does have a “valid” place. It lets
you keep your code DRY and works in 99.999% of the cases. It only
fails in the very rare case where another insert occurs after one
thread (or mongrel process) has checked for uniqueness. In that very
rare case the db’s unique index would catch it and the database would
stay valid. The only side effect is that the app would render an
error page to the user. I’m willing to bet that this would likely
never happen until a site got really big, and in even then it would
have to be the perfect storm.
I tried using drysql for my application (http://drysql.rubyforge.org/
for my guide) and kept getting this NameError message.
I have a table called “room_types” and a class called “RoomType”
My controller looks like:
def new
require_gem ‘drysql’ @room_type = RoomType.new
end
My model looks like:
class RoomType < ActiveRecord::Base
set_table_name “room_types”
end
Any insight to this matter is much appreciated,
Will T.
Bryan E. wrote:
Tom M. wrote:
Make a unique index in the database, and write this:
begin
ModelName.create
rescue Exception => e
interrogate e to determine what sort of failure it was
and take the appropriate action.
end
This is the right way to do this. Testing before insert doesn’t
work because it’s possible that after you test, but before you
insert, another process may have inserted a duplicate!
–
– Tom M., CTO
– Engine Y., Ruby on Rails Hosting
– Reliability, Ease of Use, Scalability
– (866) 518-YARD (9273)
I agree with Tom that defining a unique key in your DB and letting the
DB enforce it is the best way to go.
I question the usefulness of validates_uniqueness_of in general because:
validates_uniqueness_of can’t guarantee that the field you are about
to save to the DB is indeed unique (as Tom explained)
validates_uniqueness_of needs to query the DB in order to validate
your model, which defeats the whole purpose of an application-side
validation (IMO)
Evaluating the validation on a more subjective criterion, I don’t
believe that using validates_uniqueness_of provides any DRYness to my
application code that can’t be achieved by extending ActiveRecord::Base
to handle a duplicate key error returned from the DB. Given that
validates_uniqueness_of needs to be defined multiple times in your
application code (once for each unique key), I think that defining a
generic duplicate key error handler in ActiveRecord::Base is actually a
more DRY approach, but I suppose that it is a matter of personal taste.
I agree. If only the databases and their drivers provided these info in
a
more standard, accessible way. I tried parsing postgres contraint
violation
errors and it’s a real pain to deduce which table and columns were
affected,
especially since these messages are locale dependent and change between
versions.
That said, a common way to introspect database errors in addition to
tables + columns would be wonderful.
Evaluating the validation on a more subjective criterion, I don’t
believe that using validates_uniqueness_of provides any DRYness to my
application code that can’t be achieved by extending ActiveRecord::Base
to handle a duplicate key error returned from the DB. Given that
validates_uniqueness_of needs to be defined multiple times in your
application code (once for each unique key), I think that defining a
generic duplicate key error handler in ActiveRecord::Base is actually a
more DRY approach, but I suppose that it is a matter of personal taste.
I agree. If only the databases and their drivers provided these info in
a
more standard, accessible way. I tried parsing postgres contraint
violation
errors and it’s a real pain to deduce which table and columns were
affected,
especially since these messages are locale dependent and change between
versions.
That said, a common way to introspect database errors in addition to
tables + columns would be wonderful.
jeremy
Good point, Jeremy.
I think you’ve identified a hole in my argument
I agree with Tom that defining a unique key in your DB and letting the
Bryan,
I think validates_uniqueness_of does have a “valid” place. It lets
you keep your code DRY and works in 99.999% of the cases. It only
fails in the very rare case where another insert occurs after one
thread (or mongrel process) has checked for uniqueness. In that very
rare case the db’s unique index would catch it and the database would
stay valid. The only side effect is that the app would render an
error page to the user. I’m willing to bet that this would likely
never happen until a site got really big, and in even then it would
have to be the perfect storm.
I agree with you that it would be a rare occurrance for a duplicate
value to be inserted into the DB after ActiveRecord does the uniqueness
check and before it actually saves your record.
However, it is possible. As well, your DB already does a duplicate key
check on insert/update (assuming that you defined a unique key on the
DB), so the uniqueness check done by the validation is redundant
database I/O and can’t be guaranteed to be accurate. In terms of
functionality and performance, using the validation actually seems to me
to be detrimental to an application, rather than beneficial.
Evaluating the validation on a more subjective criterion, I don’t
believe that using validates_uniqueness_of provides any DRYness to my
application code that can’t be achieved by extending ActiveRecord::Base
to handle a duplicate key error returned from the DB. Given that
validates_uniqueness_of needs to be defined multiple times in your
application code (once for each unique key), I think that defining a
generic duplicate key error handler in ActiveRecord::Base is actually a
more DRY approach, but I suppose that it is a matter of personal taste.
From my perspective, the application-side validations’ prime purpose is
to provide “fast” model validation by avoiding DB I/O. If an
application-side validation needs to perform redundant DB I/O in order
to validate an object, I can’t see the advantage of using it, especially
if it can’t even guarantee model validity.
This is just my opinion, and I respect yours as well.
Cheers.
This forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.