Domyślna kolejność sortowania dla modelu rails?

Chciałbym określić domyślną kolejność sortowania w moim modelu.

Tak, że gdy robię .where() bez podania .order() używa domyślnego sortowania. Ale jeśli podam .order(), nadpisuje domyślną wartość.

Author: Kara, 2010-08-03

3 answers

default_scope

To działa dla Rails 4+:
class Book < ActiveRecord::Base
  default_scope { order(created_at: :desc) }
end
W przypadku Rails 2.3, 3 potrzebujesz tego zamiast tego:
default_scope order('created_at DESC')

Dla Rails 2.x:

default_scope :order => 'created_at DESC'

Gdzie created_at jest polem, na którym ma być wykonane domyślne sortowanie.

Uwaga: ASC jest kodem używanym do wstępowania i DESC jest dla malejących (desc, nie dsc !).

scope

Kiedy już się do tego przyzwyczaisz, możesz również użyć scope:

class Book < ActiveRecord::Base
  scope :confirmed, :conditions => { :confirmed => true }
  scope :published, :conditions => { :published => true }
end

Do Rails 2 potrzebujesz named_scope.

:published scope daje Book.published zamiast Book.find(:published => true).

Od Rails 3 możesz' połączyć ' te metody ze sobą, łącząc je z okresami między nimi, więc z powyższymi zakresami możesz teraz używać Book.published.confirmed.

W przypadku tej metody zapytanie nie jest faktycznie wykonywane, dopóki nie są potrzebne rzeczywiste wyniki( leniwa ocena), więc 7 zakresów może być połączonych łańcuchowo, ale tylko w wyniku 1 rzeczywistego zapytania bazy danych, aby uniknąć problemy z wydajnością po wykonaniu 7 oddzielnych zapytań.

Możesz użyć parametru passed in, takiego jak date lub user_id (coś, co zmieni się w czasie wykonywania, a więc będzie wymagało 'leniwej oceny', z lambda, jak to: {27]}

scope :recent_books, lambda 
  { |since_when| where("created_at >= ?", since_when) }
  # Note the `where` is making use of AREL syntax added in Rails 3.

W końcu możesz wyłączyć domyślny zakres za pomocą:

Book.with_exclusive_scope { find(:all) } 

Albo jeszcze lepiej:

Book.unscoped.all

Który wyłączy dowolny filtr (warunki) lub sortowanie (kolejność według).

zauważ, że pierwsza wersja działa w Rails2+, podczas gdy drugi (bez znaku) jest tylko dla szyn 3 +


Więc ... jeśli myślisz, hmm, więc to są takie same metody... dokładnie tym są te lunety!
Są jak posiadanie def self.method_name ...code... end, ale jak zawsze w ruby są to ładne małe skróty składniowe (lub "cukier"), aby ułatwić Ci życie!

W rzeczywistości są to metody na poziomie klasy, ponieważ działają na 1 zbiorze' wszystkich ' rekordów.

Ich format zmienia się jednak Z rails 4 podczas używania #scope, bez przekazywania obiektu wywołującego, są ostrzeżenia o wycofaniu. na przykład scope: red, where (color: 'red') należy zmienić na scope :red, -> { where(color: 'red') }.

Na marginesie, w przypadku nieprawidłowego użycia, default _scope może być nadużywane/nadużywane.
Chodzi głównie o to, kiedy jest używany do działań takich jak where ograniczanie (filtrowanie) wyboru default (a zły pomysł dla domyślnej), a nie tylko do porządkowania wyników.
Dla where zaznaczenia, wystarczy użyć zwykłych nazwanych zakresów. i dodać ten zakres w zapytaniu, np. Book.all.published gdzie published jest nazwanym zakresem.

Podsumowując, lunety są naprawdę świetne i pomagają wprowadzić rzeczy do modelu suszarki "fat model thin controller".

 485
Author: Michael Durrant,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-02 15:42:38

Szybka aktualizacja do doskonałej odpowiedzi Michaela powyżej.

Dla Rails 4.0 + musisz umieścić swój sort w takim bloku:

class Book < ActiveRecord::Base
  default_scope { order('created_at DESC') }
end

Zwróć uwagę, że polecenie jest umieszczone w bloku oznaczonym nawiasami klamrowymi.

Zmienili go, ponieważ zbyt łatwo było przejść w coś dynamicznego (jak obecny czas). Usuwa to problem, ponieważ blok jest oceniany w czasie wykonywania. Jeśli nie użyjesz bloku, otrzymasz ten błąd:

Wsparcie dla wywołania # default_scope bez bloku jest usuwany. Na przykład zamiast default_scope where(color: 'red') Użyj default_scope { where(color: 'red') }. (Alternatywnie możesz po prostu przedefiniować siebie.default_scope.)

Jako @Dan wspomina w swoim komentarzu poniżej, możesz zrobić bardziej rubyish składni jak to:

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

Thanks @Dan!

 105
Author: Paul Oliver,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:26

Możesz użyć default_scope, aby zaimplementować domyślny porządek sortowania http://api.rubyonrails.org/classes/ActiveRecord/Scoping/Default/ClassMethods.html

 6
Author: Slobodan Kovacevic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-03-18 22:19:30