Forum: Italian Ruby user group ActiveRecord validate uniqueness case sensitivity: variazioni

Posted by gabriele renzi (Guest)
on 2012-06-18 09:05
(Received via mailing list)
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
work: circleme.com
Posted by Stefano Pigozzi (Guest)
on 2012-06-18 09:18
(Received via mailing list)
2012/6/18 gabriele renzi <rff.rff@gmail.com>

> 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
Posted by Marco Mastrodonato (marcomd)
on 2012-06-21 09:34
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
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.