2011-11-23 11 views
11

tratando de hacer un alcance en rails3.rails3 alcance para el recuento de niños en la relación has_many

:book has_many :chapters 

Quiero alcance: tiempo para devolver los libros con> 10 capítulos.

¿Cuál es la mejor manera de estructurar este alcance (sin el uso de la memoria caché del contador)?

gracias!

+0

¿por qué no hay caché en el contador? –

+0

¿Puede describir/publicar con la base de datos que está utilizando? Creo que esto está causando cierta confusión en las respuestas a continuación –

Respuesta

19

Esto debe conseguir que va:

class Book 
    scope :long, joins(:chapters). 
       select('books.id, count(chapters.id) as n_chapters'). 
       group('books.id'). 
       having('n_chapters > 10') 
end 

¿Ayuda?

+0

Este es el camino a seguir. El único problema que encuentro es que el método de recuento no funciona como se espera aquí. Por ejemplo, Book.long.count devuelve un hash con el recuento de capítulos para cada libro, creo. Tienes que hacer Book.long.all.count. No está mal, creo que –

+3

Parece correcto pero me aparece un error: 'column' card_count 'does not exists' (card_count is my n_chapters). Todo por 'having' parece funcionar correctamente, y la columna card_count definitivamente está poblada cuando la ejecuto directamente en una consola SQL ... –

+0

No estoy seguro si es una buena práctica vincular otras publicaciones de stackoverflow. Pero tengo un problema similar a este post pero solo requiere ciertos atributos en los objetos has_many. Realmente apreciaría la ayuda http://stackoverflow.com/questions/31719184/rails-active-record-find-all-records-which-have-a-count-on-has-many-associati –

8

Ah - para responder a mi propia pregunta en el comentario anterior, que tenía que poner la cuenta en la que presenta:

class Book 
    scope :long, joins(:chapters). 
    select('books.id'). 
    group('books.id'). 
    having('count(chapters.id) > 10') 
end 
1

en Rails 4.0 Esta versión funciona. Tienes que contar() en la cláusula having. Parece que teniendo cláusula no se ve 'como n_chapters'.

0

Una alternativa es hacer una subconsulta. Si bien la unión es más correcta (y posiblemente también conduzca a un mejor rendimiento), puede terminar con resultados extraños si combina múltiples ámbitos que intentan agrupar. Una subconsulta es mucho menos intrusiva. Para este ejemplo, sería algo así como:

class Book 
    scope :with_chapters_count, -> { 
    select('books.*'). 
    select('(select count(chapters.id) from chapters where chapters.book_id = books.id) as chapters_count') 
    } 
    scope :long, -> { 
    with_chapters_count.where("chapters_count > 10") 
    } 
end 
Cuestiones relacionadas