2009-07-14 7 views
40

Ich habe zwei Modelle in einer Beziehung has_many, so dass Log has_many Elemente. Rails richtet dann schön Dinge wie: some_log.items, die alle zugehörigen Elemente zu some_log zurückgibt. Wenn ich diese Elemente basierend auf einem anderes Feld in dem Item Modell bestellen wollte, ist es eine Möglichkeit, dies durch ein ähnliches Konstrukt zu tun, oder man in etwas zu brechen hat wie:Rails Bestellung von in verbundenen Modell

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

Antwort

74

Es gibt mehr Möglichkeiten dies zu tun:

Wenn Sie alle Anrufe an diese Vereinigung auf diese Weise bestellt werden, können Sie die Reihenfolge festlegen, wenn Sie die Zuordnung erstellen, wie folgt:

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

man könnte dies auch mit einem named_scope, mit der die Reihenfolge e asily angegeben Artikel jederzeit zugegriffen wird:

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 

Wenn Sie immer die Einzelteile wünschen, die standardmäßig in der gleichen Art und Weise bestellt werden, können Sie die (neu in Rails 2.3) default_scope Methode verwenden, wie folgt:

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

Da Rails 3.x, die benannte_Scope-Syntax ist etwas anders. Es wird jetzt mit "scope" anstelle von "named_scope" aufgerufen und verwendet Funktionen, um die Scope-Struktur zu definieren. Zum Beispiel: "scope: ordered, order (" some_col DESC ")". –

+11

In Rails 4 gibt es wieder einen anderen Ansatz. Der Standard-Assoziationsbereich sollte als ein lambda wie 'has_many: items, -> {order (: irgendein_col) .where (foo: 'bar')}' angegeben werden und in ähnlicher Weise nehmen die benannten Bereiche jetzt einen lambda 'scope: name_of_scope, -> {wo (foo: 'bar')} '. Der Standardbereich benötigt einen Block: 'default_scope: {wo (foo: 'bar')}' – Leo

+0

Hervorragende Antwort. +1 – sscirrus

4

Beides sollte funktionieren:

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

gesetzt default_scope in Ihrer Modellklasse

Dies funktioniert

+2

funktioniert nicht mit Schienen 4 – SsouLlesS

+2

@SsouLlesS Dies hat im Jahr 2011 beantwortet, wenn es keine Rails 4 gab. – Sayuj

16

Schienen 4.2.20 Syntax erfordert mit einem Block Aufruf:

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

Dies kann auch mit einer alternativen Syntax geschrieben werden:

default_scope { order(some_col: :desc) }