web-dev-qa-db-fra.com

Comment faire un ordre insensible à la casse dans Rails avec postgresql

Je suis en train de passer mon environnement de développement de sqlite3 à postgresql 8.4 et j'ai un dernier obstacle.

Dans mon original, j'avais la ligne suivante dans une méthode d'aide;

result = Users.find(:all, :order => "name collate NOCASE")

qui a fourni une recherche très sensible à la casse. Je ne peux pas répliquer cela pour postgresql. Devrait être facile - des idées?

Merci.

52
brad
result = Users.find(:all, :order => "LOWER(name)")

Pour reprendre un peu de Brad et Frank.

80
LanceH

Réponse de LanecH adapté pour Rails 3+ (y compris Rails 4 et 5):

users = User.order('LOWER(name)')

Ou créez une étendue nommée que vous pouvez réutiliser:

class User < ActiveRecord::Base
  scope :order_by_name, -> { order('LOWER(name)') }
end

users = User.order_by_name
24
Thomas Klemm

Maintenant avec Rails 5.2 vous obtiendrez probablement un avertissement si vous utilisez la réponse acceptée.

AVERTISSEMENT DE DÉPRÉCIATION: Méthode de requête dangereuse (méthode dont les arguments sont utilisés en tant que SQL brut) appelée avec un ou des arguments sans attribut: "LOWER (?) ASC".

Une alternative pourrait être de s'appuyer sur Arel (il est maintenant fusionné dans Rails):

results = User.order(User.arel_table['name'].lower.asc)
# results.to_sql == "SELECT \"users\".* FROM \"users\" ORDER BY LOWER(\"users\".\"name\") ASC" 
19
Mario Pérez

Avez-vous envisagé de stocker votre colonne en tant que type citext ? Il intériorise vraiment juste l'appel à lower () tel que je le comprends. Ce serait automatique pour vous par la suite. Si vous avez parfois besoin d'une recherche sensible à la casse, ce n'est peut-être pas la meilleure idée.

6
rfusca

EN SQL, vous pouvez utiliser ORDER BY LOWER (nom_colonne), aucune idée de comment le faire dans Ruby. Un index fonctionnel (également sur LOWER (nom de colonne)) aidera à accélérer les choses.

5
Frank Heikens