2012-02-08 5 views
15

Mam projekt RoR w pracach. Oto odpowiednie sekcje moich modeli.Szyny - Sortuj według danych tabeli złącz

strona

has_many :communities, :through => :availabilities 
has_many :availabilities, :order => "price ASC" 

Społeczność

has_many :homes, :through => :availabilities 
has_many :availabilities 

Dostępność

belongs_to :home 
belongs_to :community 

„Wolne” tabela w bazie danych ma dodatkowe kolumny „cena”

Więc teraz mogę nazwać

@home.availabilities.each do |a| 
    a.community.name 
    a.price 

i odzyskać dane Wolne Zamówione przez cenę, jak chcę. Moje pytanie jest następujące:

Czy istnieje sposób automatycznego zamówienia Homes przez avaliabilities.first.price (first = lowest)? Może coś z default_scope :order?

Odpowiedz

17

Proponuję unikać używania default_scope, zwłaszcza w przypadku czegoś podobnego do ceny na innym stole. Za każdym razem, gdy użyjesz tej tabeli, nastąpi sprzężenie i zamówienie, co może dać dziwne wyniki w złożonych zapytaniach, a co za tym idzie, spowolnienie zapytania.

Nie ma nic złego w zakresie własnej, to jest prostsze i jest jeszcze wyraźniejsza, można zrobić to tak proste, jak:

scope :ordered, -> { includes(:availabilities).order('availabilities.price') } 

PS: Pamiętaj, aby dodać indeks na price

+1

Czy zamiast łączenia należy użyć opcji 'includes'? – Jwan622

+0

Zależy, @TeWu robi świetną robotę wyjaśniając różnicę w swojej odpowiedzi. W szczególności link do bloga Toma Dallimore'a jest niesamowity. – ecoologic

20

Wyliczyłem to z pomocą this related post.

przeniosłem kolejność z modelu domu i do modelu Dostępność:

Dostępność

default_scope :order => "price ASC" 

Potem chętnie załadowany Wolne do modelu domu i posortowane według ceny:

Strona główna

default_scope :include => :availabilities, :order => "availabilities.price ASC" 
6

@ ecoologic answer:

scope :ordered, -> { includes(:availabilities).order('availabilities.price') } 

jest wielki, ale należy wspomnieć, że includes może, aw niektórych przypadkach powinna zastąpiony przez joins. They both have their optimal use cases.

Z praktycznego punktu widzenia istnieją dwa główne różnice:

  1. includes obciążenia związanego rekordu (ów); w tym przypadku rekordów Availability. joins nie ładuj żadnych powiązanych rekordów. Powinieneś więc użyć includes, gdy chcesz użyć danych z modelu łączenia, np. wyświetl gdzieś: price. Z drugiej strony, jeśli chcesz używać danych modelu sprzężenia tylko w zapytaniu, użyj: joins w klauzulach: ORDER BY lub WHERE.

  2. includes ładuje wszystkie rekordy, podczas gdy joins ładuje tylko te rekordy, które mają skojarzony model łączenia. Tak więc w przypadku OP, Home.includes(:availabilities) załadowałoby wszystkie domy, podczas gdy Home.joins(:availabilities) załadowałoby tylko te domy, które powiązały co najmniej jedną dostępność.

Zobacz także this question.