Sortieren Sie das von ActiveRecord zurückgegebene Array nach Datum (oder einer anderen Spalte).

70

Wie kann ich ein von einer ActiveRecord-Abfrage zurückgegebenes Array nach einer Datumsspalte sortieren created_at?

Dies tritt auf, sobald die Abfrage ausgeführt wurde.

Bitte sagen Sie mir nicht, dass ich es in der Abfrage tun soll, da dies in der Ansicht erforderlich ist.

user94154
quelle

Antworten:

130

Ruby bietet Unterstützung für das sofortige Sortieren.

sorted = @records.sort_by &:created_at

Dies scheint jedoch nicht viel mit der Anzeige zu tun zu haben und gehört wahrscheinlich in die Steuerung.

Futter
quelle
2
Enumerable # sort_by eignet sich hervorragend für diese Art von Dingen, viel besser als das andere Beispiel mit Enumerable # sort.
Tadman
1
Danke für die Klarstellung. Ich habe mehrere "Einstiegspunkte" für dieselbe Ansicht, und die Abfragen können dieselben Sortiermuster aufweisen oder nicht (ich weiß, nicht ideal). Aber ist die Reihenfolge, in der Listen von Dingen angezeigt werden, nicht unbedingt eine "Nur-Controller" -Funktion?
user94154
1
tadman - willst du das näher erläutern? Nach meinem Verständnis aus den API-Dokumenten ist sort_by die langsamere, flexiblere Art, eine Sortierung durchzuführen. Großartig für komplexere Sorten, aber zu viel für etwas so Einfaches.
Bill D
3
@ Bill D: Das ist ziemlich entgegengesetzt zur Wahrheit. sortist flexibler - Sie geben das gesamte Vergleichsprädikat an, während sort_bySie ihm nur mitteilen, was verglichen werden soll, und dies unter Verwendung des Standardprädikats sorttun. Dieser Fall, in dem Sie eine Methode aufrufen und anhand des Ergebnisses sortieren, ist weit verbreitet - sort_bynur eine präzisere Schreibweise.
Chuck
1
@ BillD scheint jedoch richtig zu sein. sort_byist für einfache Keysets aufgrund der Schwartzschen Transformation teurer, siehe ruby-doc.org/core-2.1.2/Enumerable.html#method-i-sort_by
Eero
35

Während Ruby Enumerable fantastisch ist, geben ActiveRecord-Abfragen tatsächlich eine ActiveRecord :: Relation zurück, deren Abfrage noch nicht ausgewertet wurde (Lazy Loading), und es kann die Order-Methode aufgerufen werden, um diese Verarbeitung in die Datenbank zu laden, in der sie skaliert wird viel besser als eine auf Enumerable basierende Strategie.

Die Verwendung von Enumerable zum Sortieren verwirrt auch die Paginierung in der Datenbank. Nichts hindert die Auftragsstrategie daran, in der Ansicht angewendet zu werden. Ich würde dies jedoch eher auf das Modell übertragen.

sorted = @records.order(:created_at)
Shulmang
quelle
26

Rufen Sie einfach sort für die Sammlung auf und übergeben Sie den Codeblock, der Ruby mitteilt, wie er sortiert werden soll:

collection.sort { |a,b| a.created_at <=> b.created_at }
Bill D.
quelle
3
Dies ist im Vergleich zu .sort_bydiesem Fall viel zu ineffizient . Bitte überprüfen Sie die andere Antwort von Chuck.
Dogbert
6
Für die Aufzeichnung wird dies nicht weniger effizient sein als die Version, die ich gegeben habe.
Chuck
1
Für die Aufzeichnung ist dies effizienter für einen einfachen Sortierschlüssel wie datetime - ruby-doc.org/core-2.1.2/Enumerable.html#method-i-sort_by
Eero
Beste Antwort, manchmal möchten Sie sich die lange Form ansehen. Meistens spielt Effizienz keine Rolle, deshalb schreiben wir alle Rubin.
Dekman
9

Bitte schauen Sie sich diese an und überprüfen Sie auch die Komplexität.

Model.all.sort_by{|m| m.created_at} #=> O(log n)

#versus

Model.order(“created_at DESC”) #=> O(1)
Sajjad Murtaza
quelle
Vielen Dank für die Erwähnung der Laufzeitkomplexität O (log n) und O (1)
Afsan Abdulali Gujarati
5

Die beste Methode zum Sortieren des ActiveRecord-Arrays ist die Verwendung der Standardmethodenreihenfolge

@ users.order (: created_at)

Dies ist die schnellste und am besten geeignete Lösung, da in diesem Fall ein sortiertes Array von db zurückgegeben wird und Sie dafür keine andere Operation in der Klasse verwenden müssen. Wenn Sie beispielsweise die vorgeschlagene Operation verwenden, sort_bywird jedes Element des Arrays in einer Schleife ausgelöst. und danach wird es kein ActiveRecord-Array mehr sein, meiner Meinung nach nicht cool.

order kann Strings und Sumbols verwenden, ist sehr nützlich und benötigt mehrere Parameter

@ users.order ('created_at asc, first_name desc, last_name asc')

Dmitriy Gusev
quelle