2014-07-07 4 views
4

레일이 여전히이 유형의 관계를 지원하지 않는 것처럼 보이고 ActiveRecord :: HasManyThroughAssociationPolymorphicThroughError 오류가 발생합니다.다형성 has_many를 통한 ActiveRecord has_many

이러한 종류의 관계를 구현하려면 어떻게해야합니까?

Users 1..n Articles 
Categories n..n Articles 
Projects 1..n Articles 

그리고 여기에 서브 스크립 션 모델

Subscription 1..1 User 
Subscription 1..1 Target (polymorphic (Article, Category or User)) 

내가 사용자 # 가입에 따라 가입 # 목표 # 기사를 통해 기사를 선택해야합니다

나는 다음과 같은 연결을 가지고있다.

나는 협회 클래스의 인스턴스를 얻으려면 이상적이

을 구현하는 뜨거운 아무 생각이

업데이트 한 다음

는하자가 USER_1 4를 가지고 말을

작은 예를하다 구독 기록 :

s1 = (user_id: 1, target_id: 3, target_type: 'User') 
s2 = (user_id: 1, target_id: 2, target_type: 'Category') 
s3 = (user_id: 1, target_id: 3, target_type: 'Project') 
s4 = (user_id: 1, target_id: 8, target_type: 'Project') 

나는 User # feed_articles 메소드가 필요합니다.이 메소드는 구독 한 모든 타겟에 속한 모든 기사를 가져옵니다.

user_1.feed_articles.order(created_at: :desc).limit(10) 

업데이트 2

나는 사용자 모델 유형에 따라 기사의 소스를 분리 :

has_many :out_subscriptions, class_name: 'Subscription' 

    has_many :followes_users, through: :out_subscriptions, source: :target, source_type: 'User' 
    has_many :followes_categories, through: :out_subscriptions, source: :target, source_type: 'Category' 
    has_many :followes_projects, through: :out_subscriptions, source: :target, source_type: 'Project' 

    has_many :feed_user_articles, class_name: 'Article', through: :followes_users, source: :articles 
    has_many :feed_category_articles, class_name: 'Article', through: :followes_categories, source: :articles 
    has_many :feed_project_articles, class_name: 'Article', through: :followes_projects, source: :articles 

하지만 어떻게 perfomance의 손실없이 feed_category_articles 및 feed_project_articles와 feed_user_articles을 병합 할 수 있습니다

업데이트 3.1

유일한 방법은 원시 SQL 조인 쿼리를 사용하는 것입니다. 제대로 작동하는 것 같지만 잘 모르겠습니다.

def feed_articles 
    join_clause = <<JOIN 
inner join users on articles.user_id = users.id 
inner join articles_categories on articles_categories.article_id = articles.id 
inner join categories on categories.id = articles_categories.category_id 
inner join subscriptions on 
    (subscriptions.target_id = users.id and subscriptions.target_type = 'User') or 
    (subscriptions.target_id = categories.id and subscriptions.target_type = 'Category') 
JOIN 

    Article.joins(join_clause).where('subscriptions.user_id' => id).distinct 
    end 

(이것은 단지 사용자 및 카테고리입니다)

그것은 범위 및 기타 기능을 지원합니다. 유일한 관심사는이 검색어로 인해 약간의 바람직하지 않은 영향을 미치나요?

+0

그래서 주어진 사용자가 구독 한 모든 기사를 원하십니까? – nicooga

+0

예, 정확하게 그 것입니다. – atomAltera

+0

ActiveRecord dsl 만 사용하여 원하는 표준 솔루션은 없습니다. 내 솔루션은 관계와 동일한 방식으로 작동합니다 (두 번째 편집 참조). – nicooga

답변

0

UNION ALL 멀티 쿼리를 사용하는 DB 성능이 다형성 다중 조인보다 더 효율적이라고 생각합니다. 또한 더 읽기 쉬울 것입니다. 나는 Arel 쿼리를 예제로 작성하려고 시도했지만 좋지 않습니다. (나는 order by 절을 제대로 만들지 못했습니다.) 그래서 원시 SQL을 사용하여 작성해야한다고 생각합니다. ORDER BY 절과 별도로 SQL 템플리트를 사용하여이를 건조시킬 수 있습니다.

+0

order by 절에 대해서는 union의 끝에 넣었습니까? 예를 들어 노동 조합의 각 부분마다 하나의 순서가 아닙니다. 이것은 내가 노동 조합 sql 문을 작성한 마지막 시간에 나를 망 쳤다. (nb : 마지막으로 SQL을 작성한 적이 있는데, postgresql og mysql에서 동작이 다른지 알 수 없습니다.) –

+0

@ OleHenrikSkogstrøm SQL 표준에 따르면 ORDER BY 절은 모든 공용체 뒤에 있어야합니다. 그러나 Arel은 그렇게 할 수 없습니다. 나는 분리 된 SQL과 ORDER BY 절을 추천한다. 그래서 당신은 다른 순서로 하나의 SQL을 사용할 수있다. –

0

레일스가 has_many : through/polymorphic 연관을 지원하지 않는다는 것이 맞습니다. User 클래스에 인스턴스 메서드를 정의하여이 동작을 모방 할 수 있습니다.그러면 다음과 같이 보일 것입니다 :

def articles 
    Article. 
    joins("join subscriptions on subscriptions.target_id = articles.id and subscriptions.target_type = 'Article'"). 
    joins("join users on users.id = subscriptions.user_id") 
end 
관련 문제