Ordonnez un model en fonction d'une table associé

Default
,

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

32341
,

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 :)