2010-02-05 11 views
51

Dati i seguenti modelli AR, vorrei ordinare gli utenti in ordine alfabetico per cognome quando somministrato un handle a un compito:Come posso ordinare un has_many tramite associazione in Ruby on Rails?

Vorrei ottenere un compito poi di navigazione ai propri utenti assegnati, e ordinare l'elenco degli utenti in ordine alfabetico.

continuo a pensare che dovrei essere in grado di aggiungere la clausola :order-has_many :users, :through => :assignments in questo modo:

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

tuttavia questo non funziona.

Come è possibile ordinare gli utenti tramite last_name quando viene assegnata un'attività?

risposta

7

Questo lavoro potrebbe funzionare?

# User.rb 

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

È possibile definire altri ambiti con nome per quando l'ordinamento deve essere diverso.

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

+2

Siamo spiacenti di rispondere a una domanda precedente, ma potrebbe essere pertinente per i futuri lettori: alcuni plug-in (act_as_list per esempio) non funzionano correttamente con default_scope. – robinjam

+0

Inoltre, ho riscontrato un problema simile, ma avevo bisogno di ordinare su un campo nella tabella: through: la cosa fantastica è che default_scope funziona anche nella tabella: through e i record recuperati tramite quella relazione rispetteranno l'ordine. – MBHNYC

36

Rails versione 3.x:

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

UPDATE: Questo funziona solo in Rails 3.x (forse prima che troppo). Per 4+, vedi altre risposte.

+0

Funziona bene anche per me. Soluzione pulita che non influisce su altre funzioni del modello ordinato come fa la prima risposta. – barancw

+2

non funziona, dice: l'ordine non è una chiave. Di seguito la risposta di Denial IS funziona. – RohitPorwal

12

L'approccio M.G.Palmer's funziona bene, tuttavia il nome della tabella è coinvolto. C'è un modo migliore per farlo:

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

ma cosa succede se l'ordine è determinato dalla tabella di join? per esempio. assegnazioni ... ma senza definire un ambito predefinito per le assegnazioni .. – Tilo

2

Si potrebbe anche creare una nuova colonna 'sort_order' sulla tabella di assegnazione, e aggiungere un ambito predefinito come

default_scope { order('sort_order desc')} 

al modello assegnazioni.

65

Poiché l'argomento condizione sono deprecati in Rails 4, si dovrebbe usare blocchi portata:

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

Sembra che ci sia attualmente un bug in Rails 4 con questo https://github.com/rails/rails/issues/17904 "In Rails 4.0, il la clausola dell'ordine è stata ignorata, in Rails 4.1 è stato generato un SQL non valido. " – Nate

+0

Non mi dà nemmeno questo, ignora completamente la clausola dell'ordine senza messaggi. –

6

Questo funziona per me (Rails 4.2)

Applicazione di un ordinamento sulla attraverso mappa non è conservato, in arte questo non è sufficiente per avere i generi ordinato:

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 

Così ho sovrascrivere questo per esempio:

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

Per fare quel lavoro per le assegnazioni, questo dovrebbe essere qualcosa di simile (non testato)

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

Sto usando Rails (5.0.0.1) e potrebbe fare il genere con questa sintassi nel mio modello di gruppo che ha molti utenti tramite group_users:

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

Regola il codice in base alle tue esigenze.

Problemi correlati