validates_uniqueness_of :name, :case_sensitive => false
hace el truco, pero se debe tener en cuenta que validates_uniqueness_of
no no garantizar la unicidad si tiene varios servidores / los procesos del servidor (por ejemplo, correr pasajeros Phusion, múltiples mestizos, etc.) o un servidor multi-roscado. Eso es porque puede obtener esta secuencia de eventos (el orden es importante):
- El proceso A recibe una solicitud para crear un nuevo usuario con el nombre 'foo'
- El proceso B hace lo mismo
- El proceso A valida la unicidad de 'foo' preguntando al DB si ese nombre existe todavía y el DB dice que el nombre aún no existe.
- El proceso B hace lo mismo y obtiene la misma respuesta
- El proceso A envía la
insert
declaración para el nuevo registro y tiene éxito
- Si tiene una restricción de la base de datos que requiere unicidad para ese campo, el proceso B enviará la
insert
declaración para el nuevo registro y fallará con una fea excepción de servidor que regresa del adaptador SQL. Si no tiene una restricción de base de datos, la inserción se realizará correctamente y ahora tiene dos filas con 'foo' como nombre.
Consulte también "Concurrencia e integridad" en la validates_uniqueness_of
documentación de Rails.
De Ruby on Rails 3rd Edition :
... a pesar de su nombre, validates_uniqueness_of no garantiza realmente que los valores de columna sean únicos. Todo lo que puede hacer es verificar que ninguna columna tenga el mismo valor que el del registro que se está validando en el momento en que se realiza la validación. Es posible que se creen dos registros al mismo tiempo, cada uno con el mismo valor para una columna que debe ser única, y que ambos registros pasen la validación. La forma más confiable de hacer cumplir la singularidad es con una restricción a nivel de base de datos ".
Consulte también la experiencia de este programador con validates_uniqueness_of
.
Una de las formas en que esto sucede comúnmente es el envío doble accidental de una página web al crear una nueva cuenta. Este es difícil de resolver porque lo que el usuario recuperará es el segundo (feo) error y le hará pensar que su registro falló, cuando en realidad fue exitoso. La mejor manera que he encontrado para evitar esto es simplemente usar javascript para tratar de evitar la doble presentación.