2012-02-08 12 views
15

Ho un progetto RoR in lavorazione. Ecco le sezioni applicabili dei miei modelli.Rails - Ordina per dati tabella join

casa

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

Comunità

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

disponibilità

belongs_to :home 
belongs_to :community 

La tabella "disponibilità" nel database ha l'ulteriore dati della colonna "prezzo"

Così ora posso chiamare

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

e tornare i dati di disponibilità in ordine di prezzo come voglio. La mia domanda è questa:

C'è un modo per ordinare automaticamente le case da avaliabilities.first.price (primo = più basso)? Forse qualcosa con default_scope :order?

risposta

17

Vorrei suggerire di evitare l'uso di default_scope, in particolare su qualcosa come il prezzo su un altro tavolo. Ogni volta che userai questa tabella, si uniranno e si ordinerà, dando magari strani risultati in query complesse e comunque rendendo più lenta la tua query.

Non c'è niente di sbagliato con un campo di applicazione a sé stante, è più semplice ed è ancora più chiaro, si può rendere il più semplice:

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

PS: Ricordarsi di aggiungere un indice su price

+1

È necessario utilizzare 'include' anziché join? – Jwan622

+0

Depends, @TeWu sta facendo un ottimo lavoro nello spiegare la differenza nella sua risposta. In particolare il link al blog di Tom Dallimore è fantastico. – ecoologic

20

Calcolato con l'aiuto di this related post.

ho spostato l'ordinamento fuori del modello di casa e nel modello Disponibilità:

disponibilità

default_scope :order => "price ASC" 

Poi ho desiderosi disponibilità caricato nel modello di casa e scelte per prezzo:

Casa

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

@ ecoologic answer:

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

è grande, ma va detto che includes potrebbe, e in alcuni casi dovrebbero essere sostituito da joins. They both have their optimal use cases.

Dal punto di vista pratico ci sono due differenze principali:

  1. includes rilevamento dei carichi associati (s); in questo caso record Availability. joins non caricare alcun (i) record associato (i). Quindi dovresti usare includes quando vuoi utilizzare i dati dal modello di join, ad es. visualizza price da qualche parte. D'altra parte, è consigliabile utilizzare joins se si intende utilizzare i dati del modello di join solo nella query, ad es. nelle clausole ORDER BY o WHERE.

  2. includes carichi tutti i record, mentre joins carica solo i record che hanno associato unirsi modello. Quindi nel caso dell'OP, Home.includes(:availabilities) caricherà tutte le case, mentre Home.joins(:availabilities) caricherà solo quelle case che hanno associato almeno una disponibilità.

Vedere anche this question.