2012-08-04 10 views
9

Estoy tratando de aprender rails [siguiendo el curso SAAS en coursera] y trabajando con la tabla de película simple usando ActiveRecord.Raíles: ActiveRecord db sort operación caso insensible

Quiero mostrar todas las películas con título ordenado. Me gustaría que se ordene insensiblemente.

Traté de hacerlo de esta manera:

Movie.all(:conditions => ["lower(title) = ?", title.downcase],:order => "title DESC") 
=>undefined local variable or method `title' for #<MoviesController:0xb4da9a8> 

Creo que es imposible reconocer inferior (título).

¿Es esta la mejor manera de lograr el tipo de insensibilidad de caso?

Gracias!

Respuesta

16

Uso where y no all

Movie.where("lower(title) = ?", title.downcase).order("title DESC") 

no entienden realmente el tipo embargo. Aquí obtendrá todas las películas con un título inferior igual a title.downcase. Todo es igual, ¿cómo podrías ordenarlo por title desc?

Para ordenar alfabéticamente inverso todas las películas por título en minúsculas:

Movie.order("lower(title) DESC").all 
3

Tener MySQL realizar la operación en mayúsculas o minúsculas cada vez es bastante caro.

Lo que yo recomiendo es tener una columna title y una columna title_lower. De esta manera, puede visualizar y ordenar fácilmente con insensibilidad de mayúsculas y minúsculas en la columna title_lower sin tener MySQL arriba o abajo cada vez que ordena.

Recuerde indexar ambos o al menos title_lower.

5

que tiene que hacer esto:

Movie.order("lower(title) DESC").all 
0

Una solución más robusta es utilizar nodos AREL. Me gustaría recomendar que define un par de ámbitos en el modelo Movie:

scope :order_by_title, -> { 
    order(arel_table['title'].lower.desc) 
} 

scope :for_title, (title)-> { 
    where(arel_table['title'].lower.eq title.downcase) 
} 

y luego llamar Movie.for_title(title).order_by_title

La ventaja sobre otras respuestas enumeradas es que .for_title y .order_by_title no se romperá si el alias de columna o title unirse a otra tabla con una columna title, y se escapó sql.

Como rickypai mentioned, si no tiene un índice en la columna, la base de datos será lenta. Sin embargo, es una forma incorrecta (normal) copiar sus datos y aplicar una transformación a otra columna, porque entonces una columna puede perder sincronía con la otra. Desafortunadamente, las versiones anteriores de mysql no permitían muchos alternatives que no sean desencadenantes. Después de 5.7.5 puede usar el virtual generated columns para hacer esto. Luego, en caso de casos insensibles, simplemente usa la columna generada (lo que hace que el rubí sea más directo).

Postgres tiene un poco más de flexibilidad en este sentido, y le permitirá hacer índices de funciones sin tener que hacer referencia a una columna especial, o puede hacer que la columna sea una columna que no distingue entre mayúsculas y minúsculas.