2009-07-14 11 views
40

Ho due modelli in una relazione has_many tale che Log ha_molti elementi. Rails quindi imposta bene cose come: some_log.items che restituisce tutti gli elementi associati a some_log. Se volessi ordinare questi elementi in base a un campo diverso nel modello Elementi c'è un modo per fare questo attraverso un costrutto simile, o se uno deve abbattere in qualcosa di simile:Rails ordina in modello associato

Item.find_by_log_id(:all,some_log.id => "some_col DESC") 

risposta

74

Ci sono diversi modi per fare questo:

Se si desidera che tutte le chiamate a tale associazione da ordinare in questo modo, è possibile specificare l'ordine quando si crea l'associazione, come segue:

class Log < ActiveRecord::Base 
    has_many :items, :order => "some_col DESC" 
end 

si potrebbe anche fare questo con un named_scope, che consentirebbe a quell'ordine di essere e asily specificato qualsiasi momento Item si accede:

class Item < ActiveRecord::Base 
    named_scope :ordered, :order => "some_col DESC" 
end 

class Log < ActiveRecord::Base 
    has_many :items 
end 

log.items # uses the default ordering 
log.items.ordered # uses the "some_col DESC" ordering 

Se si desidera sempre gli elementi da ordinare nello stesso modo di default, è possibile utilizzare la (nuova in Rails 2.3) Metodo default_scope, come segue:

class Item < ActiveRecord::Base 
    default_scope :order => "some_col DESC" 
end 
+12

Dal Rails 3.x, la sintassi named_scope è leggermente diversa. Viene ora chiamato usando "scope" invece di "named_scope" e utilizza le funzioni per definire la struttura dell'ambito. Ad esempio: "scope: ordered, order (" some_col DESC ")". –

+11

In Rails 4 c'è di nuovo un altro approccio. L'ambito di associazione predefinito deve essere specificato come un lambda come 'has_many: items, -> {order (: some_col) .where (foo: 'bar')}' e, analogamente, gli scope nominati ora prendono uno scope lambda: nome_of_scope, -> {where (foo: 'bar')} '. L'ambito predefinito richiede un blocco: 'default_scope: {where (foo: 'bar')}' – Leo

+0

Risposta superba. +1 – sscirrus

4

Uno di questi dovrebbe funzionare:

Item.all(:conditions => {:log_id => some_log.id}, :order => "some_col DESC") 
some_log.items.all(:order => "some_col DESC") 
3

impostare default_scope nella classe del modello

class Item < ActiveRecord::Base 
    default_scope :order => "some_col DESC" 
end 

Ciò funzionerà

+2

non funziona con i binari 4 – SsouLlesS

+2

@SsouLlesS Questo ha risposto nel 2011 quando non c'erano Rails 4. – Sayuj

16

rotaie 4.2.20 sintassi richiede di chiamare con un blocco:

class Item < ActiveRecord::Base 
    default_scope { order('some_col DESC') } 
end 

Questo può anche essere scritto con una sintassi alternativa:

default_scope { order(some_col: :desc) } 
Problemi correlati