2012-02-01 3 views
9

Ad esempio, si consideri il seguente codice (in un modello):C'è un buon modo per DEUMIDARE la duplicazione logica scope/predicato?

scope :popular, where("views >= 250 OR (views >= 10 AND avg_rating >= 4.75)") 

def popular? 
    views >= 250 or views >= 10 && avg_rating >= 4.75 
end 

Prima condizione è SQL, secondo rubino, ma ancora, c'è una duplicazione ovvio. C'è un buon modo per ASCIUGARE? Qual è la migliore pratica per questi casi?

risposta

2

Ci sono buone ragioni per avere entrambi così potrei considerare questo (tutti in modello):

VIEWS_QUALIFIER = 250 
RATING_VIEWS_QUALIFIER = 10 
RATING_QUALIFIER = 4.75 

scope :popular, where("views >= ? OR (views >= ? AND avg_rating >= ? ", 
       VIEWS_QUALIFIER, RATING_VIEWS_QUALIFIER, RATING_QUALIFIER) 

def popular? 
    views >= VIEWS_QUALIFIER or 
    (views >= RATING_VIEWS_QUALIFIER && avg_rating >= RATING_QUALIFIER) 
end 
+0

Sembra che ci sia un errore di battitura nella definizione dell'ambito ... – Alexis

+0

sì. L'ho corretto –

0
def popular? 
    !!self.class.popular.includes? self 
end 
+0

Avrei sconsigliato in quanto questo caricherebbe tutti i record popolari solo per verificare che l'elemento sia popolare. Forse 'self.class.popular.exists? (Id)' potrebbe funzionare –

+2

@ThongKuah c'è anche un altro problema con tutte le soluzioni simili - il metodo potrebbe restituire risultati errati quando l'oggetto si trova in un 'dirty' e 'views' o' avg_rating 'è cambiato ma non salvato – Alexis

+1

C'è sempre un posto per imparare in SO. TY per i commenti! :) – fuzzyalej

Problemi correlati