2011-11-23 13 views
11

próbuje zrobić zakres w szynach3.rails3 zakres dla liczby dzieci w has_many związku

:book has_many :chapters 

Chcę zakresu: długo, aby zwrócić książki z> 10 rozdziałów.

Jak najlepiej zorganizować ten zakres (bez użycia licznika pamięci podręcznej)?

dziękuję!

+0

dlaczego nie licznik pamięci podręcznej? –

+0

Czy możesz opisać/wpis z bazą danych, z której korzystasz? Wierzę, że powoduje to pewne zamieszanie w odpowiedziach poniżej: –

Odpowiedz

19

To powinno Ci będzie:

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

Czy to pomoże?

+0

To jest droga. Jedynym problemem, który napotykam, jest to, że metoda liczenia nie działa tak, jak się spodziewano. Na przykład, Book.long.count zwraca hasz o liczbie rozdziałów dla każdej książki, jak sądzę. Musisz zrobić Book.long.all.count. Nie jest tak źle, chyba –

+3

To wygląda dobrze, ale dostaję błąd: 'column' card_count "nie istnieje" (card_count to moje n_chapters). Wszystko przez 'posiadające' wydaje się działać poprawnie, a kolumna card_count jest zdecydowanie wypełniona, gdy uruchomię to bezpośrednio w konsoli SQL ... –

+0

Nie jestem pewien, czy to dobra praktyka, aby połączyć inne stackoverflow posty. Ale mam podobny problem do tego posta, ale wymaga on tylko pewnych atrybutów na has_many obiektów. Naprawdę doceniłbym pomoc http://stackoverflow.com/questions/31719184/rails-active-record-find-all-records-which-have-a-count-on-h-many-many-associati –

8

Ah - aby odpowiedzieć na moje własne pytanie w komentarzu powyżej, musiałem liczyć w HAVING:

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

w szynach 4,0 Ta wersja dzieła. Musisz liczyć() w klauzuli ma. Wydaje się, że klauzula posiadania nie widzi "jako n_chapterów".

0

Alternatywą jest wykonanie podkwerendy. Podczas gdy sprzężenie jest bardziej poprawne (i prawdopodobnie również prowadzi do lepszej wydajności), możesz uzyskać dziwne wyniki, jeśli połączysz wiele zakresów, które próbują grupować. Podzapytowanie jest znacznie mniej inwazyjne. Dla tego przykładu będzie to coś w rodzaju:

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 
Powiązane problemy