ActiveRecord's validates_uniqueness_of
è vulnerable to race conditions. Assicurare davvero l'unicità richiede ulteriori salvaguardie. Un suggerimento dal ActiveRecord rdocs è quello di creare un indice univoco nel database, ad esempio includendo nelle migrazioni:Come posso determinare se il mio oggetto ActiveRecord viola una chiave/indice di database univoco?
add_index :recipes, :name, :unique => true
Questo assicurerà a livello di database che il nome sia univoco. Ma uno svantaggio di questo approccio è che l'eccezione ActiveRecord::StatementInvalid
restituita nel tentativo di salvare un duplicato non è molto utile. Non si può essere sicuri quando si rileva questa eccezione che l'errore è stato generato da un record duplicato e non solo da SQL rotto.
Una soluzione, come suggerito da RDocs, è di analizzare il messaggio che viene fornito con l'eccezione e provare a rilevare parole come "duplicate" o "unique", ma questo è kludgy e il messaggio è specifico del back-end del database. Per SqlLite3, la mia comprensione è che il messaggio è totalmente generico e non può essere analizzato in questo modo.
Dato che questo è un problema fondamentale per gli utenti di ActiveRecord, sarebbe bello sapere se esiste un approccio standard per gestire queste eccezioni. Offrirò il mio suggerimento qui sotto; si prega di commentare o fornire alternative; Grazie!
Ho implementato questo e sembra di portare a termine il lavoro. Tentativo di prendere validates_uniqueness poiché questo essenzialmente fa la stessa cosa in modo più efficiente. Pubblicherà qualsiasi aggiornamento pertinente. – Chinasaur
Un nitpick molto piccolo: si ottiene l'errore sbagliato se il duplicato viene eliminato tra ottenere l'eccezione e interrogare per il duplicato. – mpartel