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!
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. 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.