Ordonnez un model en fonction d'une table associé

Par Simonox, il y a 11 ans


Bonjour, je suis en train de faire une application web dans laquelle j'ai un model que j'appelle "idee" et j'aimerais pouvoir ordonner toutes ces idées en fonction de la date et de sa popularité (J'ai fais un système de vote pour ça). J'ai donc suivi ce railscast et ça marche mais seulement pour la date. Voici mes associations :

class Vote < ActiveRecord::Base belongs_to :idee belongs_to :user

Idee

has_many :votes, dependent: :destroy

User

has_many :idees, dependent: :destroy has_many :votes, dependent: :destroy

Et je ne sais pas comment je pourrais ordonner mes Idées en fonction des votes sachant que les votes proviennent d'une autre table. Voici pour l'instant ce que j'ai fait pour la date :

Application Helper

def sortable(column, title = nil) title ||= column.titleize direction = (column == params[:sort] && params[:direction] == "asc") ? "desc" : "asc" link_to title, :sort => column, :direction => direction end

Controller

def publiee @idees = Idee.order(sort_column + " " + sort_direction) @activites = Activite.all end private def sort_column params[:sort] || "created_at" end def sort_direction params[:direction] || "asc" end

Et dans ma vue, un lien pour changer le sens

<%= sortable "created_at", "Date" %>

Comment est-ce que je peux donc faire pour ordonner mes idées en fonction des votes et avec un lien pour en changer le sens ?

Merci de vos réponses :)

1 réponse

Tuxi, il y a 10 ans

Hello,

Visiblement tu ne veux pas trier en fonction d'un attribut du model vote, mais simplement en fonction du nombre de votes.
Dans ce cas, le plus simple est de définir un "counter cache" sur ton model idée. Il s'agit d'un champ en base de donnée qui se mettra automatiquement à jour à chaque nouveau vote.

rails generate migration add_votes_count_to_idees votes_count:integer

Puis dans ton model Vote :

belongs_to :idee, counter_cache: true

Il te faudra peut être mettre à jour tes compteurs si tu as déjà beaucoup d'entrée en base. La méthode "reset_counters" est faite pour ça.

Plus d'infos dispo ici : http://yerb.net/blog/2014/03/13/three-easy-steps-to-using-counter-caches-in-rails/

Enfin, tu n'es pas obligé d'utiliser la méthode order (qui ne s'applique sur sur un champ en base de donnée) pour trier tes colonnes. Si tu veux trier par attributs virtuels ou par retour de fonction, tu peux revoir le code du controller pour quelque chose comme ça :

@idees = Idee.all.to_a.sort_by! { |i| i.send(sort_column)}

En espérant que ça aide :)