ActiveRecord validates_uniqueness_of
es vulnerable to race conditions. Para garantizar realmente la singularidad, se requieren garantías adicionales. Una sugerencia de la ActiveRecord RDocs es crear un índice único en la base de datos, por ejemplo, al incluir en sus migraciones:¿Cómo puedo determinar si mi objeto ActiveRecord infringe una clave/índice de base de datos única?
add_index :recipes, :name, :unique => true
Esto asegurará a nivel de base de datos que el nombre es único. Pero una desventaja de este enfoque es que la excepción ActiveRecord::StatementInvalid
devuelta al intentar guardar un duplicado no es muy útil. Uno no puede estar seguro al detectar esta excepción que el error fue generado por un registro duplicado y no solo por un SQL quebrado.
Una solución, como sugieren los RDOCs, es analizar el mensaje que viene con la excepción e intentar detectar palabras como "duplicado" o "único", pero esto es kludgy y el mensaje es específico del back-end de la base de datos. Para SqlLite3, entiendo que el mensaje es totalmente genérico y no se puede analizar de esta manera.
Dado que este es un problema fundamental para los usuarios de ActiveRecord, sería bueno saber si existe algún enfoque estándar para manejar estas excepciones. Voy a ofrecer mi sugerencia a continuación; por favor comente o brinde alternativas; ¡Gracias!
Implementé esto y parece hacer el trabajo. Tentado de sacar validates_uniqueness ya que esto esencialmente hace lo mismo más eficientemente. Publicará cualquier actualización relevante. – Chinasaur
Un pequeño detalle: recibes el error incorrecto si el duplicado se elimina entre obtener la excepción y consultar el duplicado. – mpartel