web-dev-qa-db-fra.com

Comment commander les éléments inclus dans Rails 3

J'ai une relation de modèle où today a beaucoup tasks

J'essaye de récupérer l'objet today d'un utilisateur, d'inclure le tasks et de les rendre tous à Json. Tout cela allait très bien jusqu'à ce que je décide que je souhaite commander le tasks dans l'objet today car respond_with block est également utilisé pour le rendu de la page html. Existe-t-il un moyen d'inclure les tasks et de les commander?

J'essaye quelque chose comme ça:

class TodaysController < ApplicationController
  respond_to :html, :json
  def show
    @today = Today.where(:user_id => current_user.id).joins(:tasks).includes(:tasks).order(:priority).first
    respond_with @today, :include => :tasks
  end
end

Cela récupère tout correctement, mais ne semble pas du tout ordonner les tâches.

C'est ce que j'avais l'habitude d'avoir (qui fonctionnait très bien, mais je n'avais pas la commande):

class TodaysController < ApplicationController
  respond_to :html, :json
  def show
    @today = current_user.today
    respond_with @today, :include => :tasks
  end
end

Je sais que je peux récupérer les données et les trier par la suite comme ceci:

@today = current_user.today
@today.tasks.sort!{|a,b| a.priority <=> b.priority }

Cela fonctionne et passera mes tests, mais j'espérais un moyen ActiveRecord de résoudre ce problème.

41
royvandewater

Essayez ceci dans votre modèle Today:

has_many :tasks, :order => 'priority DESC'

EDIT: Comme mentionné dans le commentaire ci-dessous, dans Rails 4+, c'est maintenant:

has_many :tasks, -> { order(:priority => :desc) }

( plus d'infos ici )

65
khelll

La solution directe serait d'inclure le nom de la table tasks avant priority:

Today.where(:user_id => current_user.id).includes(:tasks).order('tasks.priority').first
# joins(:tasks) is not required

Ou, si vous ne voulez pas que le nom de la table soit codé en dur, vous pouvez fusionner avec la portée du modèle Task:

Today.where(:user_id => current_user.id).joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first
# joins(:tasks) here is required

Vous pouvez également ajouter has_many: todays au modèle User pour abandonner la clause where et faire:

current_user.todays.includes(:tasks).order('tasks.priority').first
# or
current_user.todays.joins(:tasks).includes(:tasks).merge(Task.order(:priority)).first

Mais si vous avez seulement/toujours besoin de classer par priorité, et n'avez pas besoin d'autres ordres différents, ajoutez order à has_many :tasks est plus facile.

44
Jack