2012-02-01 15 views
9

Por ejemplo, considere el siguiente código (en un modelo):¿Existe alguna forma de SECAR la duplicación de lógica de alcance/predicado?

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 

primera condición es SQL, segundo es el rubí, pero aún así, hay una duplicación obvia. ¿Hay alguna forma de SECARLO? ¿Cuál es la mejor práctica para tales casos?

Respuesta

2

hay buenas razones para tener tanto por lo que podrían considerar esto (todo en el modelo):

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

Parece que hay un error tipográfico en el alcance definición ... – Alexis

+0

sí. Lo corregí. –

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

Lo desaconsecaría más arriba ya que esto cargaría todos los registros populares solo para comprobar que el elemento sea popular. Tal vez 'self.class.popular.exists? (Id)' podría funcionar –

+2

@ThongKuah, también hay otro problema con todas las soluciones similares: el método puede devolver resultados incorrectos cuando el objeto está en un estado 'sucio' y 'views' o' avg_rating 'se cambia pero no se guarda – Alexis

+1

Siempre hay un lugar para aprender en SO. TY por los comentarios! :) – fuzzyalej

Cuestiones relacionadas