2010-02-05 7 views
51

Compte tenu des modèles AR suivants, je voudrais trier les utilisateurs par ordre alphabétique par nom de famille quand donné une poignée à une tâche:Comment commander une association has_many via Ruby on Rails?

Je voudrais obtenir une tâche puis navigation à ses utilisateurs affectés, et trier la liste des utilisateurs par ordre alphabétique.

Je continue à penser que je devrais être en mesure d'ajouter la clause :orderhas_many :users, :through => :assignments comme ceci:

#task.rb 
has_many :assignments 
has_many :users, :through => :assignments, :order => 'last_name, first_name' 

mais cela ne fonctionne pas.

Comment trier les utilisateurs par last_name lors d'une tâche?

Répondre

7

Cela fonctionnerait-il pour vous?

# User.rb 

class User < ActiveRecord::Base 
default_scope :order => 'last_name ASC' 
... 
end 

Vous pouvez définir d'autres étendues nommées lorsque le tri doit être différent.

http://ryandaigle.com/articles/2008/11/18/what-s-new-in-edge-rails-default-scoping

+2

Désolé de passer en revue une vieille question, mais cela pourrait être pertinent pour les futurs lecteurs: Certains plugins (acts_as_list par exemple) ne fonctionnent pas correctement avec default_scope. – robinjam

+0

J'ai aussi eu un problème similaire, mais j'avais besoin de trier un champ dans la table: through: la chose géniale est que default_scope fonctionne aussi dans la table: through, et les enregistrements récupérés via cette relation respecteront l'ordre. – MBHNYC

36

Rails version 3.x:

has_many :users, :through => :assignments, :order => 'users.last_name, users.first_name' 

MISE À JOUR: Cela ne fonctionne que dans 3.x Rails (peut-être avant aussi). Pour 4+, voir d'autres réponses.

+0

Fonctionne bien pour moi aussi. Solution propre qui n'affecte pas les autres fonctions du modèle trié comme le fait la première réponse. – barancw

+2

ne fonctionne pas, il dit: l'ordre n'est pas une clé. Ci-dessous la réponse de Denial IS fonctionne. – RohitPorwal

12

L'approche M.G.Palmer's fonctionne bien, mais le nom de la table est impliqué. Il y a une meilleure façon de le faire:

has_many :users, :through => :assignments, :order => [ :last_name, :first_name ] 
+0

mais que faire si la commande est déterminée par la table de jointure? par exemple. affectations ... mais sans définir une étendue par défaut sur les affectations .. – Tilo

2

Vous pouvez également créer une nouvelle colonne « sort_order » sur la table d'affectation, et ajouter un champ par défaut comme

default_scope { order('sort_order desc')} 

à votre modèle de missions.

65

Comme arguments de condition sont déconseillés dans Rails 4, on doit utiliser des blocs de portée:

has_many :users, -> { order 'users.last_name, users.first_name' }, :through => :assignments 
+1

Il semble qu'il existe actuellement un bug dans Rails 4 avec ce https://github.com/rails/rails/issues/17904 "Dans Rails 4.0, le Dans Rails 4.1, le code SQL invalide est généré. " – Nate

+0

Il ne me donne même pas cela, ignore complètement complètement la clause d'ordre sans message. –

6

Cela fonctionne pour moi (Rails 4.2)

l'application d'une commande sur le par carte ne se conserve pas, alias cela ne suffit pas d'avoir les genres commandés:

has_many :disk_genre_maps, 
      -> {order('disk_genre_map.sort_order')}, 
      :inverse_of => :disk, 
      :dependent => :destroy, 
      :autosave => true 


has_many :genres, # not sorted like disk_genre_maps 
      :through => :disk_genre_maps, 
      :source  => :genre, 
      :autosave => true 

J'écrasent ce par exemple:

def genres # redefine genres per instance so that the ordering is preserved 
    self.disk_genre_maps.map{|dgm|dgm.genre} 
end 

Pour faire ce travail pour des missions, cela devrait être quelque chose comme ça (non testé)

def genres= some_genres 
    self.disk_genre_maps = some_genres.map.with_index do |genre, index| 
     DiskGenreMap.new(disk:self, genre:genre, sort_order:index) 
    end 
end 
2

J'utilise Rails (5.0.0.1) et pourrait faire le genre avec cette syntaxe dans mon groupe de modèle a de nombreux utilisateurs via group_users:

# Associations. 
has_many :group_users 
has_many :users, -> { order(:name) }, through: :group_users 

Ajustez le code à votre besoin qui fonctionnera.

Questions connexes