Chciałbym określić domyślną kolejność sortowania w moim modelu.
Tak więc, gdy robię a .where()
bez określania .order()
, używa domyślnego sortowania. Ale jeśli podam an .order()
, zastępuje wartość domyślną.
Chciałbym określić domyślną kolejność sortowania w moim modelu.
Tak więc, gdy robię a .where()
bez określania .order()
, używa domyślnego sortowania. Ale jeśli podam an .order()
, zastępuje wartość domyślną.
Odpowiedzi:
default_scope
Działa to z Railsami 4+:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
W przypadku Railsów 2.3, 3 potrzebujesz tego:
default_scope order('created_at DESC')
W przypadku szyn 2.x:
default_scope :order => 'created_at DESC'
Gdzie created_at
jest pole, w którym ma zostać wykonane domyślne sortowanie.
Uwaga: ASC jest kodem używać do rosnącej i DESC jest malejące ( desc
, NIE dsc
!).
scope
Gdy już się do tego przyzwyczaisz, możesz także użyć scope
:
class Book < ActiveRecord::Base
scope :confirmed, :conditions => { :confirmed => true }
scope :published, :conditions => { :published => true }
end
Do Railsów 2 potrzebujesz named_scope
.
:published
zakres daje Book.published
zamiast
Book.find(:published => true)
.
Od Rails 3 możesz łączyć te metody razem, łącząc je z okresami między nimi, więc dzięki powyższym zakresom możesz teraz używać Book.published.confirmed
.
Dzięki tej metodzie zapytanie nie jest faktycznie wykonywane, dopóki nie są potrzebne rzeczywiste wyniki (leniwa ocena), więc 7 zakresów można połączyć razem, ale tylko w wyniku 1 rzeczywistego zapytania do bazy danych, aby uniknąć problemów z wydajnością podczas wykonywania 7 oddzielnych zapytań.
Możesz użyć przekazanego parametru, takiego jak data lub identyfikator_użytkownika (coś, co zmieni się w czasie wykonywania, a więc będzie wymagało „leniwej oceny” z użyciem lambda, takie jak:
scope :recent_books, lambda
{ |since_when| where("created_at >= ?", since_when) }
# Note the `where` is making use of AREL syntax added in Rails 3.
Wreszcie możesz wyłączyć domyślny zakres za pomocą:
Book.with_exclusive_scope { find(:all) }
lub nawet lepiej:
Book.unscoped.all
co wyłączy dowolny filtr (warunki) lub sortuje (sortuj według).
Zauważ, że pierwsza wersja działa w Rails2 +, podczas gdy druga (bez zakresu) jest tylko dla Rails3 +
Więc
... jeśli myślisz, hmm, więc są to metody jak wtedy ... tak, właśnie takie są te zakresy!
Są jak posiadanie, def self.method_name ...code... end
ale jak zawsze z rubinem, są ładnymi małymi skrótami syntaktycznymi (lub „cukrowymi”), aby ułatwić ci wszystko!
W rzeczywistości są to metody na poziomie klasy, ponieważ działają na 1 zestawie „wszystkich” rekordów.
Zmienia się jednak ich format. W przypadku szyn 4 ostrzeżenie o wycofaniu jest wyświetlane podczas używania #scope bez przechodzenia przez obiekt na żądanie. Na przykład zakres: czerwony, gdzie (kolor: „czerwony”) należy zmienić na scope :red, -> { where(color: 'red') }
.
Na marginesie, w przypadku nieprawidłowego użycia domyślny _scope może być niewłaściwie wykorzystywany / nadużywany.
Dotyczy to głównie sytuacji, w której przyzwyczaja się do działań takich jak where
ograniczanie (filtrowanie) domyślnego wyboru ( zły pomysł na domyślny), a nie tylko do porządkowania wyników.
Do where
selekcji użyj zwykłych nazwanych zakresów. i dodaj ten zakres do zapytania, np. Book.all.published
gdzie published
jest nazwany zakres.
Podsumowując, zakresy są naprawdę świetne i pomagają wepchnąć rzeczy do modelu dla podejścia DRYer typu „gruby model kontrolera”.
default_scope { order("#{table_name}.created_at DESC") }
?
default_scope { order(created_at: :desc) }
4.2.6
wydaje się sortować według updated_at
nie created_at
.
updated_at
domyślnie? : - |
Szybka aktualizacja doskonałej odpowiedzi Michaela powyżej.
W przypadku Rails 4.0+ musisz umieścić swój sort w bloku takim jak ten:
class Book < ActiveRecord::Base
default_scope { order('created_at DESC') }
end
Zauważ, że instrukcja zamówienia jest umieszczona w bloku oznaczonym nawiasami klamrowymi.
Zmienili to, ponieważ zbyt łatwo było wprowadzić coś dynamicznego (jak obecny czas). To usuwa problem, ponieważ blok jest oceniany w czasie wykonywania. Jeśli nie użyjesz bloku, otrzymasz następujący błąd:
Usunięto obsługę wywoływania #default_scope bez bloku. Na przykład zamiast
default_scope where(color: 'red')
, użyjdefault_scope { where(color: 'red') }
. (Alternatywnie możesz po prostu przedefiniować self.default_scope.)
Jak wspomina @Dan w swoim komentarzu poniżej, możesz wykonać bardziej rubinową składnię, jak poniżej:
class Book < ActiveRecord::Base
default_scope { order(created_at: :desc) }
end
lub z wieloma kolumnami:
class Book < ActiveRecord::Base
default_scope { order({begin_date: :desc}, :name) }
end
Dzięki @Dan !
default_scope { order(created_at: :desc) }
, jakbyś, podobnie jak ja, próbował zminimalizować składnię sql w szynach. <br/> Jeśli masz wiele kolumn do uporządkowania i chcesz użyć nowej składni, może być konieczne zawinięcie opisu kolumny w takich wąsachdefault_scope { order({begin_date: :desc}, :name) }
Za pomocą default_scope można zaimplementować domyślną kolejność sortowania http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html
default_scope
na tej stronie nie ma nic , ponieważ został ponownie ActiveRecord::Base
przekształcony w ActiveRecord::Scoping::Default::ClassMethods
( api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/… )