2014-04-01 2 views
0

AlbumSong 클래스 사이에 일대 다 관계가 있다고 가정합니다. 앨범에서 복잡한 필터링을 수행하고 해당 노래를 검색하고 싶습니다.ActiveRecord에서 테이블과 필터링 된 테이블에 합치기

의 내가 현재

SELECT * 
FROM songs 
WHERE album_id IN (1, 5, 34, 92, ..., 2392); 

같은 쿼리를 생성

Song.where(album_id: filtered_albums.pluck_id) 

를 사용하고 노래를 검색하기 위해, 이제 앨범

filtered_albums = Album.where('released_on >= ?', from) 
         .where('rating > ?', rating) 
         .where(genre: genres) 

를 필터링 할 수있는 매우 간단한 방법을 가정 해 봅시다 두 개의 쿼리가 필요하기 때문에 (하나는 앨범 ID를 추출하고 다른 하나는 노래를 얻기 위해) 이것은 ver 일 수 있습니다 비효율적이다.

ActiveRecord는 테이블을 조인하는 것을 허용합니다. Songs.joins(:albums),하지만 난 Songs.joins(filtered_albums) 같은 것을 할 방법을 찾지 못했습니다. 먼저 ID를 "제거"하지 않고 조인을 수행하는 다른 방법이 있습니까?

답변

1

join을 사용하면 원하는 결과를 얻을 수 있습니다.

Song.joins(:album).where('albums.released_on >= ?', from) 
        .where('albums.rating > ?', rating) 
        .where(albums: {genre: genres}) 

joins 메서드는 연관을 인수로 사용합니다. 내 말은, 조인 메소드에서 전달하는 것은 모델에 정의 된 연결 이름이어야하며, 그렇지 않으면 오류가 발생합니다.

당신이 joins에서 범위를 사용하고자하는 즉, Album 모델 자체에서 필터 방식을 유지하려면

편집 할 수 있습니다. 그러면 다음과 같이 처리 할 수 ​​있습니다.

Song.joins(:album).merge(Album.filtered_albums) 

또한 filtered_albums를 명명 된 범위로 정의 할 수 있습니다. 따라서 앨범 모델에서 다음과 같이 정의하십시오 :

scope :filtered_albums, ->(from, rating, genres){ where('released_on >= ?', from) 
        .where('rating > ?', rating).where(albums: {genre: genres}) } 

또는 클래스 메소드로 정의하십시오.

+0

감사합니다. @Manoj. 이 작동합니다. 나는 자신의 클래스에있는 앨범 필터링을 유지하고 싶습니다. 위의 게시물에 대한 내 의견을 참조하십시오. – sakovias

+0

나는 당신이 가지고있는 요구 사항에 맞게 나의 대답을 편집했습니다 :) –

+0

당신은 저의 하루를 만들어 줬습니다, 고마워요! 병합 메서드는 정확히 내가 뭘 찾고 있었는지 :) 사실, 그것은 가장 보잘것없는 ActiveRecord 중 하나입니다 : [this]에 따른 관계 메소드 (http://blog.mitchcrowe.com/blog/2012/04/14/ 10-most-underused-activerecord-relation-methods /) 포스트! – sakovias

1

당신은 같은 것을 할 수 있습니다

Song.joins(:albums).where('albums.released_on >= ?', from).where('albums.rating > ?', rating).where('albums.genre = ?', genres) 

그것은 단지 하나의 쿼리를합니다.

+0

감사합니다. 내 문제는, 그러나 필터 메서드는 앨범 클래스에 살고 (여기에 지정하지 않은 옵션 인수가 많이 걸립니다), 노래 찾기는 Song 클래스에 있습니다. 따라서 본질적으로 ActiveRecord :: Relation 객체 (필터링 된 앨범)와 노래 테이블에 참여하는 문제입니다. 어쩌면 내 응용 프로그램 설계의 문제 일 수 있습니다. – sakovias

관련 문제