Ruby on Rails: Wie sortiere ich mit ActiveRecord mit zwei Spalten?

90

Ich möchte nach zwei Spalten sortieren, eine ist eine DateTime ( updated_at) und die andere ist eine Dezimalzahl (Price).

Ich möchte in der Lage sein, zuerst nach update_at zu sortieren und dann, wenn mehrere Artikel am selben Tag auftreten, nach Preis zu sortieren.

NullVoxPopuli
quelle

Antworten:

64

Angenommen, Sie verwenden MySQL.

Model.all(:order => 'DATE(updated_at), price')

Beachten Sie den Unterschied zu den anderen Antworten. Die updated_atSpalte ist ein vollständiger Zeitstempel. Wenn Sie also nach dem Tag der Aktualisierung sortieren möchten , müssen Sie eine Funktion verwenden, um nur den Datumsteil aus dem Zeitstempel abzurufen. In MySQL also DATE().

Daniel Vandersluis
quelle
7
Um zu verhindern, dass Joins zufällig mit "mehrdeutigen Spalten" -Nachrichten unterbrochen werden, sollten Sie die folgende robustere Version verwenden: :order => ["DATE(#{table_name}.updated_at)", :price](Beachten Sie, dass dies :priceein Symbol ist.)
Jo Liss
Ich musste meiner Bestellspalte folgendermaßen entkommen order:Model.all(:order => "day asc, `order` asc")
Gewähren Sie
147

In Rails 4 können Sie Folgendes tun:

Model.order(foo: :asc, bar: :desc)

foound barsind Spalten in der Datenbank.

Christian Fazzini
quelle
1
Schienen 4 ist die größte.
Darth Egregious
56
Thing.find(:all, :order => "updated_at desc, price asc")

wird den Trick machen.

Aktualisieren:

Thing.all.order("updated_at DESC, price ASC")

ist der Rails 3 Weg zu gehen. (Vielen Dank @cpursley )

Erik Escobedo
quelle
4
Vielen Dank @Erik - Ich weiß, dass diese Antwort alt ist. Hier ist meine Warnung für diejenigen, die sie jetzt sehen: Diese Methode ist ab Rails 3.2 veraltet. Verwenden Sie stattdessen Thing.all =)
Abdo
Richtig, das hat bei mir gut funktioniert: Thing.all.order("updated_at DESC, price ASC")
cpursley
1
Ihr Update war hilfreich für mich, als ich die sortierten Werte in Kleinbuchstaben schreiben musste : Thing.order("LOWER(name), number").
Nick
34

Mit der Active Record Query Interface können Sie so viele Attribute angeben, wie Sie für Ihre Abfrage bestellen möchten :

models = Model.order(:date, :hour, price: :desc)

oder wenn Sie genauer werden möchten (danke @ zw963 ):

models = Model.order(price: :desc, date: :desc, price: :asc) 

Bonus: Nach der ersten Abfrage können Sie andere Abfragen verketten:

models = models.where('date >= :date', date: Time.current.to_date)
Golfadas
quelle
Ich weiß, dass dies ein alter Beitrag ist, aber ich würde persönlich zu wechseln model, modelsdamit eine Person weiß, dass er pluralisiert ist. Nur ein Vorschlag.
Tass
1
Ich denke, ich sollte ein spezielleres Beispiel bearbeiten: zB models = Model.order ({price :: desc}, {date :: desc}, {price: asc})
zw963
Wenn jemand dies eingefügt hat und einen undefinierten Methodenfehler festgestellt hat, gibt es hier einen kleinen Tippfehler. Es sollte :ascstatt sein asc:Model.order({price: :desc}, {date: :desc}, {price: :asc})
Nayiaw
18

Tatsächlich gibt es viele Möglichkeiten, dies mit Active Record zu tun. Eine, die oben nicht erwähnt wurde, wäre (in verschiedenen Formaten, alle gültig):

Model.order(foo: :asc).order(:bar => :desc).order(:etc)

Vielleicht ist es ausführlicher, aber ich persönlich finde es einfacher zu verwalten. SQL wird nur in einem Schritt erstellt:

SELECT "models".* FROM "models" ORDER BY "models"."etc" ASC, "models"."bar" DESC, "models"."foo" ASC

Also für die ursprüngliche Frage:

Model.order(:updated_at).order(:price)

Sie müssen den Datentyp nicht deklarieren. ActiveRecord erledigt dies reibungslos, ebenso wie Ihre DB Engine

Ruby Racer
quelle
Dies funktioniert hervorragend, wenn zwei Spalten aus zwei verschiedenen Tabellen verwendet werden, z. B.: Member.includes (: voter) .order ("town_club asc"). Order ("Voter.last_name asc")
bkunzi01
1
Entspricht das von Ihnen veröffentlichte SQL Model.order(foo: :asc).order(:bar => :desc).order(:etc)? Die Reihenfolge der order-Klauseln in SQL ist das Gegenteil von dem, was ich bekomme, wenn ich darauf laufe .to_sql.
Qaz
1
@ Qaz das ist lange her. Ich denke, ich muss das wahrscheinlich korrigieren, ich hatte es nie bemerkt. Ich werde es später noch einmal überprüfen. Vielen Dank.
Ruby Racer
2
Model.all(:order => 'updated_at, price')
robertokl
quelle
0

Nichts davon hat bei mir funktioniert! Nachdem ich genau 2 Tage lang über das Internet nach oben und unten geschaut hatte, fand ich eine Lösung !!

Angenommen, die Produkttabelle enthält viele Spalten, darunter: special_price und msrp. Dies sind die beiden Spalten, mit denen wir sortieren möchten.

Okay, fügen Sie zuerst in Ihrem Modell diese Zeile hinzu:

named_scope :sorted_by_special_price_asc_msrp_asc, { :order => 'special_price asc,msrp asc' }

Zweitens fügen Sie im Product Controller hinzu, wo Sie die Suche durchführen müssen:

@search = Product.sorted_by_special_price_asc_msrp_asc.search(search_params)
Max Alexander Hanna
quelle