2017-10-16 5 views
1

J'ai une API rails qui renvoie JSON à mon front-end React. J'essaie de trier par une valeur calculée pour chaque élément d'une collection. J'ai un modèle Space qui a un attribut area et un attribut count. Je voudrais trier la réponse par total_area qui est juste area * count. Je suis en mesure de le faire en utilisant sort_by mais le processus est assez lent même avec moins de 100 enregistrements:Comment trier par une valeur calculée dans Activerecord?

@spaces = Space.all 
@spaces = @spaces.sort_by(&:total_area) 

total_area est une méthode de classe Space:

def total_area 
    self.area * self.count 
end 

Y at-il de toute façon à faire dans la base de données pour obtenir une amélioration de la vitesse? Je l'ai essayé d'utiliser la méthode order:

@spaces.order("count * area" => :asc) 

Mais je reçois l'erreur postgres suivante:

PG::UndefinedColumn: ERROR: column spaces.count * area does not exist 

Est-il possible de le faire dans la base de données? Toute suggestion sur comment je peux, ou comment je pourrais faire ce genre plus rapidement serait très appréciée.

Répondre

2

Lorsque vous la main #order un hachage:

@spaces.order("count * area" => :asc) 

il suppose que la clé est un nom de colonne il envoie SQL comme ceci à la base de données:

order by "count * area" asc 

Par conséquent l'exception PG::UndefinedColumn. BTW, les guillemets sont utilisés dans SQL pour citer des identifiants tels que les noms de colonnes et de tables.

Si vous voulez envoyer une expression à la base de données dans le cadre d'une clause ORDER BY vous voulez passer cette expression à #order comme une chaîne:

@spaces.order('count * area') 
# If you want to be explicit about the sorting direction: 
@spaces.order('count * area asc') 
# If you might have other tables with those column names: 
@spaces.order('spaces.count * spaces.area')