¿Hay alguna buena manera de SECAR la duplicación de lógica de predicado / alcance?

For example, consider the following code (in a model):

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

First condition is SQL, second one is ruby, but still, there's an obvious duplication. Is there any good way to DRY it up? What is best practice for such cases?

preguntado el 01 de febrero de 12 a las 22:02

2 Respuestas

There are good reasons to have both so I might consider this (all in model):

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

Respondido 17 ago 15, 14:08

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

Respondido 02 Feb 12, 14:02

Would advise against above as this would load up all popular records just to check the one item is popular. Maybe self.class.popular.exists?(id) Podría funcionar - Tanga Kuah

@ThongKuah there's also another problem with all similar solutions - the method may possibly return wrong result when object is in a 'dirty' and views or avg_rating is changed but not saved - Alexis

There is always a place for learning in SO. TY for the comments! :) - fuzzyalej

@Alexis yeah I realised that soon after :) - Tanga Kuah

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.