# ActiveRecord validate uniqueness case sensitivity: variazioni

**URL:** <https://www.ruby-forum.com/t/activerecord-validate-uniqueness-case-sensitivity-variazioni/220711>\
**Category:** IT\
**Created:** [June 18, 2012, 9:05am UTC](https://www.ruby-forum.com/t/activerecord-validate-uniqueness-case-sensitivity-variazioni/220711 "2012-06-18T09:05:46Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![aris](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/a/258eb7/32.png) [@aris](https://www.ruby-forum.com/u/aris)\
**Post date:** [June 18, 2012, 9:05am UTC](https://www.ruby-forum.com/t/activerecord-validate-uniqueness-case-sensitivity-variazioni/220711/1 "2012-06-18T09:05:46Z")

</div>

Eil,

mi trovo con un rdbms rompiballe che non distingue tra maiuscole e  
minuscole, e che quindi mi da lo stesso risultato quando faccio

select 1 from records where column = ‘loL’  
select 1 from records where column = ‘Lol’  
select 1 from records where column = ‘lOl’

C’ un simpatico indice sulla colonna, e ovviamente il db mi scoppia  
in mano quando provo a fare INSERT di due stringhe uguali.

Voglio validare l’unicit di un campo. Chiaramente:

validates :column, :uniqueness

apparentemente, questo mi risulta in due operazioni: un check sul db,  
e un’altro in ruby land.  
Ergo, il db mi risponde indifferentemente qualunque sia il case, ma  
poi in ruby non funziona perch normalmente “FOO” e “foo” sono  
diversi.

A me, visto che comunque serve che siano uguali indifferentemente dal  
case, andrebbe bene usare

validates :column, :uniqueness =\> {:case\_sensitive =\> false}

ma questo mi risulta in una

select 1 from records where LOWER(column) = LOWER(‘lol’)

che plausibilmente dovrebbe essere la stessa cosa, visto che l’indice  
case insensitive, ma concretamente mi risulta nei log come una query  
non indicizzata e mi crea un sacco di righe inutili.

Qualcuno ha visto una situazione simile, ed a conoscenza di una cosa  
tipo

validates :column, :uniqueness =\> { :case\_sensitive =\> {:db =\>  
:dontcare, :ruby =\> :ignorecase} }

?

(peraltro ora che vedo i sorgenti di AR 3.2 non c’ un check in ruby  
land _eppure_ son sicuro di avere un test che dimostra sto doppio  
check)

–  
twitter: @riffraff  
blog (en, it): www.riffraff.info [riffraff.blogsome.com](http://riffraff.blogsome.com)  
work: [circleme.com](http://circleme.com)

---

<div class="post-metadata">

**Author:** ![gabriele\_renzi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/e19b73/32.png) [@gabriele\_renzi](https://www.ruby-forum.com/u/gabriele_renzi)\
**Post date:** [June 18, 2012, 9:18am UTC](https://www.ruby-forum.com/t/activerecord-validate-uniqueness-case-sensitivity-variazioni/220711/2 "2012-06-18T09:18:38Z")

</div>

2012/6/18 gabriele renzi [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)

> select 1 from records where LOWER(column) = LOWER(‘lol’)
> 
> che plausibilmente dovrebbe essere la stessa cosa, visto che l’indice  
> case insensitive, ma concretamente mi risulta nei log come una query  
> non indicizzata e mi crea un sacco di righe inutili.

Non conosco nessun modo per fare l’ignore solo in rubyland. Immagino che  
il  
db non ti permetta di creare un indice sul risultato della funzione  
lower?  
(sono quasi certo che postgresql e oracle lo permettano).

Come workaround non particolarmente bello, potresti aggiungere una  
colonna  
‘column\_lower’ che ha dentro il dato denormalizzato dell’operazione  
lower(column) e mettere l’indice su questa nuova colonna. Da quanto ho  
capito ad esempio mysql deve fare un full table scan quando usi funzioni  
SQL su una colonna indicizzata.

Stefano

---

<div class="post-metadata">

**Author:** ![gabriele\_renzi](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/g/e19b73/32.png) [@gabriele\_renzi](https://www.ruby-forum.com/u/gabriele_renzi)\
**Post date:** [June 21, 2012, 9:34am UTC](https://www.ruby-forum.com/t/activerecord-validate-uniqueness-case-sensitivity-variazioni/220711/3 "2012-06-21T09:34:09Z")

</div>

Potresti sistemarti il dato per non far arrabbiare il db es.

before\_validation :force\_downcase

private  
def force\_downcase  
self.pippo.downcase! if attribute\_present?(“pippo”)  
end
