ActiveRecord's validates_uniqueness_of
is vulnerable to race conditions. To really ensure uniqueness requires additional safeguards. One suggestion from the ActiveRecord RDocs is to create a unique index on the database, for example by including in your migrations:
add_index :recipes, :name, :unique => true
This will ensure at the database level that the name is unique. But a disadvantage to this approach is that the ActiveRecord::StatementInvalid
exception returned on attempting to save a duplicate is not very useful. One cannot be sure when catching this exception that the error was generated by a duplicate record and not just by broken SQL.
One solution, as the RDocs suggest, is to parse the message that comes with the exception and try to detect words like "duplicate" or "unique", but this is kludgy and the message is database backend specific. For SqlLite3, my understanding is that the message is totally generic and cannot be parsed this way at all.
Given that this is a fundamental problem for ActiveRecord users, it would be nice to know if there is any standard approach to handling these exceptions. I will offer my suggestion below; please comment or provide alternatives; thanks!